From 2df9344be5bf1c65daae2ca7ea47982fe2a1c2fb Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 16 May 2017 10:27:41 -0700 Subject: Rename tx manager to tx controller --- app/scripts/controllers/transactions.js | 404 ++++++++++++++++++++++++++++++++ 1 file changed, 404 insertions(+) create mode 100644 app/scripts/controllers/transactions.js (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js new file mode 100644 index 000000000..9f267160f --- /dev/null +++ b/app/scripts/controllers/transactions.js @@ -0,0 +1,404 @@ +const EventEmitter = require('events') +const async = require('async') +const extend = require('xtend') +const Semaphore = require('semaphore') +const ObservableStore = require('obs-store') +const ethUtil = require('ethereumjs-util') +const EthQuery = require('eth-query') +const TxProviderUtil = require('./lib/tx-utils') +const createId = require('./lib/random-id') + +module.exports = class TransactionManager extends EventEmitter { + constructor (opts) { + super() + this.store = new ObservableStore(extend({ + transactions: [], + }, opts.initState)) + this.memStore = new ObservableStore({}) + this.networkStore = opts.networkStore || new ObservableStore({}) + this.preferencesStore = opts.preferencesStore || new ObservableStore({}) + this.txHistoryLimit = opts.txHistoryLimit + this.provider = opts.provider + this.blockTracker = opts.blockTracker + this.query = new EthQuery(this.provider) + this.txProviderUtils = new TxProviderUtil(this.provider) + this.blockTracker.on('block', this.checkForTxInBlock.bind(this)) + this.signEthTx = opts.signTransaction + this.nonceLock = Semaphore(1) + + // memstore is computed from a few different stores + this._updateMemstore() + this.store.subscribe(() => this._updateMemstore()) + this.networkStore.subscribe(() => this._updateMemstore()) + this.preferencesStore.subscribe(() => this._updateMemstore()) + } + + getState () { + return this.memStore.getState() + } + + getNetwork () { + return this.networkStore.getState().network + } + + getSelectedAddress () { + return this.preferencesStore.getState().selectedAddress + } + + // Returns the tx list + getTxList () { + const network = this.getNetwork() + const fullTxList = this.getFullTxList() + return fullTxList.filter(txMeta => txMeta.metamaskNetworkId === network) + } + + // Returns the number of txs for the current network. + getTxCount () { + return this.getTxList().length + } + + // Returns the full tx list across all networks + getFullTxList () { + return this.store.getState().transactions + } + + // Adds a tx to the txlist + addTx (txMeta) { + const txCount = this.getTxCount() + const network = this.getNetwork() + const fullTxList = this.getFullTxList() + const txHistoryLimit = this.txHistoryLimit + + // checks if the length of the tx history is + // longer then desired persistence limit + // and then if it is removes only confirmed + // or rejected tx's. + // not tx's that are pending or unapproved + if (txCount > txHistoryLimit - 1) { + var index = fullTxList.findIndex((metaTx) => ((metaTx.status === 'confirmed' || metaTx.status === 'rejected') && network === txMeta.metamaskNetworkId)) + fullTxList.splice(index, 1) + } + fullTxList.push(txMeta) + this._saveTxList(fullTxList) + this.emit('update') + + this.once(`${txMeta.id}:signed`, function (txId) { + this.removeAllListeners(`${txMeta.id}:rejected`) + }) + this.once(`${txMeta.id}:rejected`, function (txId) { + this.removeAllListeners(`${txMeta.id}:signed`) + }) + + this.emit('updateBadge') + this.emit(`${txMeta.id}:unapproved`, txMeta) + } + + // gets tx by Id and returns it + getTx (txId, cb) { + var txList = this.getTxList() + var txMeta = txList.find(txData => txData.id === txId) + return cb ? cb(txMeta) : txMeta + } + + // + updateTx (txMeta) { + var txId = txMeta.id + var txList = this.getFullTxList() + var index = txList.findIndex(txData => txData.id === txId) + txList[index] = txMeta + this._saveTxList(txList) + this.emit('update') + } + + get unapprovedTxCount () { + return Object.keys(this.getUnapprovedTxList()).length + } + + get pendingTxCount () { + return this.getTxsByMetaData('status', 'signed').length + } + + addUnapprovedTransaction (txParams, done) { + let txMeta + async.waterfall([ + // validate + (cb) => this.txProviderUtils.validateTxParams(txParams, cb), + // construct txMeta + (cb) => { + txMeta = { + id: createId(), + time: (new Date()).getTime(), + status: 'unapproved', + metamaskNetworkId: this.getNetwork(), + txParams: txParams, + } + cb() + }, + // add default tx params + (cb) => this.addTxDefaults(txMeta, cb), + // save txMeta + (cb) => { + this.addTx(txMeta) + cb(null, txMeta) + }, + ], done) + } + + addTxDefaults (txMeta, cb) { + 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) + }) + } + + getUnapprovedTxList () { + var txList = this.getTxList() + return txList.filter((txMeta) => txMeta.status === 'unapproved') + .reduce((result, tx) => { + result[tx.id] = tx + return result + }, {}) + } + + approveTransaction (txId, cb = warn) { + const self = this + // approve + self.setTxStatusApproved(txId) + // only allow one tx at a time for atomic nonce usage + self.nonceLock.take(() => { + // begin signature process + async.waterfall([ + (cb) => self.fillInTxParams(txId, cb), + (cb) => self.signTransaction(txId, cb), + (rawTx, cb) => self.publishTransaction(txId, rawTx, cb), + ], (err) => { + self.nonceLock.leave() + if (err) { + this.setTxStatusFailed(txId, { + errCode: err.errCode || err, + message: err.message || 'Transaction failed during approval', + }) + return cb(err) + } + cb() + }) + }) + } + + cancelTransaction (txId, cb = warn) { + this.setTxStatusRejected(txId) + cb() + } + + fillInTxParams (txId, cb) { + const txMeta = this.getTx(txId) + this.txProviderUtils.fillInTxParams(txMeta.txParams, (err) => { + if (err) return cb(err) + this.updateTx(txMeta) + cb() + }) + } + + getChainId () { + const networkState = this.networkStore.getState() + const getChainId = parseInt(networkState.network) + if (Number.isNaN(getChainId)) { + return 0 + } else { + return getChainId + } + } + + signTransaction (txId, cb) { + const txMeta = this.getTx(txId) + const txParams = txMeta.txParams + const fromAddress = txParams.from + // add network/chain id + txParams.chainId = this.getChainId() + const ethTx = this.txProviderUtils.buildEthTxFromParams(txParams) + this.signEthTx(ethTx, fromAddress).then(() => { + this.setTxStatusSigned(txMeta.id) + cb(null, ethUtil.bufferToHex(ethTx.serialize())) + }).catch((err) => { + cb(err) + }) + } + + publishTransaction (txId, rawTx, cb) { + this.txProviderUtils.publishTransaction(rawTx, (err, txHash) => { + if (err) return cb(err) + this.setTxHash(txId, txHash) + this.setTxStatusSubmitted(txId) + cb() + }) + } + + // receives a txHash records the tx as signed + setTxHash (txId, txHash) { + // Add the tx hash to the persisted meta-tx object + const txMeta = this.getTx(txId) + txMeta.hash = txHash + this.updateTx(txMeta) + } + + /* + Takes an object of fields to search for eg: + var thingsToLookFor = { + to: '0x0..', + from: '0x0..', + status: 'signed', + } + and returns a list of tx with all + options matching + + this is for things like filtering a the tx list + for only tx's from 1 account + or for filltering for all txs from one account + and that have been 'confirmed' + */ + getFilteredTxList (opts) { + var filteredTxList + Object.keys(opts).forEach((key) => { + filteredTxList = this.getTxsByMetaData(key, opts[key], filteredTxList) + }) + return filteredTxList + } + + getTxsByMetaData (key, value, txList = this.getTxList()) { + return txList.filter((txMeta) => { + if (txMeta.txParams[key]) { + return txMeta.txParams[key] === value + } else { + return txMeta[key] === value + } + }) + } + + // STATUS METHODS + // get::set status + + // should return the status of the tx. + getTxStatus (txId) { + const txMeta = this.getTx(txId) + return txMeta.status + } + + // should update the status of the tx to 'rejected'. + setTxStatusRejected (txId) { + this._setTxStatus(txId, 'rejected') + } + + // should update the status of the tx to 'approved'. + setTxStatusApproved (txId) { + this._setTxStatus(txId, 'approved') + } + + // should update the status of the tx to 'signed'. + setTxStatusSigned (txId) { + this._setTxStatus(txId, 'signed') + } + + // should update the status of the tx to 'submitted'. + setTxStatusSubmitted (txId) { + this._setTxStatus(txId, 'submitted') + } + + // should update the status of the tx to 'confirmed'. + setTxStatusConfirmed (txId) { + this._setTxStatus(txId, 'confirmed') + } + + setTxStatusFailed (txId, reason) { + const txMeta = this.getTx(txId) + txMeta.err = reason + this.updateTx(txMeta) + this._setTxStatus(txId, 'failed') + } + + // merges txParams obj onto txData.txParams + // use extend to ensure that all fields are filled + updateTxParams (txId, txParams) { + var txMeta = this.getTx(txId) + txMeta.txParams = extend(txMeta.txParams, txParams) + this.updateTx(txMeta) + } + + // checks if a signed tx is in a block and + // if included sets the tx status as 'confirmed' + checkForTxInBlock () { + var signedTxList = this.getFilteredTxList({status: 'submitted'}) + if (!signedTxList.length) return + signedTxList.forEach((txMeta) => { + var txHash = txMeta.hash + var txId = txMeta.id + if (!txHash) { + const errReason = { + errCode: 'No hash was provided', + message: 'We had an error while submitting this transaction, please try again.', + } + return this.setTxStatusFailed(txId, errReason) + } + this.query.getTransactionByHash(txHash, (err, txParams) => { + if (err || !txParams) { + if (!txParams) return + txMeta.err = { + isWarning: true, + errorCode: err, + message: 'There was a problem loading this transaction.', + } + this.updateTx(txMeta) + return console.error(err) + } + if (txParams.blockNumber) { + this.setTxStatusConfirmed(txId) + } + }) + }) + } + + // PRIVATE METHODS + + // Should find the tx in the tx list and + // update it. + // should set the status in txData + // - `'unapproved'` the user has not responded + // - `'rejected'` the user has responded no! + // - `'approved'` the user has approved the tx + // - `'signed'` the tx is signed + // - `'submitted'` the tx is sent to a server + // - `'confirmed'` the tx has been included in a block. + _setTxStatus (txId, status) { + var txMeta = this.getTx(txId) + txMeta.status = status + this.emit(`${txMeta.id}:${status}`, txId) + if (status === 'submitted' || status === 'rejected') { + this.emit(`${txMeta.id}:finished`, txMeta) + } + this.updateTx(txMeta) + this.emit('updateBadge') + } + + // Saves the new/updated txList. + // Function is intended only for internal use + _saveTxList (transactions) { + this.store.updateState({ transactions }) + } + + _updateMemstore () { + const unapprovedTxs = this.getUnapprovedTxList() + const selectedAddressTxList = this.getFilteredTxList({ + from: this.getSelectedAddress(), + metamaskNetworkId: this.getNetwork(), + }) + this.memStore.updateState({ unapprovedTxs, selectedAddressTxList }) + } +} + + +const warn = () => console.warn('warn was used no cb provided') -- cgit v1.2.3 From 68d6ea44a0c9f3d75415ccadefe182f9a0872db1 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 16 May 2017 11:39:00 -0700 Subject: Fix path references --- app/scripts/controllers/transactions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 9f267160f..21dd25b30 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -5,8 +5,8 @@ const Semaphore = require('semaphore') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') const EthQuery = require('eth-query') -const TxProviderUtil = require('./lib/tx-utils') -const createId = require('./lib/random-id') +const TxProviderUtil = require('../lib/tx-utils') +const createId = require('../lib/random-id') module.exports = class TransactionManager extends EventEmitter { constructor (opts) { -- cgit v1.2.3 From 529304c005318852b60bb93846a58d6eb3da2066 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 23 May 2017 01:56:10 -0400 Subject: Wrap the provider in a proxy --- app/scripts/controllers/transactions.js | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index cfeeab6e6..b9bea2f1c 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -4,7 +4,6 @@ const extend = require('xtend') const Semaphore = require('semaphore') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') -const EthQuery = require('eth-query') const TxProviderUtil = require('../lib/tx-utils') const createId = require('../lib/random-id') @@ -18,11 +17,13 @@ module.exports = class TransactionManager extends EventEmitter { this.networkStore = opts.networkStore || new ObservableStore({}) this.preferencesStore = opts.preferencesStore || new ObservableStore({}) this.txHistoryLimit = opts.txHistoryLimit - this.setupProviderAndEthQuery({ - provider: opts.provider, - blockTracker: opts.blockTracker, - ethQuery: opts.ethQuery, - }) + this.provider = opts.provider + this.blockTracker = opts.blockTracker + this.query = opts.ethQuery + this.txProviderUtils = new TxProviderUtil(this.query) + this.networkStore.subscribe((_) => this.blockTracker.on('block', this.checkForTxInBlock.bind(this))) + this.blockTracker.on('block', this.checkForTxInBlock.bind(this)) + this.signEthTx = opts.signTransaction this.nonceLock = Semaphore(1) @@ -41,20 +42,6 @@ module.exports = class TransactionManager extends EventEmitter { return this.networkStore.getState().network } - setupProviderAndEthQuery ({provider, blockTracker, ethQuery}) { - if (this.provider) { - delete this.provider - delete this.blockTracker - delete this.query - delete this.txProviderUtils - } - this.provider = provider - this.query = ethQuery - this.txProviderUtils = new TxProviderUtil(ethQuery) - blockTracker ? this.blockTracker = blockTracker : this.blockTracker = provider - this.blockTracker.on('block', this.checkForTxInBlock.bind(this)) - } - getSelectedAddress () { return this.preferencesStore.getState().selectedAddress } -- cgit v1.2.3 From cd2ad1733da16aa3d84158e5df9fbf33f51450aa Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 23 May 2017 11:49:25 -0700 Subject: Continually resubmit pending txs --- app/scripts/controllers/transactions.js | 54 +++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 21dd25b30..3d86a171e 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -7,6 +7,10 @@ const ethUtil = require('ethereumjs-util') const EthQuery = require('eth-query') const TxProviderUtil = require('../lib/tx-utils') const createId = require('../lib/random-id') +const denodeify = require('denodeify') + +const RETRY_LIMIT = 200 +const RESUBMIT_INTERVAL = 10000 // Ten seconds module.exports = class TransactionManager extends EventEmitter { constructor (opts) { @@ -31,6 +35,8 @@ module.exports = class TransactionManager extends EventEmitter { this.store.subscribe(() => this._updateMemstore()) this.networkStore.subscribe(() => this._updateMemstore()) this.preferencesStore.subscribe(() => this._updateMemstore()) + + this.continuallyResubmitPendingTxs() } getState () { @@ -230,7 +236,11 @@ module.exports = class TransactionManager extends EventEmitter { }) } - publishTransaction (txId, rawTx, cb) { + publishTransaction (txId, rawTx, cb = warn) { + const txMeta = this.getTx(txId) + txMeta.rawTx = rawTx + this.updateTx(txMeta) + this.txProviderUtils.publishTransaction(rawTx, (err, txHash) => { if (err) return cb(err) this.setTxHash(txId, txHash) @@ -353,7 +363,7 @@ module.exports = class TransactionManager extends EventEmitter { message: 'There was a problem loading this transaction.', } this.updateTx(txMeta) - return console.error(err) + return log.error(err) } if (txParams.blockNumber) { this.setTxStatusConfirmed(txId) @@ -379,6 +389,7 @@ module.exports = class TransactionManager extends EventEmitter { this.emit(`${txMeta.id}:${status}`, txId) if (status === 'submitted' || status === 'rejected') { this.emit(`${txMeta.id}:finished`, txMeta) + } this.updateTx(txMeta) this.emit('updateBadge') @@ -398,6 +409,45 @@ module.exports = class TransactionManager extends EventEmitter { }) this.memStore.updateState({ unapprovedTxs, selectedAddressTxList }) } + + continuallyResubmitPendingTxs () { + const pending = this.getTxsByMetaData('status', 'submitted') + const resubmit = denodeify(this.resubmitTx.bind(this)) + Promise.all(pending.map(txMeta => resubmit(txMeta))) + .catch((reason) => { + log.info('Problem resubmitting tx', reason) + }) + .then(() => { + global.setTimeout(() => { + this.continuallyResubmitPendingTxs() + }, RESUBMIT_INTERVAL) + }) + } + + resubmitTx (txMeta, cb) { + // Increment a try counter. + if (!('retryCount' in txMeta)) { + txMeta.retryCount = 0 + } + + // Only auto-submit already-signed txs: + if (!('rawTx' in txMeta)) { + return cb() + } + + if (txMeta.retryCount > RETRY_LIMIT) { + txMeta.err = { + isWarning: true, + message: 'Gave up submitting tx.', + } + this.updateTx(txMeta) + return log.error(txMeta.err.message) + } + + txMeta.retryCount++ + const rawTx = txMeta.rawTx + this.txProviderUtils.publishTransaction(rawTx, cb) + } } -- cgit v1.2.3 From e4d09aebf470f9c014f2b658ccf5042a3995d708 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 23 May 2017 14:49:10 -0700 Subject: Cleanup --- app/scripts/controllers/transactions.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 3d86a171e..4d3197cba 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -12,7 +12,7 @@ const denodeify = require('denodeify') const RETRY_LIMIT = 200 const RESUBMIT_INTERVAL = 10000 // Ten seconds -module.exports = class TransactionManager extends EventEmitter { +module.exports = class TransactionController extends EventEmitter { constructor (opts) { super() this.store = new ObservableStore(extend({ @@ -448,7 +448,8 @@ module.exports = class TransactionManager extends EventEmitter { const rawTx = txMeta.rawTx this.txProviderUtils.publishTransaction(rawTx, cb) } + } -const warn = () => console.warn('warn was used no cb provided') +const warn = () => log.warn('warn was used no cb provided') -- cgit v1.2.3 From 243eeff7cb0d4c5d613a9250d234f81fdccbbf15 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 23 May 2017 02:12:28 -0400 Subject: Fix for tests --- app/scripts/controllers/transactions.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index b9bea2f1c..2ebeed3ab 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -21,9 +21,7 @@ module.exports = class TransactionManager extends EventEmitter { this.blockTracker = opts.blockTracker this.query = opts.ethQuery this.txProviderUtils = new TxProviderUtil(this.query) - this.networkStore.subscribe((_) => this.blockTracker.on('block', this.checkForTxInBlock.bind(this))) this.blockTracker.on('block', this.checkForTxInBlock.bind(this)) - this.signEthTx = opts.signTransaction this.nonceLock = Semaphore(1) @@ -39,7 +37,7 @@ module.exports = class TransactionManager extends EventEmitter { } getNetwork () { - return this.networkStore.getState().network + return this.networkStore.getState() } getSelectedAddress () { -- cgit v1.2.3 From 96fa29ffbce841977ae02acaba2d8114436262d4 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Mon, 12 Jun 2017 16:11:37 -0700 Subject: put tx resubmission on the block event --- app/scripts/controllers/transactions.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index faccf1ab1..bf24523cc 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -9,7 +9,6 @@ const createId = require('../lib/random-id') const denodeify = require('denodeify') const RETRY_LIMIT = 200 -const RESUBMIT_INTERVAL = 10000 // Ten seconds module.exports = class TransactionController extends EventEmitter { constructor (opts) { @@ -26,6 +25,7 @@ module.exports = class TransactionController extends EventEmitter { this.query = opts.ethQuery this.txProviderUtils = new TxProviderUtil(this.query) this.blockTracker.on('block', this.checkForTxInBlock.bind(this)) + this.blockTracker.on('block', this.continuallyResubmitPendingTxs.bind(this)) this.signEthTx = opts.signTransaction this.nonceLock = Semaphore(1) @@ -34,8 +34,6 @@ module.exports = class TransactionController extends EventEmitter { this.store.subscribe(() => this._updateMemstore()) this.networkStore.subscribe(() => this._updateMemstore()) this.preferencesStore.subscribe(() => this._updateMemstore()) - - this.continuallyResubmitPendingTxs() } getState () { @@ -411,16 +409,13 @@ module.exports = class TransactionController extends EventEmitter { continuallyResubmitPendingTxs () { const pending = this.getTxsByMetaData('status', 'submitted') + // 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))) .catch((reason) => { log.info('Problem resubmitting tx', reason) }) - .then(() => { - global.setTimeout(() => { - this.continuallyResubmitPendingTxs() - }, RESUBMIT_INTERVAL) - }) } resubmitTx (txMeta, cb) { -- cgit v1.2.3 From ae7c296669ad5c81e85071de071e2b0f2b1d4463 Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Mon, 12 Jun 2017 17:44:11 -0700 Subject: Fix networkState in chain id --- app/scripts/controllers/transactions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index faccf1ab1..d4603aafa 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -212,7 +212,7 @@ module.exports = class TransactionController extends EventEmitter { getChainId () { const networkState = this.networkStore.getState() - const getChainId = parseInt(networkState.network) + const getChainId = parseInt(networkState) if (Number.isNaN(getChainId)) { return 0 } else { -- cgit v1.2.3 From ec3383c16275f8d4594323b7b4ec38b447844e68 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 13 Jun 2017 09:50:01 -0700 Subject: rename continuallyResubmitPendingTxs to resubmitPendingTxs --- app/scripts/controllers/transactions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index bf24523cc..9f621747f 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -25,7 +25,7 @@ module.exports = class TransactionController extends EventEmitter { this.query = opts.ethQuery this.txProviderUtils = new TxProviderUtil(this.query) this.blockTracker.on('block', this.checkForTxInBlock.bind(this)) - this.blockTracker.on('block', this.continuallyResubmitPendingTxs.bind(this)) + this.blockTracker.on('block', this.resubmitPendingTxs.bind(this)) this.signEthTx = opts.signTransaction this.nonceLock = Semaphore(1) @@ -407,7 +407,7 @@ module.exports = class TransactionController extends EventEmitter { this.memStore.updateState({ unapprovedTxs, selectedAddressTxList }) } - continuallyResubmitPendingTxs () { + resubmitPendingTxs () { const pending = this.getTxsByMetaData('status', 'submitted') // only try resubmitting if their are transactions to resubmit if (!pending.length) return -- cgit v1.2.3 From 0fd32e67d4c8e911cd5cd88b81f04d11b2202609 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 14 Jun 2017 12:01:45 -0700 Subject: Do not mark slowly mined txs as failed. Fixes #1567 Also seems to fix #1556 Also improves resubmit performance by only resubmitting on `latest`. --- app/scripts/controllers/transactions.js | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 2db8041eb..931f01855 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -25,7 +25,7 @@ module.exports = class TransactionController extends EventEmitter { this.query = opts.ethQuery this.txProviderUtils = new TxProviderUtil(this.query) this.blockTracker.on('block', this.checkForTxInBlock.bind(this)) - this.blockTracker.on('block', this.resubmitPendingTxs.bind(this)) + this.blockTracker.on('latest', this.resubmitPendingTxs.bind(this)) this.signEthTx = opts.signTransaction this.nonceLock = Semaphore(1) @@ -339,7 +339,7 @@ module.exports = class TransactionController extends EventEmitter { // checks if a signed tx is in a block and // if included sets the tx status as 'confirmed' checkForTxInBlock () { - var signedTxList = this.getFilteredTxList({status: 'submitted'}) + var signedTxList = this.getFilteredTxList({ status: 'submitted' }) if (!signedTxList.length) return signedTxList.forEach((txMeta) => { var txHash = txMeta.hash @@ -430,12 +430,8 @@ module.exports = class TransactionController extends EventEmitter { } if (txMeta.retryCount > RETRY_LIMIT) { - txMeta.err = { - isWarning: true, - message: 'Gave up submitting tx.', - } - this.updateTx(txMeta) - return log.error(txMeta.err.message) + const message = 'Gave up submitting tx ' + txMeta.hash + return log.warning(message) } txMeta.retryCount++ -- cgit v1.2.3 From 6fda78cd2b850c7414d598227a0ef6b4235f241e Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 14 Jun 2017 15:17:46 -0700 Subject: Refresh token balance on network change --- app/scripts/controllers/transactions.js | 1 - 1 file changed, 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 8be73fad8..d546615ed 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -389,7 +389,6 @@ module.exports = class TransactionController extends EventEmitter { this.emit(`${txMeta.id}:${status}`, txId) if (status === 'submitted' || status === 'rejected') { this.emit(`${txMeta.id}:finished`, txMeta) - } this.updateTx(txMeta) this.emit('updateBadge') -- cgit v1.2.3 From 6ae97290f0e744479a41e31507f79309137d94c0 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 14 Jun 2017 16:14:55 -0700 Subject: check for the tx in the block that provider engine gives us --- app/scripts/controllers/transactions.js | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 2db8041eb..71f90c2cd 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -338,12 +338,13 @@ module.exports = class TransactionController extends EventEmitter { // checks if a signed tx is in a block and // if included sets the tx status as 'confirmed' - checkForTxInBlock () { + checkForTxInBlock (block) { var signedTxList = this.getFilteredTxList({status: 'submitted'}) if (!signedTxList.length) return signedTxList.forEach((txMeta) => { var txHash = txMeta.hash var txId = txMeta.id + if (!txHash) { const errReason = { errCode: 'No hash was provided', @@ -351,20 +352,9 @@ module.exports = class TransactionController extends EventEmitter { } return this.setTxStatusFailed(txId, errReason) } - this.query.getTransactionByHash(txHash, (err, txParams) => { - if (err || !txParams) { - if (!txParams) return - txMeta.err = { - isWarning: true, - errorCode: err, - message: 'There was a problem loading this transaction.', - } - this.updateTx(txMeta) - return log.error(err) - } - if (txParams.blockNumber) { - this.setTxStatusConfirmed(txId) - } + + block.transactions.forEach((tx) => { + if (tx.hash === txHash) this.setTxStatusConfirmed(txId) }) }) } -- cgit v1.2.3 From a10740af7e35aa60e0445598403e6bda22382c2f Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 14 Jun 2017 20:17:59 -0700 Subject: add a check for weather a tx is included in a block when jumping blocks --- app/scripts/controllers/transactions.js | 41 +++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 2db8041eb..41f651458 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -26,6 +26,7 @@ module.exports = class TransactionController extends EventEmitter { this.txProviderUtils = new TxProviderUtil(this.query) this.blockTracker.on('block', this.checkForTxInBlock.bind(this)) this.blockTracker.on('block', this.resubmitPendingTxs.bind(this)) + this.provider._blockTracker.on('sync', this.queryPendingTxs.bind(this)) this.signEthTx = opts.signTransaction this.nonceLock = Semaphore(1) @@ -369,6 +370,15 @@ module.exports = class TransactionController extends EventEmitter { }) } + queryPendingTxs ({oldBlock, newBlock}) { + if (!oldBlock) { + this._checkPendingTxs() + return + } + const diff = Number.parseInt(newBlock.number) - Number.parseInt(oldBlock.number) + if (diff > 1) this._checkPendingTxs() + } + // PRIVATE METHODS // Should find the tx in the tx list and @@ -443,6 +453,37 @@ module.exports = class TransactionController extends EventEmitter { this.txProviderUtils.publishTransaction(rawTx, cb) } + _checkPendingTxs () { + var signedTxList = this.getFilteredTxList({status: 'submitted'}) + if (!signedTxList.length) return + signedTxList.forEach((txMeta) => { + var txHash = txMeta.hash + var txId = txMeta.id + if (!txHash) { + const errReason = { + errCode: 'No hash was provided', + message: 'We had an error while submitting this transaction, please try again.', + } + return this.setTxStatusFailed(txId, errReason) + } + this.query.getTransactionByHash(txHash, (err, txParams) => { + if (err || !txParams) { + if (!txParams) return + txMeta.err = { + isWarning: true, + errorCode: err, + message: 'There was a problem loading this transaction.', + } + this.updateTx(txMeta) + return log.error(err) + } + if (txParams.blockNumber) { + this.setTxStatusConfirmed(txId) + } + }) + }) + } + } -- cgit v1.2.3 From 07539a63e4378153778b5bb264aaffad7e46cf34 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 14 Jun 2017 21:52:49 -0700 Subject: remove unnecessary log --- app/scripts/controllers/transactions.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 931f01855..2769a8d59 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -429,10 +429,7 @@ module.exports = class TransactionController extends EventEmitter { return cb() } - if (txMeta.retryCount > RETRY_LIMIT) { - const message = 'Gave up submitting tx ' + txMeta.hash - return log.warning(message) - } + if (txMeta.retryCount > RETRY_LIMIT) return txMeta.retryCount++ const rawTx = txMeta.rawTx -- cgit v1.2.3 From b3492d9c17e62332c17bb082c23db30512e2b881 Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 14 Jun 2017 23:44:02 -0700 Subject: transaction controller - use nonce-tracker --- app/scripts/controllers/transactions.js | 90 +++++++++++++++++++++------------ 1 file changed, 58 insertions(+), 32 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 2db8041eb..e7fe9927e 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -4,9 +4,10 @@ const extend = require('xtend') const Semaphore = require('semaphore') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') +const denodeify = require('denodeify') const TxProviderUtil = require('../lib/tx-utils') const createId = require('../lib/random-id') -const denodeify = require('denodeify') +const NonceTracker = require('../lib/nonce-tracker') const RETRY_LIMIT = 200 @@ -22,6 +23,11 @@ module.exports = class TransactionController extends EventEmitter { this.txHistoryLimit = opts.txHistoryLimit this.provider = opts.provider this.blockTracker = opts.blockTracker + this.nonceTracker = new NonceTracker({ + provider: this.provider, + blockTracker: this.blockTracker, + getPendingTransactions: (address) => this.getFilteredTxList({ from: address, status: 'submitted' }), + }) this.query = opts.ethQuery this.txProviderUtils = new TxProviderUtil(this.query) this.blockTracker.on('block', this.checkForTxInBlock.bind(this)) @@ -169,29 +175,58 @@ module.exports = class TransactionController extends EventEmitter { }, {}) } - approveTransaction (txId, cb = warn) { - const self = this - // approve - self.setTxStatusApproved(txId) - // only allow one tx at a time for atomic nonce usage - self.nonceLock.take(() => { - // begin signature process - async.waterfall([ - (cb) => self.fillInTxParams(txId, cb), - (cb) => self.signTransaction(txId, cb), - (rawTx, cb) => self.publishTransaction(txId, rawTx, cb), - ], (err) => { - self.nonceLock.leave() - if (err) { - this.setTxStatusFailed(txId, { - errCode: err.errCode || err, - message: err.message || 'Transaction failed during approval', - }) - return cb(err) - } - cb() + // approveTransaction (txId, cb = warn) { + // promiseToCallback((async () => { + // // approve + // self.setTxStatusApproved(txId) + // // get next nonce + // const txMeta = this.getTx(txId) + // const fromAddress = txMeta.txParams.from + // const { nextNonce, releaseLock } = await this.nonceTracker.getNonceLock(fromAddress) + // txMeta.txParams.nonce = nonce + // this.updateTx(txMeta) + // // sign transaction + // const rawTx = await denodeify(self.signTransaction.bind(self))(txId) + // await denodeify(self.publishTransaction.bind(self))(txId, rawTx) + // })())((err) => { + // if (err) { + // this.setTxStatusFailed(txId, { + // errCode: err.errCode || err, + // message: err.message || 'Transaction failed during approval', + // }) + // } + // // must set transaction to submitted/failed before releasing lock + // releaseLock() + // cb(err) + // }) + // } + + async approveTransaction (txId) { + let nonceLock + try { + // approve + this.setTxStatusApproved(txId) + // get next nonce + const txMeta = this.getTx(txId) + const fromAddress = txMeta.txParams.from + nonceLock = await this.nonceTracker.getNonceLock(fromAddress) + txMeta.txParams.nonce = nonceLock.nextNonce + this.updateTx(txMeta) + // sign transaction + const rawTx = await denodeify(this.signTransaction.bind(this))(txId) + await denodeify(this.publishTransaction.bind(this))(txId, rawTx) + // must set transaction to submitted/failed before releasing lock + nonceLock.releaseLock() + } catch (err) { + this.setTxStatusFailed(txId, { + errCode: err.errCode || err, + message: err.message || 'Transaction failed during approval', }) - }) + // must set transaction to submitted/failed before releasing lock + if (nonceLock) nonceLock.releaseLock() + // continue with error chain + throw err + } } cancelTransaction (txId, cb = warn) { @@ -199,15 +234,6 @@ module.exports = class TransactionController extends EventEmitter { cb() } - fillInTxParams (txId, cb) { - const txMeta = this.getTx(txId) - this.txProviderUtils.fillInTxParams(txMeta.txParams, (err) => { - if (err) return cb(err) - this.updateTx(txMeta) - cb() - }) - } - getChainId () { const networkState = this.networkStore.getState() const getChainId = parseInt(networkState) -- cgit v1.2.3 From 2e5deef2b0bdaaa67ee1584da52b7001cc9e849b Mon Sep 17 00:00:00 2001 From: frankiebee Date: Thu, 15 Jun 2017 13:48:48 -0700 Subject: check nonce and balance when resubmiting tx --- app/scripts/controllers/transactions.js | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 2769a8d59..58dc8a6ab 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -25,10 +25,10 @@ module.exports = class TransactionController extends EventEmitter { this.query = opts.ethQuery this.txProviderUtils = new TxProviderUtil(this.query) this.blockTracker.on('block', this.checkForTxInBlock.bind(this)) - this.blockTracker.on('latest', this.resubmitPendingTxs.bind(this)) + this.provider._blockTracker.on('latest', this.resubmitPendingTxs.bind(this)) this.signEthTx = opts.signTransaction this.nonceLock = Semaphore(1) - + this.ethStore = opts.ethStore // memstore is computed from a few different stores this._updateMemstore() this.store.subscribe(() => this._updateMemstore()) @@ -411,26 +411,31 @@ module.exports = class TransactionController extends EventEmitter { const pending = this.getTxsByMetaData('status', 'submitted') // only try resubmitting if their are transactions to resubmit if (!pending.length) return - const resubmit = denodeify(this.resubmitTx.bind(this)) + const resubmit = denodeify(this._resubmitTx.bind(this)) Promise.all(pending.map(txMeta => resubmit(txMeta))) .catch((reason) => { log.info('Problem resubmitting tx', reason) }) } - resubmitTx (txMeta, cb) { - // Increment a try counter. - if (!('retryCount' in txMeta)) { - txMeta.retryCount = 0 - } + _resubmitTx (txMeta, cb) { + const address = txMeta.txParams.from + const balance = this.ethStore.getState().accounts[address].balance + const nonce = Number.parseInt(this.ethStore.getState().accounts[address].nonce) + const txNonce = Number.parseInt(txMeta.txParams.nonce) + 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() // Only auto-submit already-signed txs: - if (!('rawTx' in txMeta)) { - return cb() - } + if (!('rawTx' in txMeta)) return cb() if (txMeta.retryCount > RETRY_LIMIT) return + // Increment a try counter. txMeta.retryCount++ const rawTx = txMeta.rawTx this.txProviderUtils.publishTransaction(rawTx, cb) -- cgit v1.2.3 From 27b874f2c48fd1cb9dc0984646cb739173ddaf2c Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 15 Jun 2017 14:08:07 -0700 Subject: transactions controller - add comments --- app/scripts/controllers/transactions.js | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 41f651458..aa168b736 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -26,6 +26,7 @@ module.exports = class TransactionController extends EventEmitter { this.txProviderUtils = new TxProviderUtil(this.query) this.blockTracker.on('block', this.checkForTxInBlock.bind(this)) this.blockTracker.on('block', this.resubmitPendingTxs.bind(this)) + // provider-engine only exploses the 'block' event, not 'latest' for 'sync' this.provider._blockTracker.on('sync', this.queryPendingTxs.bind(this)) this.signEthTx = opts.signTransaction this.nonceLock = Semaphore(1) @@ -371,10 +372,12 @@ module.exports = class TransactionController extends EventEmitter { } queryPendingTxs ({oldBlock, newBlock}) { + // check pending transactions on start if (!oldBlock) { this._checkPendingTxs() return } + // if we synced by more than one block, check for missed pending transactions const diff = Number.parseInt(newBlock.number) - Number.parseInt(oldBlock.number) if (diff > 1) this._checkPendingTxs() } @@ -453,6 +456,8 @@ module.exports = class TransactionController extends EventEmitter { this.txProviderUtils.publishTransaction(rawTx, cb) } + // checks the network for signed txs and + // if confirmed sets the tx status as 'confirmed' _checkPendingTxs () { var signedTxList = this.getFilteredTxList({status: 'submitted'}) if (!signedTxList.length) return -- cgit v1.2.3 From 5f8e74e0aa7eed37fc86a84f1495cc65030e9136 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Fri, 16 Jun 2017 16:36:32 -0700 Subject: put the block listeners back on the provider --- app/scripts/controllers/transactions.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 9c20a7f1a..d56a81150 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -24,10 +24,9 @@ module.exports = class TransactionController extends EventEmitter { this.blockTracker = opts.blockTracker this.query = opts.ethQuery this.txProviderUtils = new TxProviderUtil(this.query) - this.blockTracker.on('block', this.checkForTxInBlock.bind(this)) + this.blockTracker.on('rawBlock', this.checkForTxInBlock.bind(this)) this.blockTracker.on('block', this.resubmitPendingTxs.bind(this)) - // provider-engine only exploses the 'block' event, not 'latest' for 'sync' - this.provider._blockTracker.on('sync', this.queryPendingTxs.bind(this)) + this.blockTracker.on('sync', this.queryPendingTxs.bind(this)) this.signEthTx = opts.signTransaction this.nonceLock = Semaphore(1) -- cgit v1.2.3 From 9c2ead3d528046e4a6eed5bc45e82c972000354d Mon Sep 17 00:00:00 2001 From: frankiebee Date: Fri, 16 Jun 2017 16:43:38 -0700 Subject: put event back on the "blockTracker:/provider" --- app/scripts/controllers/transactions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index f6eb4e4d9..042d8e66d 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -27,7 +27,7 @@ module.exports = class TransactionController extends EventEmitter { this.blockTracker.on('block', this.checkForTxInBlock.bind(this)) // provider-engine only exploses the 'block' event, not 'latest' for 'sync' this.provider._blockTracker.on('sync', this.queryPendingTxs.bind(this)) - this.provider._blockTracker.on('latest', this.resubmitPendingTxs.bind(this)) + this.blockTracker.on('latest', this.resubmitPendingTxs.bind(this)) this.signEthTx = opts.signTransaction this.nonceLock = Semaphore(1) this.ethStore = opts.ethStore -- cgit v1.2.3 From 235cb1f2d790a7bda349ab0d33ad1009751a8536 Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Mon, 19 Jun 2017 17:50:06 -0700 Subject: Keeps dapp gas price if set --- app/scripts/controllers/transactions.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index d9d9849b1..e3c2d74d3 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -152,13 +152,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 () { -- cgit v1.2.3 From 92df9965ebd4a833817c32fd32f7e4533ec7fe19 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 21 Jun 2017 19:51:00 -0700 Subject: fix nonceTracker --- app/scripts/controllers/transactions.js | 51 +++++++++------------------------ 1 file changed, 13 insertions(+), 38 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index c2f98e66a..59c8be8b7 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -25,7 +25,7 @@ module.exports = class TransactionController extends EventEmitter { this.blockTracker = opts.blockTracker this.nonceTracker = new NonceTracker({ provider: this.provider, - blockTracker: this.blockTracker, + blockTracker: this.provider._blockTracker, getPendingTransactions: (address) => this.getFilteredTxList({ from: address, status: 'submitted' }), }) this.query = opts.ethQuery @@ -176,33 +176,7 @@ module.exports = class TransactionController extends EventEmitter { }, {}) } - // approveTransaction (txId, cb = warn) { - // promiseToCallback((async () => { - // // approve - // self.setTxStatusApproved(txId) - // // get next nonce - // const txMeta = this.getTx(txId) - // const fromAddress = txMeta.txParams.from - // const { nextNonce, releaseLock } = await this.nonceTracker.getNonceLock(fromAddress) - // txMeta.txParams.nonce = nonce - // this.updateTx(txMeta) - // // sign transaction - // const rawTx = await denodeify(self.signTransaction.bind(self))(txId) - // await denodeify(self.publishTransaction.bind(self))(txId, rawTx) - // })())((err) => { - // if (err) { - // this.setTxStatusFailed(txId, { - // errCode: err.errCode || err, - // message: err.message || 'Transaction failed during approval', - // }) - // } - // // must set transaction to submitted/failed before releasing lock - // releaseLock() - // cb(err) - // }) - // } - - async approveTransaction (txId) { + async approveTransaction (txId, cb = warn) { let nonceLock try { // approve @@ -215,9 +189,10 @@ module.exports = class TransactionController extends EventEmitter { this.updateTx(txMeta) // sign transaction const rawTx = await denodeify(this.signTransaction.bind(this))(txId) - await denodeify(this.publishTransaction.bind(this))(txId, rawTx) + await this.publishTransaction(txId, rawTx) // must set transaction to submitted/failed before releasing lock nonceLock.releaseLock() + cb() } catch (err) { this.setTxStatusFailed(txId, { errCode: err.errCode || err, @@ -226,7 +201,7 @@ module.exports = class TransactionController extends EventEmitter { // must set transaction to submitted/failed before releasing lock if (nonceLock) nonceLock.releaseLock() // continue with error chain - throw err + cb(err) } } @@ -260,16 +235,17 @@ module.exports = class TransactionController extends EventEmitter { }) } - publishTransaction (txId, rawTx, cb = warn) { + publishTransaction (txId, rawTx) { const txMeta = this.getTx(txId) txMeta.rawTx = rawTx this.updateTx(txMeta) - - this.txProviderUtils.publishTransaction(rawTx, (err, txHash) => { - if (err) return cb(err) - this.setTxHash(txId, txHash) - this.setTxStatusSubmitted(txId) - cb() + return new Promise((resolve, reject) => { + this.txProviderUtils.publishTransaction(rawTx, (err, txHash) => { + if (err) reject(err) + this.setTxHash(txId, txHash) + this.setTxStatusSubmitted(txId) + resolve() + }) }) } @@ -414,7 +390,6 @@ module.exports = class TransactionController extends EventEmitter { this.emit(`${txMeta.id}:${status}`, txId) if (status === 'submitted' || status === 'rejected') { this.emit(`${txMeta.id}:finished`, txMeta) - } this.updateTx(txMeta) this.emit('updateBadge') -- cgit v1.2.3 From db2836a1ae5bfb2e641ab2b68a9853297e97b64b Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 27 Jun 2017 14:19:28 -0700 Subject: dont stop retrying brodcasting txs --- app/scripts/controllers/transactions.js | 4 ---- 1 file changed, 4 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index f6dea34e7..31cf8239a 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 denodeify = require('denodeify') -const RETRY_LIMIT = 200 - module.exports = class TransactionController extends EventEmitter { constructor (opts) { super() @@ -435,8 +433,6 @@ module.exports = class TransactionController extends EventEmitter { // 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 -- cgit v1.2.3 From 0ee4502d716ebe28fa426a05c454a75c7f82d965 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 27 Jun 2017 15:26:04 -0700 Subject: calculate nonce based on local pending txs w/o error state. --- app/scripts/controllers/transactions.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 651565519..460280578 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -26,7 +26,7 @@ module.exports = class TransactionController extends EventEmitter { this.nonceTracker = new NonceTracker({ provider: this.provider, blockTracker: this.provider._blockTracker, - getPendingTransactions: (address) => this.getFilteredTxList({ from: address, status: 'submitted' }), + getPendingTransactions: (address) => this.getFilteredTxList({ from: address, status: 'submitted', err: undefined }), }) this.query = opts.ethQuery this.txProviderUtils = new TxProviderUtil(this.query) @@ -263,10 +263,19 @@ module.exports = class TransactionController extends EventEmitter { to: '0x0..', from: '0x0..', status: 'signed', + err: undefined, } and returns a list of tx with all options matching + ****************HINT**************** + | `err: undefined` is like looking | + | for a tx with no err | + | so you can also search txs that | + | dont have something as well by | + | setting the value as undefined | + ************************************ + this is for things like filtering a the tx list for only tx's from 1 account or for filltering for all txs from one account -- cgit v1.2.3 From 690685d20de310b4c4589e92a5053afd9c56e85a Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 27 Jun 2017 16:46:14 -0700 Subject: nonce-tracker: only check transactions that are not supposed to be ignored --- app/scripts/controllers/transactions.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 460280578..c74427cd5 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -26,7 +26,14 @@ module.exports = class TransactionController extends EventEmitter { this.nonceTracker = new NonceTracker({ provider: this.provider, blockTracker: this.provider._blockTracker, - getPendingTransactions: (address) => this.getFilteredTxList({ from: address, status: 'submitted', err: undefined }), + getPendingTransactions: (address) => { + return this.getFilteredTxList({ + from: address, + status: 'submitted', + err: undefined, + ignore: undefined, + }) + }, }) this.query = opts.ethQuery this.txProviderUtils = new TxProviderUtil(this.query) -- cgit v1.2.3 From 51ff6d74e884b599f78b5454b33f2bc1a046f0b2 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 5 Jul 2017 12:07:34 -0700 Subject: clean up unused code from old noncelock --- app/scripts/controllers/transactions.js | 2 -- 1 file changed, 2 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index c74427cd5..2b40f9456 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -1,7 +1,6 @@ const EventEmitter = require('events') const async = require('async') const extend = require('xtend') -const Semaphore = require('semaphore') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') const denodeify = require('denodeify') @@ -41,7 +40,6 @@ module.exports = class TransactionController extends EventEmitter { this.blockTracker.on('latest', this.resubmitPendingTxs.bind(this)) this.blockTracker.on('sync', this.queryPendingTxs.bind(this)) this.signEthTx = opts.signTransaction - this.nonceLock = Semaphore(1) this.ethStore = opts.ethStore // memstore is computed from a few different stores this._updateMemstore() -- cgit v1.2.3 From 3abceac55d16e41b37116a8dda565644ed0a9f52 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 5 Jul 2017 22:06:39 -0700 Subject: Fail pending txs with low balance or invalid nonce --- app/scripts/controllers/transactions.js | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 52251d66e..3f5834756 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -428,10 +428,28 @@ 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) { + txMeta.err = { + isWarning: true, + message: 'Insufficient balance.', + } + this.updateTx(txMeta) + cb() + return log.error(txMeta.err.message) + } + + // if the nonce of the transaction is lower then the accounts nonce, fail. + if (txNonce < nonce) { + txMeta.err = { + isWarning: true, + message: 'Invalid nonce.', + } + this.updateTx(txMeta) + cb() + return log.error(txMeta.err.message) + } + // Only auto-submit already-signed txs: if (!('rawTx' in txMeta)) return cb() -- cgit v1.2.3 From 07d4e4fe6f31d99a9f15c3862671c5c07831ff2a Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 5 Jul 2017 23:23:57 -0700 Subject: Fix failing test --- app/scripts/controllers/transactions.js | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 3f5834756..7946d10d1 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -430,24 +430,18 @@ module.exports = class TransactionController extends EventEmitter { // if the value of the transaction is greater then the balance, fail. if (gtBalance) { - txMeta.err = { - isWarning: true, - message: 'Insufficient balance.', - } - this.updateTx(txMeta) + const message = 'Insufficient balance.' + this.setTxStatusFailed(txMeta.id, message) cb() - return log.error(txMeta.err.message) + return log.error(message) } // if the nonce of the transaction is lower then the accounts nonce, fail. if (txNonce < nonce) { - txMeta.err = { - isWarning: true, - message: 'Invalid nonce.', - } - this.updateTx(txMeta) + const message = 'Invalid nonce.' + this.setTxStatusFailed(txMeta.id, message) cb() - return log.error(txMeta.err.message) + return log.error(message) } // Only auto-submit already-signed txs: -- cgit v1.2.3 From 11b744bb87b4858dd2ef982c7d27e9751d8a09a1 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Thu, 6 Jul 2017 22:30:25 -0700 Subject: if an error happens during a tx publication set tx status to fail --- app/scripts/controllers/transactions.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 7946d10d1..8d3445c6f 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -240,7 +240,16 @@ module.exports = class TransactionController extends EventEmitter { this.updateTx(txMeta) this.txProviderUtils.publishTransaction(rawTx, (err, txHash) => { - if (err) return cb(err) + if (err) { + const errorMessage = err.message.toLowerCase() + if (errorMessage !== 'replacement transaction underpriced' + && errorMessage !== 'gas price too low to replace' + && !errorMessage.startsWith('known transaction') + ) { + this.setTxStatusFailed(txId) + } + return cb(err) + } this.setTxHash(txId, txHash) this.setTxStatusSubmitted(txId) cb() -- cgit v1.2.3 From 99556684096ed788ef01c909ff4cb4b0e61d3a05 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Thu, 6 Jul 2017 22:34:54 -0700 Subject: add comment --- app/scripts/controllers/transactions.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 8d3445c6f..14de786b7 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -241,11 +241,17 @@ module.exports = class TransactionController extends EventEmitter { this.txProviderUtils.publishTransaction(rawTx, (err, txHash) => { if (err) { - const errorMessage = err.message.toLowerCase() - if (errorMessage !== 'replacement transaction underpriced' - && errorMessage !== 'gas price too low to replace' - && !errorMessage.startsWith('known transaction') - ) { + const errorMessage = err.message.toLowerCase() + /* + Dont marked as failed if the error is because + it's a "known" transaction + "there is already a transaction with the same sender-nonce + but higher/same gas price" + */ + + if (errorMessage !== 'replacement transaction underpriced' // geth + && errorMessage !== 'gas price too low to replace' // parity + && !errorMessage.startsWith('known transaction')) { // geth this.setTxStatusFailed(txId) } return cb(err) -- cgit v1.2.3 From 8661989f516ae4455117e5158a97b4a6912a1980 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 7 Jul 2017 01:37:45 -0700 Subject: tx controller - move comments --- app/scripts/controllers/transactions.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 14de786b7..42baaaadc 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -249,9 +249,13 @@ module.exports = class TransactionController extends EventEmitter { but higher/same gas price" */ - if (errorMessage !== 'replacement transaction underpriced' // geth - && errorMessage !== 'gas price too low to replace' // parity - && !errorMessage.startsWith('known transaction')) { // geth + // geth + if (errorMessage !== 'replacement transaction underpriced' + // geth + && !errorMessage.startsWith('known transaction') + // parity + && errorMessage !== 'gas price too low to replace' + ) { this.setTxStatusFailed(txId) } return cb(err) -- cgit v1.2.3 From 34e2f6650d0db42b9f820d56a7acf9b72ca14da2 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 7 Jul 2017 01:50:48 -0700 Subject: tx controller - clean code --- app/scripts/controllers/transactions.js | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 42baaaadc..b855f910c 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -241,23 +241,24 @@ module.exports = class TransactionController extends EventEmitter { this.txProviderUtils.publishTransaction(rawTx, (err, txHash) => { if (err) { - const errorMessage = err.message.toLowerCase() /* - Dont marked as failed if the error is because - it's a "known" transaction + 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" */ - - // geth - if (errorMessage !== 'replacement transaction underpriced' - // geth - && !errorMessage.startsWith('known transaction') - // parity - && errorMessage !== 'gas price too low to replace' - ) { - this.setTxStatusFailed(txId) - } + const errorMessage = err.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) return cb() + + // encountered unknown error, set status to failed + this.setTxStatusFailed(txId, err.message) return cb(err) } this.setTxHash(txId, txHash) -- cgit v1.2.3 From 092a9c9defd4d9bd2db7f969a8076c8b624d30bb Mon Sep 17 00:00:00 2001 From: frankiebee Date: Fri, 7 Jul 2017 03:05:39 -0700 Subject: fail transactions that fail in resubmit --- app/scripts/controllers/transactions.js | 47 +++++++++++++++------------------ 1 file changed, 22 insertions(+), 25 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index b855f910c..41d70194e 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -23,7 +23,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.nonceLock = Semaphore(1) @@ -240,27 +243,7 @@ module.exports = class TransactionController extends EventEmitter { this.updateTx(txMeta) this.txProviderUtils.publishTransaction(rawTx, (err, txHash) => { - if (err) { - /* - 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 = err.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) return cb() - - // encountered unknown error, set status to failed - this.setTxStatusFailed(txId, err.message) - return cb(err) - } + if (err) return cb(err) this.setTxHash(txId, txHash) this.setTxStatusSubmitted(txId) cb() @@ -434,10 +417,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) { -- cgit v1.2.3 From 4fa999e4deae5451e73c126a80e541db6e3d0dc3 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 7 Jul 2017 19:02:34 -0700 Subject: tx controller - resubmit - recognize parity known hash message --- app/scripts/controllers/transactions.js | 1 + 1 file changed, 1 insertion(+) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 41d70194e..bcce1bf8f 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -431,6 +431,7 @@ module.exports = class TransactionController extends EventEmitter { || errorMessage.startsWith('known transaction') // parity || errorMessage === 'gas price too low to replace' + || errorMessage === 'transaction with the same hash was already imported.' ) // ignore resubmit warnings, return early if (!isKnownTx) this.setTxStatusFailed(txMeta.id, reason.message) -- cgit v1.2.3 From c53aac398a29ff7cfe0efa6c844653693d78157b Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 7 Jul 2017 19:09:32 -0700 Subject: tx controller - correctly set error message on resubmit error --- app/scripts/controllers/transactions.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index bcce1bf8f..e1eaba232 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -417,14 +417,13 @@ 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)) - pending.forEach((txMeta) => resubmit(txMeta) - .catch((reason) => { + pending.forEach((txMeta) => resubmit(txMeta).catch((err) => { /* 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 errorMessage = err.message.toLowerCase() const isKnownTx = ( // geth errorMessage === 'replacement transaction underpriced' @@ -434,7 +433,12 @@ module.exports = class TransactionController extends EventEmitter { || errorMessage === 'transaction with the same hash was already imported.' ) // ignore resubmit warnings, return early - if (!isKnownTx) this.setTxStatusFailed(txMeta.id, reason.message) + if (isKnownTx) return + // encountered real error - transition to error state + this.setTxStatusFailed(txMeta.id, { + errCode: err.errCode || err, + message: err.message, + }) })) } -- cgit v1.2.3 From c425ad4ec71c6a5d5cc7af3d2a4d42c56c3ca125 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 7 Jul 2017 19:13:06 -0700 Subject: tx controller - resubmit - correctly set error on bad nonce/balance --- app/scripts/controllers/transactions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index e1eaba232..18bb245de 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -453,7 +453,7 @@ module.exports = class TransactionController extends EventEmitter { // if the value of the transaction is greater then the balance, fail. if (gtBalance) { const message = 'Insufficient balance.' - this.setTxStatusFailed(txMeta.id, message) + this.setTxStatusFailed(txMeta.id, { message }) cb() return log.error(message) } @@ -461,7 +461,7 @@ module.exports = class TransactionController extends EventEmitter { // 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) + this.setTxStatusFailed(txMeta.id, { message }) cb() return log.error(message) } -- cgit v1.2.3 From 11d57adc5c6fa124cbb83a907a55a0aa733bb1cc Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 11 Jul 2017 11:57:42 -0700 Subject: add "Gateway timeout" to ignored errors when resubmiting and use .includes over .startsWith --- app/scripts/controllers/transactions.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 18bb245de..933c079d2 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -427,10 +427,12 @@ module.exports = class TransactionController extends EventEmitter { const isKnownTx = ( // geth errorMessage === 'replacement transaction underpriced' - || errorMessage.startsWith('known transaction') + || errorMessage.includes('known transaction') // parity || errorMessage === 'gas price too low to replace' || errorMessage === 'transaction with the same hash was already imported.' + // other + || errorMessage.includes('gateway timeout') ) // ignore resubmit warnings, return early if (isKnownTx) return -- cgit v1.2.3 From d97c6533b87b0a9dd6937c1ca57ec05129ac619b Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 11 Jul 2017 11:59:56 -0700 Subject: Remove local nonce error setting. --- app/scripts/controllers/transactions.js | 8 -------- 1 file changed, 8 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 18bb245de..02487c385 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -458,14 +458,6 @@ module.exports = class TransactionController extends EventEmitter { 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() -- cgit v1.2.3 From 611338c4e0b6de670f1a3ac6a0f1ddd3a2c063f7 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 11 Jul 2017 12:01:59 -0700 Subject: use .includes --- app/scripts/controllers/transactions.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 933c079d2..c0d4841a9 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -426,11 +426,11 @@ module.exports = class TransactionController extends EventEmitter { const errorMessage = err.message.toLowerCase() const isKnownTx = ( // geth - errorMessage === 'replacement transaction underpriced' + errorMessage.includes('replacement transaction underpriced') || errorMessage.includes('known transaction') // parity - || errorMessage === 'gas price too low to replace' - || errorMessage === 'transaction with the same hash was already imported.' + || errorMessage.includes('gas price too low to replace') + || errorMessage.includes('transaction with the same hash was already imported') // other || errorMessage.includes('gateway timeout') ) -- cgit v1.2.3 From c121ac21ec3bed0381e36de7ead1b583a3da148c Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 11 Jul 2017 12:16:08 -0700 Subject: remove irrelevan code --- app/scripts/controllers/transactions.js | 1 - 1 file changed, 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 2b40f9456..14b423d5d 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -30,7 +30,6 @@ module.exports = class TransactionController extends EventEmitter { from: address, status: 'submitted', err: undefined, - ignore: undefined, }) }, }) -- cgit v1.2.3 From c7b9e3fb1878cebbab26d5343cc18084a601c6bb Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 11 Jul 2017 12:18:07 -0700 Subject: Improve insufficient balance checking in retry loop --- app/scripts/controllers/transactions.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 02487c385..ca379a7ff 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -445,13 +445,10 @@ module.exports = class TransactionController extends EventEmitter { _resubmitTx (txMeta, cb) { const address = txMeta.txParams.from const balance = this.ethStore.getState().accounts[address].balance - const nonce = Number.parseInt(this.ethStore.getState().accounts[address].nonce) - const txNonce = Number.parseInt(txMeta.txParams.nonce) - 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, fail. - if (gtBalance) { + if (!this.txProviderUtils.sufficientBalance(txMeta.txParams, balance)) { const message = 'Insufficient balance.' this.setTxStatusFailed(txMeta.id, { message }) cb() -- cgit v1.2.3 From bd26ec46aa8f2d144939573a8c427e2a7743d25c Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 12 Jul 2017 15:07:56 -0700 Subject: mv updateAndApproveTx to txController --- app/scripts/controllers/transactions.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 45c6fb25a..a2842ae44 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -183,7 +183,7 @@ module.exports = class TransactionController extends EventEmitter { }, {}) } - async approveTransaction (txId, cb = warn) { + async approveTransaction (txId) { let nonceLock try { // approve @@ -199,7 +199,6 @@ module.exports = class TransactionController extends EventEmitter { await this.publishTransaction(txId, rawTx) // must set transaction to submitted/failed before releasing lock nonceLock.releaseLock() - cb() } catch (err) { this.setTxStatusFailed(txId, { errCode: err.errCode || err, @@ -208,7 +207,7 @@ module.exports = class TransactionController extends EventEmitter { // must set transaction to submitted/failed before releasing lock if (nonceLock) nonceLock.releaseLock() // continue with error chain - cb(err) + throw err } } @@ -217,6 +216,11 @@ module.exports = class TransactionController extends EventEmitter { cb() } + async updateAndApproveTransaction (txMeta) { + this.updateTx(txMeta) + await this.approveTransaction(txMeta.id) + } + getChainId () { const networkState = this.networkStore.getState() const getChainId = parseInt(networkState) -- cgit v1.2.3 From 27cb02bc5868673af794e0ad597fea87b2ddf175 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 12 Jul 2017 18:54:01 -0700 Subject: add "nonce too low" to the ignored errs list for tx retrys --- app/scripts/controllers/transactions.js | 1 + 1 file changed, 1 insertion(+) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 43735a691..4d037ce98 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -433,6 +433,7 @@ module.exports = class TransactionController extends EventEmitter { || errorMessage.includes('transaction with the same hash was already imported') // other || errorMessage.includes('gateway timeout') + || errorMessage.includes('nonce too low') ) // ignore resubmit warnings, return early if (isKnownTx) return -- cgit v1.2.3 From 7eccf5905a830853bbb1932dde9a7f4536d43f55 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Thu, 13 Jul 2017 15:25:43 -0400 Subject: make publishTransaction and signTransaction async methods --- app/scripts/controllers/transactions.js | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index a2842ae44..707543c87 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -3,7 +3,6 @@ const async = require('async') const extend = require('xtend') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') -const denodeify = require('denodeify') const TxProviderUtil = require('../lib/tx-utils') const createId = require('../lib/random-id') const NonceTracker = require('../lib/nonce-tracker') @@ -195,7 +194,7 @@ module.exports = class TransactionController extends EventEmitter { txMeta.txParams.nonce = nonceLock.nextNonce this.updateTx(txMeta) // sign transaction - const rawTx = await denodeify(this.signTransaction.bind(this))(txId) + const rawTx = await this.signTransaction(txId) await this.publishTransaction(txId, rawTx) // must set transaction to submitted/failed before releasing lock nonceLock.releaseLock() @@ -231,32 +230,27 @@ module.exports = class TransactionController extends EventEmitter { } } - signTransaction (txId, cb) { + async signTransaction (txId) { const txMeta = this.getTx(txId) const txParams = txMeta.txParams const fromAddress = txParams.from // add network/chain id txParams.chainId = this.getChainId() const ethTx = this.txProviderUtils.buildEthTxFromParams(txParams) - this.signEthTx(ethTx, fromAddress).then(() => { + const rawTx = await this.signEthTx(ethTx, fromAddress).then(() => { this.setTxStatusSigned(txMeta.id) - cb(null, ethUtil.bufferToHex(ethTx.serialize())) - }).catch((err) => { - cb(err) + return ethUtil.bufferToHex(ethTx.serialize()) }) + return rawTx } - publishTransaction (txId, rawTx) { + async publishTransaction (txId, rawTx) { const txMeta = this.getTx(txId) txMeta.rawTx = rawTx this.updateTx(txMeta) - return new Promise((resolve, reject) => { - this.txProviderUtils.publishTransaction(rawTx, (err, txHash) => { - if (err) reject(err) - this.setTxHash(txId, txHash) - this.setTxStatusSubmitted(txId) - resolve() - }) + await this.txProviderUtils.publishTransaction(rawTx).then((txHash) => { + this.setTxHash(txId, txHash) + this.setTxStatusSubmitted(txId) }) } @@ -435,8 +429,7 @@ module.exports = class TransactionController extends EventEmitter { const pending = this.getTxsByMetaData('status', 'submitted') // only try resubmitting if their are transactions to resubmit if (!pending.length) return - const resubmit = denodeify(this._resubmitTx.bind(this)) - pending.forEach((txMeta) => resubmit(txMeta).catch((err) => { + pending.forEach((txMeta) => this._resubmitTx(txMeta).catch((err) => { /* Dont marked as failed if the error is a "known" transaction warning "there is already a transaction with the same sender-nonce @@ -463,7 +456,7 @@ module.exports = class TransactionController extends EventEmitter { })) } - _resubmitTx (txMeta, cb) { + async _resubmitTx (txMeta, cb) { const address = txMeta.txParams.from const balance = this.ethStore.getState().accounts[address].balance if (!('retryCount' in txMeta)) txMeta.retryCount = 0 @@ -482,7 +475,7 @@ module.exports = class TransactionController extends EventEmitter { // Increment a try counter. txMeta.retryCount++ const rawTx = txMeta.rawTx - this.txProviderUtils.publishTransaction(rawTx, cb) + return await this.txProviderUtils.publishTransaction(rawTx, cb) } // checks the network for signed txs and -- cgit v1.2.3 From 67fdba5e42d8deac1dcbb4a82fd3d22b944e639a Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 18 Jul 2017 14:00:43 -0700 Subject: transaction - promisify _checkPendingTxs --- app/scripts/controllers/transactions.js | 68 ++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 27 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 61e96ca13..1fc48aadd 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -3,6 +3,7 @@ const async = require('async') const extend = require('xtend') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') +const pify = require('pify') const TxProviderUtil = require('../lib/tx-utils') const createId = require('../lib/random-id') const NonceTracker = require('../lib/nonce-tracker') @@ -481,35 +482,48 @@ module.exports = class TransactionController extends EventEmitter { // checks the network for signed txs and // if confirmed sets the tx status as 'confirmed' - _checkPendingTxs () { - var signedTxList = this.getFilteredTxList({status: 'submitted'}) - if (!signedTxList.length) return - signedTxList.forEach((txMeta) => { - var txHash = txMeta.hash - var txId = txMeta.id - if (!txHash) { - const errReason = { - errCode: 'No hash was provided', - message: 'We had an error while submitting this transaction, please try again.', - } - return this.setTxStatusFailed(txId, errReason) + async _checkPendingTxs () { + const signedTxList = this.getFilteredTxList({status: 'submitted'}) + try { + await Promise.all(signedTxList.map((txMeta) => this._checkPendingTx(txMeta))) + } catch (err) { + console.error('TransactionController - Error updating pending transactions') + console.error(err) + } + } + + async _checkPendingTx (txMeta) { + const txHash = txMeta.hash + const txId = txMeta.id + // extra check in case there was an uncaught error during the + // signature and submission process + if (!txHash) { + const errReason = { + errCode: 'No hash was provided', + message: 'We had an error while submitting this transaction, please try again.', } - this.query.getTransactionByHash(txHash, (err, txParams) => { - if (err || !txParams) { - if (!txParams) return - txMeta.err = { - isWarning: true, - errorCode: err, - message: 'There was a problem loading this transaction.', - } - this.updateTx(txMeta) - return log.error(err) - } - if (txParams.blockNumber) { - this.setTxStatusConfirmed(txId) + this.setTxStatusFailed(txId, errReason) + return + } + // get latest transaction status + let txParams + try { + txParams = await pify((cb) => this.query.getTransactionByHash(txHash, cb))() + if (!txParams) return + if (txParams.blockNumber) { + this.setTxStatusConfirmed(txId) + } + } catch (err) { + if (err || !txParams) { + txMeta.err = { + isWarning: true, + errorCode: err, + message: 'There was a problem loading this transaction.', } - }) - }) + this.updateTx(txMeta) + log.error(err) + } + } } } -- cgit v1.2.3 From 12d6f2162791b421bd51313b0063e144b47ed868 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 18 Jul 2017 15:27:15 -0700 Subject: transactions - block nonce-tracker while updating pending transactions --- app/scripts/controllers/transactions.js | 3 +++ 1 file changed, 3 insertions(+) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 1fc48aadd..5f3d84ebe 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -484,12 +484,15 @@ module.exports = class TransactionController extends EventEmitter { // if confirmed sets the tx status as 'confirmed' async _checkPendingTxs () { const signedTxList = this.getFilteredTxList({status: 'submitted'}) + // in order to keep the nonceTracker accurate we block it while updating pending transactions + const nonceGlobalLock = await this.nonceTracker.getGlobalLock() try { await Promise.all(signedTxList.map((txMeta) => this._checkPendingTx(txMeta))) } catch (err) { console.error('TransactionController - Error updating pending transactions') console.error(err) } + nonceGlobalLock.releaseLock() } async _checkPendingTx (txMeta) { -- cgit v1.2.3 From ab01358a480243c9073ac06dc4f510a6089567d0 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 25 Jul 2017 16:08:31 -0400 Subject: Add stack traces both in errors and as a way to track txMetas --- app/scripts/controllers/transactions.js | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 5f3d84ebe..4d1a18df7 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -1,10 +1,12 @@ const EventEmitter = require('events') const async = require('async') const extend = require('xtend') +const clone = require('deep-clone') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') const pify = require('pify') const TxProviderUtil = require('../lib/tx-utils') +const getStack = require('../lib/util').getStack const createId = require('../lib/random-id') const NonceTracker = require('../lib/nonce-tracker') @@ -117,9 +119,14 @@ module.exports = class TransactionController extends EventEmitter { // updateTx (txMeta) { + const txMetaForHistory = clone(txMeta) + txMetaForHistory.stack = getStack() var txId = txMeta.id var txList = this.getFullTxList() var index = txList.findIndex(txData => txData.id === txId) + if (!txMeta.history) txMeta.history = [] + txMeta.history.push(txMetaForHistory) + txList[index] = txMeta this._saveTxList(txList) this.emit('update') @@ -134,7 +141,7 @@ module.exports = class TransactionController extends EventEmitter { } addUnapprovedTransaction (txParams, done) { - let txMeta + let txMeta = {} async.waterfall([ // validate (cb) => this.txProviderUtils.validateTxParams(txParams, cb), @@ -146,6 +153,7 @@ module.exports = class TransactionController extends EventEmitter { status: 'unapproved', metamaskNetworkId: this.getNetwork(), txParams: txParams, + history: [], } cb() }, @@ -165,6 +173,7 @@ module.exports = class TransactionController extends EventEmitter { txParams.value = txParams.value || '0x0' if (!txParams.gasPrice) { this.query.gasPrice((err, gasPrice) => { + if (err) return cb(err) // set gasPrice txParams.gasPrice = gasPrice @@ -201,6 +210,7 @@ module.exports = class TransactionController extends EventEmitter { nonceLock.releaseLock() } catch (err) { this.setTxStatusFailed(txId, { + stack: err.stack || err.message, errCode: err.errCode || err, message: err.message || 'Transaction failed during approval', }) @@ -364,11 +374,11 @@ module.exports = class TransactionController extends EventEmitter { var txId = txMeta.id if (!txHash) { - const errReason = { + return this.setTxStatusFailed(txId, { + stack: 'checkForTxInBlock: custom tx-controller error message Line# 368', errCode: 'No hash was provided', message: 'We had an error while submitting this transaction, please try again.', - } - return this.setTxStatusFailed(txId, errReason) + }) } block.transactions.forEach((tx) => { @@ -452,6 +462,7 @@ module.exports = class TransactionController extends EventEmitter { if (isKnownTx) return // encountered real error - transition to error state this.setTxStatusFailed(txMeta.id, { + stack: err.stack || err.message, errCode: err.errCode || err, message: err.message, }) @@ -466,7 +477,10 @@ module.exports = class TransactionController extends EventEmitter { // if the value of the transaction is greater then the balance, fail. if (!this.txProviderUtils.sufficientBalance(txMeta.txParams, balance)) { const message = 'Insufficient balance.' - this.setTxStatusFailed(txMeta.id, { message }) + this.setTxStatusFailed(txMeta.id, { + stack: '_resubnitTx: custom tx-controller error line# 472', + message, + }) cb() return log.error(message) } @@ -501,11 +515,11 @@ module.exports = class TransactionController extends EventEmitter { // extra check in case there was an uncaught error during the // signature and submission process if (!txHash) { - const errReason = { + this.setTxStatusFailed(txId, { + stack: '_checkPendingTxs: custom tx-controller error message Line# 510', errCode: 'No hash was provided', message: 'We had an error while submitting this transaction, please try again.', - } - this.setTxStatusFailed(txId, errReason) + }) return } // get latest transaction status -- cgit v1.2.3 From 5b9a6bd367173330d8bcfd973278eeba6f31ec06 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 25 Jul 2017 13:16:46 -0700 Subject: tx cont - remove old cb from async fn --- app/scripts/controllers/transactions.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 5f3d84ebe..fc91bdf4d 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -458,7 +458,7 @@ module.exports = class TransactionController extends EventEmitter { })) } - async _resubmitTx (txMeta, cb) { + async _resubmitTx (txMeta) { const address = txMeta.txParams.from const balance = this.ethStore.getState().accounts[address].balance if (!('retryCount' in txMeta)) txMeta.retryCount = 0 @@ -467,17 +467,17 @@ module.exports = class TransactionController extends EventEmitter { if (!this.txProviderUtils.sufficientBalance(txMeta.txParams, balance)) { const message = 'Insufficient balance.' this.setTxStatusFailed(txMeta.id, { message }) - cb() - return log.error(message) + log.error(message) + return } // Only auto-submit already-signed txs: - if (!('rawTx' in txMeta)) return cb() + if (!('rawTx' in txMeta)) return // Increment a try counter. txMeta.retryCount++ const rawTx = txMeta.rawTx - return await this.txProviderUtils.publishTransaction(rawTx, cb) + return await this.txProviderUtils.publishTransaction(rawTx) } // checks the network for signed txs and -- cgit v1.2.3 From e0a626da3b026fd7dd258e8accf771353c4ea38e Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 25 Jul 2017 18:02:21 -0400 Subject: remove line numbers --- app/scripts/controllers/transactions.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 4d1a18df7..d96e2236a 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -375,7 +375,7 @@ module.exports = class TransactionController extends EventEmitter { if (!txHash) { return this.setTxStatusFailed(txId, { - stack: 'checkForTxInBlock: custom tx-controller error message Line# 368', + stack: 'checkForTxInBlock: custom tx-controller error me', errCode: 'No hash was provided', message: 'We had an error while submitting this transaction, please try again.', }) @@ -478,7 +478,7 @@ module.exports = class TransactionController extends EventEmitter { if (!this.txProviderUtils.sufficientBalance(txMeta.txParams, balance)) { const message = 'Insufficient balance.' this.setTxStatusFailed(txMeta.id, { - stack: '_resubnitTx: custom tx-controller error line# 472', + stack: '_resubnitTx: custom tx-controller ', message, }) cb() @@ -516,7 +516,7 @@ module.exports = class TransactionController extends EventEmitter { // signature and submission process if (!txHash) { this.setTxStatusFailed(txId, { - stack: '_checkPendingTxs: custom tx-controller error message Line# 510', + stack: '_checkPendingTxs: custom tx-controller error message', errCode: 'No hash was provided', message: 'We had an error while submitting this transaction, please try again.', }) -- cgit v1.2.3 From 1df833bee8a51c304491a3045138560e8c3f2b52 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 25 Jul 2017 18:21:40 -0400 Subject: use clone --- app/scripts/controllers/transactions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index d96e2236a..4de2b7db3 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -1,7 +1,7 @@ const EventEmitter = require('events') const async = require('async') const extend = require('xtend') -const clone = require('deep-clone') +const clone = require('clone') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') const pify = require('pify') -- cgit v1.2.3 From b81f8831505b1ebb1d58a474d52b068d42879d56 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 25 Jul 2017 18:23:17 -0400 Subject: fix stack wording --- app/scripts/controllers/transactions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 4de2b7db3..5485dc723 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -375,7 +375,7 @@ module.exports = class TransactionController extends EventEmitter { if (!txHash) { return this.setTxStatusFailed(txId, { - stack: 'checkForTxInBlock: custom tx-controller error me', + stack: 'checkForTxInBlock: custom tx-controller error message', errCode: 'No hash was provided', message: 'We had an error while submitting this transaction, please try again.', }) @@ -478,7 +478,7 @@ module.exports = class TransactionController extends EventEmitter { if (!this.txProviderUtils.sufficientBalance(txMeta.txParams, balance)) { const message = 'Insufficient balance.' this.setTxStatusFailed(txMeta.id, { - stack: '_resubnitTx: custom tx-controller ', + stack: '_resubnitTx: custom tx-controller error', message, }) cb() -- cgit v1.2.3 From ba88f7b8dd32b6ffdb46e70b8c9fbd563bb53b69 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 25 Jul 2017 18:29:02 -0400 Subject: fix typo --- app/scripts/controllers/transactions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 5485dc723..263424518 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -478,7 +478,7 @@ module.exports = class TransactionController extends EventEmitter { if (!this.txProviderUtils.sufficientBalance(txMeta.txParams, balance)) { const message = 'Insufficient balance.' this.setTxStatusFailed(txMeta.id, { - stack: '_resubnitTx: custom tx-controller error', + stack: '_resubmitTx: custom tx-controller error', message, }) cb() -- cgit v1.2.3 From 0ef90fb1f0f1a1bf4a7efd90df7b8f8c66fc07d5 Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 26 Jul 2017 10:40:08 -0700 Subject: tx controller + nonce tracker - record nonce components on txMeta --- app/scripts/controllers/transactions.js | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 7b2e4e314..32795a9f2 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -200,8 +200,12 @@ module.exports = class TransactionController extends EventEmitter { // get next nonce const txMeta = this.getTx(txId) const fromAddress = txMeta.txParams.from + // wait for a nonce nonceLock = await this.nonceTracker.getNonceLock(fromAddress) + // add nonce to txParams txMeta.txParams.nonce = nonceLock.nextNonce + // add nonce debugging information to txMeta + txMeta.nonceDetails = nonceLock.nonceDetails this.updateTx(txMeta) // sign transaction const rawTx = await this.signTransaction(txId) -- cgit v1.2.3 From 7e2e4948a6ce5856338406de49cbad6a9931d72b Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 26 Jul 2017 10:57:47 -0700 Subject: tx cont - dont recursively store history --- app/scripts/controllers/transactions.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index d6b2b555e..8f53ffa8c 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -119,14 +119,20 @@ module.exports = class TransactionController extends EventEmitter { // updateTx (txMeta) { + // create txMeta snapshot for history const txMetaForHistory = clone(txMeta) + // dont include previous history in this snapshot + delete txMetaForHistory.history + // add stack to help understand why tx was updated txMetaForHistory.stack = getStack() - var txId = txMeta.id - var txList = this.getFullTxList() - var index = txList.findIndex(txData => txData.id === txId) + // add snapshot to tx history if (!txMeta.history) txMeta.history = [] txMeta.history.push(txMetaForHistory) + // update the tx + var txId = txMeta.id + var txList = this.getFullTxList() + var index = txList.findIndex(txData => txData.id === txId) txList[index] = txMeta this._saveTxList(txList) this.emit('update') -- cgit v1.2.3 From 35a128db1e6ecba9076ec145c9d2334f623703b7 Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 26 Jul 2017 11:37:00 -0700 Subject: nonce-tracker - hotfix for provider proxying --- app/scripts/controllers/transactions.js | 1 - 1 file changed, 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 8f53ffa8c..f71659042 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -24,7 +24,6 @@ module.exports = class TransactionController extends EventEmitter { this.blockTracker = opts.blockTracker this.nonceTracker = new NonceTracker({ provider: this.provider, - blockTracker: this.provider._blockTracker, getPendingTransactions: (address) => { return this.getFilteredTxList({ from: address, -- cgit v1.2.3 From 432f516ab005dd2b4eb4b2e8766ed30216386d98 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 26 Jul 2017 14:56:52 -0400 Subject: make addUnapprovedTransaction async function and use promise based ethQuery --- app/scripts/controllers/transactions.js | 296 +++++++++++++++----------------- 1 file changed, 138 insertions(+), 158 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 5f2d75b47..d3e852ef9 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -1,10 +1,11 @@ const EventEmitter = require('events') const async = require('async') const extend = require('xtend') +const pify = require('pify') const clone = require('clone') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') -const pify = require('pify') +const EthQuery = require('ethjs-query'); const TxProviderUtil = require('../lib/tx-utils') const getStack = require('../lib/util').getStack const createId = require('../lib/random-id') @@ -33,7 +34,7 @@ module.exports = class TransactionController extends EventEmitter { }) }, }) - this.query = opts.ethQuery + this.query = new EthQuery(this.provider) this.txProviderUtils = new TxProviderUtil(this.query) this.blockTracker.on('rawBlock', this.checkForTxInBlock.bind(this)) // this is a little messy but until ethstore has been either @@ -62,13 +63,6 @@ module.exports = class TransactionController extends EventEmitter { return this.preferencesStore.getState().selectedAddress } - // Returns the tx list - getTxList () { - const network = this.getNetwork() - const fullTxList = this.getFullTxList() - return fullTxList.filter(txMeta => txMeta.metamaskNetworkId === network) - } - // Returns the number of txs for the current network. getTxCount () { return this.getTxList().length @@ -79,6 +73,50 @@ module.exports = class TransactionController extends EventEmitter { return this.store.getState().transactions } + get unapprovedTxCount () { + return Object.keys(this.getUnapprovedTxList()).length + } + + get pendingTxCount () { + return this.getTxsByMetaData('status', 'signed').length + } + + // Returns the tx list + getTxList () { + const network = this.getNetwork() + const fullTxList = this.getFullTxList() + return this.getTxsByMetaData('metamaskNetworkId', network, fullTxList) + } + + // gets tx by Id and returns it + getTx (txId) { + const txList = this.getTxList() + const txMeta = txList.find(txData => txData.id === txId) + return txMeta + } + getUnapprovedTxList () { + let txList = this.getTxList() + return txList.filter((txMeta) => txMeta.status === 'unapproved') + .reduce((result, tx) => { + result[tx.id] = tx + return result + }, {}) + } + + updateTx (txMeta) { + const txMetaForHistory = clone(txMeta) + txMetaForHistory.stack = getStack() + const txId = txMeta.id + const txList = this.getFullTxList() + const index = txList.findIndex(txData => txData.id === txId) + if (!txMeta.history) txMeta.history = [] + txMeta.history.push(txMetaForHistory) + + txList[index] = txMeta + this._saveTxList(txList) + this.emit('update') + } + // Adds a tx to the txlist addTx (txMeta) { const txCount = this.getTxCount() @@ -92,7 +130,7 @@ module.exports = class TransactionController extends EventEmitter { // or rejected tx's. // not tx's that are pending or unapproved if (txCount > txHistoryLimit - 1) { - var index = fullTxList.findIndex((metaTx) => ((metaTx.status === 'confirmed' || metaTx.status === 'rejected') && network === txMeta.metamaskNetworkId)) + let index = fullTxList.findIndex((metaTx) => ((metaTx.status === 'confirmed' || metaTx.status === 'rejected') && network === txMeta.metamaskNetworkId)) fullTxList.splice(index, 1) } fullTxList.push(txMeta) @@ -110,86 +148,40 @@ module.exports = class TransactionController extends EventEmitter { this.emit(`${txMeta.id}:unapproved`, txMeta) } - // gets tx by Id and returns it - getTx (txId, cb) { - var txList = this.getTxList() - var txMeta = txList.find(txData => txData.id === txId) - return cb ? cb(txMeta) : txMeta - } - - // - updateTx (txMeta) { - const txMetaForHistory = clone(txMeta) - txMetaForHistory.stack = getStack() - var txId = txMeta.id - var txList = this.getFullTxList() - var index = txList.findIndex(txData => txData.id === txId) - if (!txMeta.history) txMeta.history = [] - txMeta.history.push(txMetaForHistory) - - txList[index] = txMeta - this._saveTxList(txList) - this.emit('update') - } - - get unapprovedTxCount () { - return Object.keys(this.getUnapprovedTxList()).length - } - - get pendingTxCount () { - return this.getTxsByMetaData('status', 'signed').length - } - - addUnapprovedTransaction (txParams, done) { - let txMeta = {} - async.waterfall([ - // validate - (cb) => this.txProviderUtils.validateTxParams(txParams, cb), - // construct txMeta - (cb) => { - txMeta = { - id: createId(), - time: (new Date()).getTime(), - status: 'unapproved', - metamaskNetworkId: this.getNetwork(), - txParams: txParams, - history: [], - } - cb() - }, - // add default tx params - (cb) => this.addTxDefaults(txMeta, cb), - // save txMeta - (cb) => { - this.addTx(txMeta) - cb(null, txMeta) - }, - ], done) + async addUnapprovedTransaction (txParams) { + // validate + await this.txProviderUtils.validateTxParams(txParams) + // construct txMeta + const txMeta = { + id: createId(), + time: (new Date()).getTime(), + status: 'unapproved', + metamaskNetworkId: this.getNetwork(), + txParams: txParams, + history: [], + } + // add default tx params + await this.addTxDefaults(txMeta), + // save txMeta + this.addTx(txMeta) + return txMeta } - addTxDefaults (txMeta, cb) { + async addTxDefaults (txMeta) { const txParams = txMeta.txParams // ensure value txParams.value = txParams.value || '0x0' if (!txParams.gasPrice) { - this.query.gasPrice((err, gasPrice) => { - - if (err) return cb(err) - // set gasPrice - txParams.gasPrice = gasPrice - }) + gassPrice = await this.query.gasPrice() + txParams.gasPrice = gasPrice } // set gasLimit - this.txProviderUtils.analyzeGasUsage(txMeta, cb) + return await this.txProviderUtils.analyzeGasUsage(txMeta) } - getUnapprovedTxList () { - var txList = this.getTxList() - return txList.filter((txMeta) => txMeta.status === 'unapproved') - .reduce((result, tx) => { - result[tx.id] = tx - return result - }, {}) + async updateAndApproveTransaction (txMeta) { + this.updateTx(txMeta) + await this.approveTransaction(txMeta.id) } async approveTransaction (txId) { @@ -221,26 +213,6 @@ module.exports = class TransactionController extends EventEmitter { } } - cancelTransaction (txId, cb = warn) { - this.setTxStatusRejected(txId) - cb() - } - - async updateAndApproveTransaction (txMeta) { - this.updateTx(txMeta) - await this.approveTransaction(txMeta.id) - } - - getChainId () { - const networkState = this.networkStore.getState() - const getChainId = parseInt(networkState) - if (Number.isNaN(getChainId)) { - return 0 - } else { - return getChainId - } - } - async signTransaction (txId) { const txMeta = this.getTx(txId) const txParams = txMeta.txParams @@ -265,6 +237,22 @@ module.exports = class TransactionController extends EventEmitter { }) } + cancelTransaction (txId) { + this.setTxStatusRejected(txId) + return Promise.resolve() + } + + + getChainId () { + const networkState = this.networkStore.getState() + const getChainId = parseInt(networkState) + if (Number.isNaN(getChainId)) { + return 0 + } else { + return getChainId + } + } + // receives a txHash records the tx as signed setTxHash (txId, txHash) { // Add the tx hash to the persisted meta-tx object @@ -275,7 +263,7 @@ module.exports = class TransactionController extends EventEmitter { /* Takes an object of fields to search for eg: - var thingsToLookFor = { + let thingsToLookFor = { to: '0x0..', from: '0x0..', status: 'signed', @@ -298,7 +286,7 @@ module.exports = class TransactionController extends EventEmitter { and that have been 'confirmed' */ getFilteredTxList (opts) { - var filteredTxList + let filteredTxList Object.keys(opts).forEach((key) => { filteredTxList = this.getTxsByMetaData(key, opts[key], filteredTxList) }) @@ -359,7 +347,7 @@ module.exports = class TransactionController extends EventEmitter { // merges txParams obj onto txData.txParams // use extend to ensure that all fields are filled updateTxParams (txId, txParams) { - var txMeta = this.getTx(txId) + const txMeta = this.getTx(txId) txMeta.txParams = extend(txMeta.txParams, txParams) this.updateTx(txMeta) } @@ -367,20 +355,19 @@ module.exports = class TransactionController extends EventEmitter { // checks if a signed tx is in a block and // if included sets the tx status as 'confirmed' checkForTxInBlock (block) { - var signedTxList = this.getFilteredTxList({status: 'submitted'}) + const signedTxList = this.getFilteredTxList({status: 'submitted'}) if (!signedTxList.length) return signedTxList.forEach((txMeta) => { - var txHash = txMeta.hash - var txId = txMeta.id + const txHash = txMeta.hash + const txId = txMeta.id if (!txHash) { - return this.setTxStatusFailed(txId, { - stack: 'checkForTxInBlock: custom tx-controller error message', - errCode: 'No hash was provided', - message: 'We had an error while submitting this transaction, please try again.', - }) + const noTxHash = new Error('We had an error while submitting this transaction, please try again.') + noTxHash.name = 'NoTxHashError' + this.setTxStatusFailed(noTxHash) } + block.transactions.forEach((tx) => { if (tx.hash === txHash) this.setTxStatusConfirmed(txId) }) @@ -398,6 +385,39 @@ module.exports = class TransactionController extends EventEmitter { if (diff > 1) this._checkPendingTxs() } + resubmitPendingTxs () { + const pending = this.getTxsByMetaData('status', 'submitted') + // only try resubmitting if their are transactions to resubmit + if (!pending.length) return + pending.forEach((txMeta) => this._resubmitTx(txMeta).catch((err) => { + /* + 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 = err.message.toLowerCase() + const isKnownTx = ( + // geth + errorMessage.includes('replacement transaction underpriced') + || errorMessage.includes('known transaction') + // parity + || errorMessage.includes('gas price too low to replace') + || errorMessage.includes('transaction with the same hash was already imported') + // other + || errorMessage.includes('gateway timeout') + || errorMessage.includes('nonce too low') + ) + // ignore resubmit warnings, return early + if (isKnownTx) return + // encountered real error - transition to error state + this.setTxStatusFailed(txMeta.id, { + stack: err.stack || err.message, + errCode: err.errCode || err, + message: err.message, + }) + })) + } + // PRIVATE METHODS // Should find the tx in the tx list and @@ -411,7 +431,7 @@ module.exports = class TransactionController extends EventEmitter { // - `'confirmed'` the tx has been included in a block. // - `'failed'` the tx failed for some reason, included on tx data. _setTxStatus (txId, status) { - var txMeta = this.getTx(txId) + const txMeta = this.getTx(txId) txMeta.status = status this.emit(`${txMeta.id}:${status}`, txId) if (status === 'submitted' || status === 'rejected') { @@ -436,39 +456,6 @@ module.exports = class TransactionController extends EventEmitter { this.memStore.updateState({ unapprovedTxs, selectedAddressTxList }) } - resubmitPendingTxs () { - const pending = this.getTxsByMetaData('status', 'submitted') - // only try resubmitting if their are transactions to resubmit - if (!pending.length) return - pending.forEach((txMeta) => this._resubmitTx(txMeta).catch((err) => { - /* - 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 = err.message.toLowerCase() - const isKnownTx = ( - // geth - errorMessage.includes('replacement transaction underpriced') - || errorMessage.includes('known transaction') - // parity - || errorMessage.includes('gas price too low to replace') - || errorMessage.includes('transaction with the same hash was already imported') - // other - || errorMessage.includes('gateway timeout') - || errorMessage.includes('nonce too low') - ) - // ignore resubmit warnings, return early - if (isKnownTx) return - // encountered real error - transition to error state - this.setTxStatusFailed(txMeta.id, { - stack: err.stack || err.message, - errCode: err.errCode || err, - message: err.message, - }) - })) - } - async _resubmitTx (txMeta) { const address = txMeta.txParams.from const balance = this.ethStore.getState().accounts[address].balance @@ -515,17 +502,14 @@ module.exports = class TransactionController extends EventEmitter { // extra check in case there was an uncaught error during the // signature and submission process if (!txHash) { - this.setTxStatusFailed(txId, { - stack: '_checkPendingTxs: custom tx-controller error message', - errCode: 'No hash was provided', - message: 'We had an error while submitting this transaction, please try again.', - }) - return + const noTxHash = new Error('We had an error while submitting this transaction, please try again.') + noTxHash.name = 'NoTxHashError' + this.setTxStatusFailed(noTxHash) } // get latest transaction status let txParams try { - txParams = await pify((cb) => this.query.getTransactionByHash(txHash, cb))() + txParams = await this.query.getTransactionByHash(txHash) if (!txParams) return if (txParams.blockNumber) { this.setTxStatusConfirmed(txId) @@ -538,12 +522,8 @@ module.exports = class TransactionController extends EventEmitter { message: 'There was a problem loading this transaction.', } this.updateTx(txMeta) - log.error(err) + throw err } } } - -} - - -const warn = () => log.warn('warn was used no cb provided') +} \ No newline at end of file -- cgit v1.2.3 From 3a4726018e43157909f8c04e03f33cee2584795a Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 2 Aug 2017 11:35:35 -0400 Subject: fix addTxDefaults --- app/scripts/controllers/transactions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index d3e852ef9..43dfb9360 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -172,7 +172,7 @@ module.exports = class TransactionController extends EventEmitter { // ensure value txParams.value = txParams.value || '0x0' if (!txParams.gasPrice) { - gassPrice = await this.query.gasPrice() + const gasPrice = await this.query.gasPrice() txParams.gasPrice = gasPrice } // set gasLimit -- cgit v1.2.3 From 25bc15ba175091513f6d281e9a16f3643fe4b18d Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 2 Aug 2017 11:47:13 -0400 Subject: lint fixes --- app/scripts/controllers/transactions.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 8855dfd5b..0c63a5647 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -1,11 +1,9 @@ const EventEmitter = require('events') -const async = require('async') const extend = require('xtend') -const pify = require('pify') const clone = require('clone') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') -const EthQuery = require('ethjs-query'); +const EthQuery = require('ethjs-query') const TxProviderUtil = require('../lib/tx-utils') const getStack = require('../lib/util').getStack const createId = require('../lib/random-id') @@ -168,7 +166,7 @@ module.exports = class TransactionController extends EventEmitter { history: [], } // add default tx params - await this.addTxDefaults(txMeta), + await this.addTxDefaults(txMeta) // save txMeta this.addTx(txMeta) return txMeta -- cgit v1.2.3 From b80c7e417bfa3adf338170472ba4c4c6733e8402 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 2 Aug 2017 18:58:05 -0400 Subject: move newUnapprovedTransaction to transactions.js --- app/scripts/controllers/transactions.js | 63 ++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 21 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 0c63a5647..720323e41 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -70,11 +70,11 @@ module.exports = class TransactionController extends EventEmitter { return this.store.getState().transactions } - get unapprovedTxCount () { + getUnapprovedTxCount () { return Object.keys(this.getUnapprovedTxList()).length } - get pendingTxCount () { + getPendingTxCount () { return this.getTxsByMetaData('status', 'signed').length } @@ -92,7 +92,7 @@ module.exports = class TransactionController extends EventEmitter { return txMeta } getUnapprovedTxList () { - let txList = this.getTxList() + const txList = this.getTxList() return txList.filter((txMeta) => txMeta.status === 'unapproved') .reduce((result, tx) => { result[tx.id] = tx @@ -135,7 +135,7 @@ module.exports = class TransactionController extends EventEmitter { // or rejected tx's. // not tx's that are pending or unapproved if (txCount > txHistoryLimit - 1) { - let index = fullTxList.findIndex((metaTx) => ((metaTx.status === 'confirmed' || metaTx.status === 'rejected') && network === txMeta.metamaskNetworkId)) + const index = fullTxList.findIndex((metaTx) => ((metaTx.status === 'confirmed' || metaTx.status === 'rejected') && network === txMeta.metamaskNetworkId)) fullTxList.splice(index, 1) } fullTxList.push(txMeta) @@ -153,6 +153,25 @@ module.exports = class TransactionController extends EventEmitter { this.emit(`${txMeta.id}:unapproved`, txMeta) } + async newUnapprovedTransaction (txParams) { + log.debug(`MetaMaskController newUnapprovedTransaction ${JSON.stringify(txParams)}`) + const txMeta = await this.addUnapprovedTransaction(txParams) + this.emit('newUnaprovedTx', txMeta) + // listen for tx completion (success, fail) + return new Promise((resolve, reject) => { + this.once(`${txMeta.id}:finished`, (completedTx) => { + switch (completedTx.status) { + case 'submitted': + return resolve(completedTx.hash) + case 'rejected': + return reject(new Error('MetaMask Tx Signature: User denied transaction signature.')) + default: + return reject(new Error(`MetaMask Tx Signature: Unknown problem: ${JSON.stringify(completedTx.txParams)}`)) + } + }) + }) + } + async addUnapprovedTransaction (txParams) { // validate await this.txProviderUtils.validateTxParams(txParams) @@ -229,10 +248,9 @@ module.exports = class TransactionController extends EventEmitter { // add network/chain id txParams.chainId = this.getChainId() const ethTx = this.txProviderUtils.buildEthTxFromParams(txParams) - const rawTx = await this.signEthTx(ethTx, fromAddress).then(() => { - this.setTxStatusSigned(txMeta.id) - return ethUtil.bufferToHex(ethTx.serialize()) - }) + await this.signEthTx(ethTx, fromAddress) + this.setTxStatusSigned(txMeta.id) + const rawTx = ethUtil.bufferToHex(ethTx.serialize()) return rawTx } @@ -240,15 +258,13 @@ module.exports = class TransactionController extends EventEmitter { const txMeta = this.getTx(txId) txMeta.rawTx = rawTx this.updateTx(txMeta) - await this.txProviderUtils.publishTransaction(rawTx).then((txHash) => { - this.setTxHash(txId, txHash) - this.setTxStatusSubmitted(txId) - }) + const txHash = await this.txProviderUtils.publishTransaction(rawTx) + this.setTxHash(txId, txHash) + this.setTxStatusSubmitted(txId) } - cancelTransaction (txId) { + async cancelTransaction (txId) { this.setTxStatusRejected(txId) - return Promise.resolve() } @@ -371,9 +387,9 @@ module.exports = class TransactionController extends EventEmitter { const txId = txMeta.id if (!txHash) { - const noTxHash = new Error('We had an error while submitting this transaction, please try again.') - noTxHash.name = 'NoTxHashError' - this.setTxStatusFailed(noTxHash) + const noTxHashErr = new Error('We had an error while submitting this transaction, please try again.') + noTxHashErr.name = 'NoTxHashError' + this.setTxStatusFailed(txId, noTxHashErr) } @@ -427,7 +443,12 @@ module.exports = class TransactionController extends EventEmitter { })) } - // PRIVATE METHODS + +/* _____________________________________ +| | +| PRIVATE METHODS | +|______________________________________*/ + // Should find the tx in the tx list and // update it. @@ -511,9 +532,9 @@ module.exports = class TransactionController extends EventEmitter { // extra check in case there was an uncaught error during the // signature and submission process if (!txHash) { - const noTxHash = new Error('We had an error while submitting this transaction, please try again.') - noTxHash.name = 'NoTxHashError' - this.setTxStatusFailed(noTxHash) + const noTxHashErr = new Error('We had an error while submitting this transaction, please try again.') + noTxHashErr.name = 'NoTxHashError' + this.setTxStatusFailed(txId, noTxHashErr) } // get latest transaction status let txParams -- cgit v1.2.3 From b471afcdb34cd121b9d3e3cccb3883943ba8aef5 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 2 Aug 2017 19:24:34 -0400 Subject: use error for #approveTransaction when setting failed --- app/scripts/controllers/transactions.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 720323e41..d4f32e049 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -229,11 +229,8 @@ module.exports = class TransactionController extends EventEmitter { // must set transaction to submitted/failed before releasing lock nonceLock.releaseLock() } catch (err) { - this.setTxStatusFailed(txId, { - stack: err.stack || err.message, - errCode: err.errCode || err, - message: err.message || 'Transaction failed during approval', - }) + if(!err.message) err.message = 'Transaction failed during approval' + this.setTxStatusFailed(txId, err) // must set transaction to submitted/failed before releasing lock if (nonceLock) nonceLock.releaseLock() // continue with error chain -- cgit v1.2.3 From dce593fd7bbe1848b8744e3911f24d9ac2fa1bf7 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Thu, 3 Aug 2017 15:39:55 -0400 Subject: remove stack from txs --- app/scripts/controllers/transactions.js | 3 --- 1 file changed, 3 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 720323e41..308d43cb0 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -5,7 +5,6 @@ const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') const EthQuery = require('ethjs-query') const TxProviderUtil = require('../lib/tx-utils') -const getStack = require('../lib/util').getStack const createId = require('../lib/random-id') const NonceTracker = require('../lib/nonce-tracker') @@ -105,8 +104,6 @@ module.exports = class TransactionController extends EventEmitter { const txMetaForHistory = clone(txMeta) // dont include previous history in this snapshot delete txMetaForHistory.history - // add stack to help understand why tx was updated - txMetaForHistory.stack = getStack() // add snapshot to tx history if (!txMeta.history) txMeta.history = [] txMeta.history.push(txMetaForHistory) -- cgit v1.2.3 From 087cd9fb1a42cb59579b8e24804583d6d127e901 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Fri, 4 Aug 2017 14:41:35 -0400 Subject: break out tx status pendding watchers --- app/scripts/controllers/transactions.js | 172 +++++--------------------------- 1 file changed, 27 insertions(+), 145 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index d4f32e049..a652c3278 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -5,6 +5,7 @@ const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') const EthQuery = require('ethjs-query') const TxProviderUtil = require('../lib/tx-utils') +const PendingTransactionUtils = require('../lib/pending-tx-watchers') const getStack = require('../lib/util').getStack const createId = require('../lib/random-id') const NonceTracker = require('../lib/nonce-tracker') @@ -21,6 +22,9 @@ module.exports = class TransactionController extends EventEmitter { this.txHistoryLimit = opts.txHistoryLimit this.provider = opts.provider this.blockTracker = opts.blockTracker + this.signEthTx = opts.signTransaction + this.ethStore = opts.ethStore + this.nonceTracker = new NonceTracker({ provider: this.provider, getPendingTransactions: (address) => { @@ -32,15 +36,31 @@ module.exports = class TransactionController extends EventEmitter { }, }) this.query = new EthQuery(this.provider) - this.txProviderUtils = new TxProviderUtil(this.query) - this.blockTracker.on('rawBlock', this.checkForTxInBlock.bind(this)) + this.txProviderUtils = new TxProviderUtil(this.provider) + + this.pendingTxUtils = new PendingTransactionUtils({ + provider: this.provider, + nonceTracker: this.nonceTracker, + getBalance: (address) => this.ethStore.getState().accounts[address].balance, + publishTransaction: this.txProviderUtils.publishTransaction.bind(this.txProviderUtils), + getPendingTransactions: (address) => { + return this.getFilteredTxList({ + from: address, + status: 'submitted', + }) + }, + }) + + this.pendingTxUtils.on('txWarning', this.updateTx.bind(this)) + this.pendingTxUtils.on('txFailed', this.setTxStatusFailed.bind(this)) + this.pendingTxUtils.on('txConfirmed', this.setTxStatusConfirmed.bind(this)) + + this.blockTracker.on('rawBlock', this.pendingTxUtils.checkForTxInBlock.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 + this.blockTracker.once('latest', () => this.blockTracker.on('latest', this.pendingTxUtils.resubmitPendingTxs.bind(this))) + this.blockTracker.on('sync', this.pendingTxUtils.queryPendingTxs.bind(this)) // memstore is computed from a few different stores this._updateMemstore() this.store.subscribe(() => this._updateMemstore()) @@ -229,7 +249,7 @@ module.exports = class TransactionController extends EventEmitter { // must set transaction to submitted/failed before releasing lock nonceLock.releaseLock() } catch (err) { - if(!err.message) err.message = 'Transaction failed during approval' + if (!err.message) err.message = 'Transaction failed during approval' this.setTxStatusFailed(txId, err) // must set transaction to submitted/failed before releasing lock if (nonceLock) nonceLock.releaseLock() @@ -374,73 +394,6 @@ module.exports = class TransactionController extends EventEmitter { this.updateTx(txMeta) } - // checks if a signed tx is in a block and - // if included sets the tx status as 'confirmed' - checkForTxInBlock (block) { - const signedTxList = this.getFilteredTxList({status: 'submitted'}) - if (!signedTxList.length) return - signedTxList.forEach((txMeta) => { - const txHash = txMeta.hash - const txId = txMeta.id - - if (!txHash) { - const noTxHashErr = new Error('We had an error while submitting this transaction, please try again.') - noTxHashErr.name = 'NoTxHashError' - this.setTxStatusFailed(txId, noTxHashErr) - } - - - block.transactions.forEach((tx) => { - if (tx.hash === txHash) this.setTxStatusConfirmed(txId) - }) - }) - } - - queryPendingTxs ({oldBlock, newBlock}) { - // check pending transactions on start - if (!oldBlock) { - this._checkPendingTxs() - return - } - // if we synced by more than one block, check for missed pending transactions - const diff = Number.parseInt(newBlock.number) - Number.parseInt(oldBlock.number) - if (diff > 1) this._checkPendingTxs() - } - - resubmitPendingTxs () { - const pending = this.getTxsByMetaData('status', 'submitted') - // only try resubmitting if their are transactions to resubmit - if (!pending.length) return - pending.forEach((txMeta) => this._resubmitTx(txMeta).catch((err) => { - /* - 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 = err.message.toLowerCase() - const isKnownTx = ( - // geth - errorMessage.includes('replacement transaction underpriced') - || errorMessage.includes('known transaction') - // parity - || errorMessage.includes('gas price too low to replace') - || errorMessage.includes('transaction with the same hash was already imported') - // other - || errorMessage.includes('gateway timeout') - || errorMessage.includes('nonce too low') - ) - // ignore resubmit warnings, return early - if (isKnownTx) return - // encountered real error - transition to error state - this.setTxStatusFailed(txMeta.id, { - stack: err.stack || err.message, - errCode: err.errCode || err, - message: err.message, - }) - })) - } - - /* _____________________________________ | | | PRIVATE METHODS | @@ -482,75 +435,4 @@ module.exports = class TransactionController extends EventEmitter { }) this.memStore.updateState({ unapprovedTxs, selectedAddressTxList }) } - - async _resubmitTx (txMeta) { - const address = txMeta.txParams.from - const balance = this.ethStore.getState().accounts[address].balance - if (!('retryCount' in txMeta)) txMeta.retryCount = 0 - - // if the value of the transaction is greater then the balance, fail. - if (!this.txProviderUtils.sufficientBalance(txMeta.txParams, balance)) { - const message = 'Insufficient balance.' - this.setTxStatusFailed(txMeta.id, { - stack: '_resubmitTx: custom tx-controller error', - message, - }) - log.error(message) - return - } - - // Only auto-submit already-signed txs: - if (!('rawTx' in txMeta)) return - - // Increment a try counter. - txMeta.retryCount++ - const rawTx = txMeta.rawTx - return await this.txProviderUtils.publishTransaction(rawTx) - } - - // checks the network for signed txs and - // if confirmed sets the tx status as 'confirmed' - async _checkPendingTxs () { - const signedTxList = this.getFilteredTxList({status: 'submitted'}) - // in order to keep the nonceTracker accurate we block it while updating pending transactions - const nonceGlobalLock = await this.nonceTracker.getGlobalLock() - try { - await Promise.all(signedTxList.map((txMeta) => this._checkPendingTx(txMeta))) - } catch (err) { - console.error('TransactionController - Error updating pending transactions') - console.error(err) - } - nonceGlobalLock.releaseLock() - } - - async _checkPendingTx (txMeta) { - const txHash = txMeta.hash - const txId = txMeta.id - // extra check in case there was an uncaught error during the - // signature and submission process - if (!txHash) { - const noTxHashErr = new Error('We had an error while submitting this transaction, please try again.') - noTxHashErr.name = 'NoTxHashError' - this.setTxStatusFailed(txId, noTxHashErr) - } - // get latest transaction status - let txParams - try { - txParams = await this.query.getTransactionByHash(txHash) - if (!txParams) return - if (txParams.blockNumber) { - this.setTxStatusConfirmed(txId) - } - } catch (err) { - if (err || !txParams) { - txMeta.err = { - isWarning: true, - errorCode: err, - message: 'There was a problem loading this transaction.', - } - this.updateTx(txMeta) - throw err - } - } - } } \ No newline at end of file -- cgit v1.2.3 From 08f49ab35f5a78fba6921a2957a92e0a2e5b065a Mon Sep 17 00:00:00 2001 From: frankiebee Date: Fri, 4 Aug 2017 14:50:34 -0400 Subject: rename PendingTransactionUtils -> PendingTransactionWatchers --- app/scripts/controllers/transactions.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 498cac9af..c1a0ef0f3 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -5,7 +5,7 @@ const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') const EthQuery = require('ethjs-query') const TxProviderUtil = require('../lib/tx-utils') -const PendingTransactionUtils = require('../lib/pending-tx-watchers') +const PendingTransactionWatchers = require('../lib/pending-tx-watchers') const createId = require('../lib/random-id') const NonceTracker = require('../lib/nonce-tracker') @@ -37,7 +37,7 @@ module.exports = class TransactionController extends EventEmitter { this.query = new EthQuery(this.provider) this.txProviderUtils = new TxProviderUtil(this.provider) - this.pendingTxUtils = new PendingTransactionUtils({ + this.pendingTxWatcher = new PendingTransactionWatchers({ provider: this.provider, nonceTracker: this.nonceTracker, getBalance: (address) => this.ethStore.getState().accounts[address].balance, @@ -50,16 +50,16 @@ module.exports = class TransactionController extends EventEmitter { }, }) - this.pendingTxUtils.on('txWarning', this.updateTx.bind(this)) - this.pendingTxUtils.on('txFailed', this.setTxStatusFailed.bind(this)) - this.pendingTxUtils.on('txConfirmed', this.setTxStatusConfirmed.bind(this)) + this.pendingTxWatcher.on('txWarning', this.updateTx.bind(this)) + this.pendingTxWatcher.on('txFailed', this.setTxStatusFailed.bind(this)) + this.pendingTxWatcher.on('txConfirmed', this.setTxStatusConfirmed.bind(this)) - this.blockTracker.on('rawBlock', this.pendingTxUtils.checkForTxInBlock.bind(this)) + this.blockTracker.on('rawBlock', this.pendingTxWatcher.checkForTxInBlock.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.pendingTxUtils.resubmitPendingTxs.bind(this))) - this.blockTracker.on('sync', this.pendingTxUtils.queryPendingTxs.bind(this)) + this.blockTracker.once('latest', () => this.blockTracker.on('latest', this.pendingTxWatcher.resubmitPendingTxs.bind(this))) + this.blockTracker.on('sync', this.pendingTxWatcher.queryPendingTxs.bind(this)) // memstore is computed from a few different stores this._updateMemstore() this.store.subscribe(() => this._updateMemstore()) -- cgit v1.2.3 From fb9866b4e10c823e987d4cee9fc499673d664a8a Mon Sep 17 00:00:00 2001 From: frankiebee Date: Mon, 7 Aug 2017 14:37:20 -0400 Subject: fix spelling --- app/scripts/controllers/transactions.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index c1a0ef0f3..bc8e5b729 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -4,7 +4,7 @@ const clone = require('clone') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') const EthQuery = require('ethjs-query') -const TxProviderUtil = require('../lib/tx-utils') +const TxProviderUtils = require('../lib/tx-utils') const PendingTransactionWatchers = require('../lib/pending-tx-watchers') const createId = require('../lib/random-id') const NonceTracker = require('../lib/nonce-tracker') @@ -35,9 +35,9 @@ module.exports = class TransactionController extends EventEmitter { }, }) this.query = new EthQuery(this.provider) - this.txProviderUtils = new TxProviderUtil(this.provider) + this.txProviderUtils = new TxProviderUtils(this.provider) - this.pendingTxWatcher = new PendingTransactionWatchers({ + this.pendingTxWatchers = new PendingTransactionWatchers({ provider: this.provider, nonceTracker: this.nonceTracker, getBalance: (address) => this.ethStore.getState().accounts[address].balance, @@ -50,16 +50,16 @@ module.exports = class TransactionController extends EventEmitter { }, }) - this.pendingTxWatcher.on('txWarning', this.updateTx.bind(this)) - this.pendingTxWatcher.on('txFailed', this.setTxStatusFailed.bind(this)) - this.pendingTxWatcher.on('txConfirmed', this.setTxStatusConfirmed.bind(this)) + this.pendingTxWatchers.on('txWarning', this.updateTx.bind(this)) + this.pendingTxWatchers.on('txFailed', this.setTxStatusFailed.bind(this)) + this.pendingTxWatchers.on('txConfirmed', this.setTxStatusConfirmed.bind(this)) - this.blockTracker.on('rawBlock', this.pendingTxWatcher.checkForTxInBlock.bind(this)) + this.blockTracker.on('rawBlock', this.pendingTxWatchers.checkForTxInBlock.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.pendingTxWatcher.resubmitPendingTxs.bind(this))) - this.blockTracker.on('sync', this.pendingTxWatcher.queryPendingTxs.bind(this)) + this.blockTracker.once('latest', () => this.blockTracker.on('latest', this.pendingTxWatchers.resubmitPendingTxs.bind(this))) + this.blockTracker.on('sync', this.pendingTxWatchers.queryPendingTxs.bind(this)) // memstore is computed from a few different stores this._updateMemstore() this.store.subscribe(() => this._updateMemstore()) -- cgit v1.2.3 From a54c26382e4e5d4e4fec543ac4e0ca90d0d91191 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Mon, 7 Aug 2017 14:40:07 -0400 Subject: remove unnecessary if statment for error message --- app/scripts/controllers/transactions.js | 1 - 1 file changed, 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index bc8e5b729..efc8d7117 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -246,7 +246,6 @@ module.exports = class TransactionController extends EventEmitter { // must set transaction to submitted/failed before releasing lock nonceLock.releaseLock() } catch (err) { - if (!err.message) err.message = 'Transaction failed during approval' this.setTxStatusFailed(txId, err) // must set transaction to submitted/failed before releasing lock if (nonceLock) nonceLock.releaseLock() -- cgit v1.2.3 From 3a2190ec3cac0211d37dab6434d29f7bb484d4c4 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Mon, 7 Aug 2017 16:57:17 -0400 Subject: fix the bind on pending tx watchers --- app/scripts/controllers/transactions.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index efc8d7117..cf987db91 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -54,12 +54,12 @@ module.exports = class TransactionController extends EventEmitter { this.pendingTxWatchers.on('txFailed', this.setTxStatusFailed.bind(this)) this.pendingTxWatchers.on('txConfirmed', this.setTxStatusConfirmed.bind(this)) - this.blockTracker.on('rawBlock', this.pendingTxWatchers.checkForTxInBlock.bind(this)) + this.blockTracker.on('rawBlock', this.pendingTxWatchers.checkForTxInBlock.bind(this.pendingTxWatchers)) // 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.pendingTxWatchers.resubmitPendingTxs.bind(this))) - this.blockTracker.on('sync', this.pendingTxWatchers.queryPendingTxs.bind(this)) + this.blockTracker.once('latest', () => this.blockTracker.on('latest', this.pendingTxWatchers.resubmitPendingTxs.bind(this.pendingTxWatchers))) + this.blockTracker.on('sync', this.pendingTxWatchers.queryPendingTxs.bind(this.pendingTxWatchers)) // memstore is computed from a few different stores this._updateMemstore() this.store.subscribe(() => this._updateMemstore()) -- cgit v1.2.3 From a13643bdb545af60bd4514c9026e9657ce8aa5ea Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 8 Aug 2017 18:30:49 -0400 Subject: fix class names --- app/scripts/controllers/transactions.js | 38 +++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 16 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index cf987db91..664dbff6b 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -4,8 +4,8 @@ const clone = require('clone') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') const EthQuery = require('ethjs-query') -const TxProviderUtils = require('../lib/tx-utils') -const PendingTransactionWatchers = require('../lib/pending-tx-watchers') +const TxProviderUtil = require('../lib/tx-utils') +const PendingTransactionTracker = require('../lib/pending-tx-tracker') const createId = require('../lib/random-id') const NonceTracker = require('../lib/nonce-tracker') @@ -35,13 +35,17 @@ module.exports = class TransactionController extends EventEmitter { }, }) this.query = new EthQuery(this.provider) - this.txProviderUtils = new TxProviderUtils(this.provider) + this.txProviderUtil = new TxProviderUtil(this.provider) - this.pendingTxWatchers = new PendingTransactionWatchers({ + this.pendingTxTracker = new PendingTransactionTracker({ provider: this.provider, nonceTracker: this.nonceTracker, - getBalance: (address) => this.ethStore.getState().accounts[address].balance, - publishTransaction: this.txProviderUtils.publishTransaction.bind(this.txProviderUtils), + getBalance: async (address) => { + const account = this.ethStore.getState().accounts[address] + if (!account) return + return account.balance + }, + publishTransaction: this.txProviderUtil.publishTransaction.bind(this.txProviderUtil), getPendingTransactions: (address) => { return this.getFilteredTxList({ from: address, @@ -50,16 +54,18 @@ module.exports = class TransactionController extends EventEmitter { }, }) - this.pendingTxWatchers.on('txWarning', this.updateTx.bind(this)) - this.pendingTxWatchers.on('txFailed', this.setTxStatusFailed.bind(this)) - this.pendingTxWatchers.on('txConfirmed', this.setTxStatusConfirmed.bind(this)) + this.pendingTxTracker.on('txWarning', this.updateTx.bind(this)) + this.pendingTxTracker.on('txFailed', this.setTxStatusFailed.bind(this)) + this.pendingTxTracker.on('txConfirmed', this.setTxStatusConfirmed.bind(this)) - this.blockTracker.on('rawBlock', this.pendingTxWatchers.checkForTxInBlock.bind(this.pendingTxWatchers)) + this.blockTracker.on('rawBlock', this.pendingTxTracker.checkForTxInBlock.bind(this.pendingTxTracker)) // 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.pendingTxWatchers.resubmitPendingTxs.bind(this.pendingTxWatchers))) - this.blockTracker.on('sync', this.pendingTxWatchers.queryPendingTxs.bind(this.pendingTxWatchers)) + this.blockTracker.once('latest', () => { + this.blockTracker.on('latest', this.pendingTxTracker.resubmitPendingTxs.bind(this.pendingTxTracker)) + }) + this.blockTracker.on('sync', this.pendingTxTracker.queryPendingTxs.bind(this.pendingTxTracker)) // memstore is computed from a few different stores this._updateMemstore() this.store.subscribe(() => this._updateMemstore()) @@ -191,7 +197,7 @@ module.exports = class TransactionController extends EventEmitter { async addUnapprovedTransaction (txParams) { // validate - await this.txProviderUtils.validateTxParams(txParams) + await this.txProviderUtil.validateTxParams(txParams) // construct txMeta const txMeta = { id: createId(), @@ -217,7 +223,7 @@ module.exports = class TransactionController extends EventEmitter { txParams.gasPrice = gasPrice } // set gasLimit - return await this.txProviderUtils.analyzeGasUsage(txMeta) + return await this.txProviderUtil.analyzeGasUsage(txMeta) } async updateAndApproveTransaction (txMeta) { @@ -260,7 +266,7 @@ module.exports = class TransactionController extends EventEmitter { const fromAddress = txParams.from // add network/chain id txParams.chainId = this.getChainId() - const ethTx = this.txProviderUtils.buildEthTxFromParams(txParams) + const ethTx = this.txProviderUtil.buildEthTxFromParams(txParams) await this.signEthTx(ethTx, fromAddress) this.setTxStatusSigned(txMeta.id) const rawTx = ethUtil.bufferToHex(ethTx.serialize()) @@ -271,7 +277,7 @@ module.exports = class TransactionController extends EventEmitter { const txMeta = this.getTx(txId) txMeta.rawTx = rawTx this.updateTx(txMeta) - const txHash = await this.txProviderUtils.publishTransaction(rawTx) + const txHash = await this.txProviderUtil.publishTransaction(rawTx) this.setTxHash(txId, txHash) this.setTxStatusSubmitted(txId) } -- cgit v1.2.3 From 5bb84f6e21842b9ac860be48c0ddc322d654559b Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 8 Aug 2017 21:49:48 -0400 Subject: fix getPendingTransactions function for pendingTxTracker --- app/scripts/controllers/transactions.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 664dbff6b..542881b8f 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -46,9 +46,8 @@ module.exports = class TransactionController extends EventEmitter { return account.balance }, publishTransaction: this.txProviderUtil.publishTransaction.bind(this.txProviderUtil), - getPendingTransactions: (address) => { + getPendingTransactions: () => { return this.getFilteredTxList({ - from: address, status: 'submitted', }) }, -- cgit v1.2.3 From 9c9165e930684b53d525d6bced6df1a76030253b Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 8 Aug 2017 21:54:26 -0400 Subject: filter by network for pending txs --- app/scripts/controllers/transactions.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 542881b8f..28130c164 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -47,8 +47,10 @@ module.exports = class TransactionController extends EventEmitter { }, publishTransaction: this.txProviderUtil.publishTransaction.bind(this.txProviderUtil), getPendingTransactions: () => { + const network = this.getNetwork() return this.getFilteredTxList({ status: 'submitted', + metamaskNetworkId: network, }) }, }) -- cgit v1.2.3 From 5e6962342df488073de61314fa4dfae9b7870fb8 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 8 Aug 2017 21:08:30 -0700 Subject: tx controller - fix getBalance fn --- app/scripts/controllers/transactions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 28130c164..8b5c6dde2 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -40,7 +40,7 @@ module.exports = class TransactionController extends EventEmitter { this.pendingTxTracker = new PendingTransactionTracker({ provider: this.provider, nonceTracker: this.nonceTracker, - getBalance: async (address) => { + getBalance: (address) => { const account = this.ethStore.getState().accounts[address] if (!account) return return account.balance -- cgit v1.2.3 From 25f9746dabb4ecc736a5cdd7b01b2d8a6c8151de Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 8 Aug 2017 21:09:28 -0700 Subject: tx controller - fix error serialization --- app/scripts/controllers/transactions.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 8b5c6dde2..58c468e22 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -382,9 +382,12 @@ module.exports = class TransactionController extends EventEmitter { this._setTxStatus(txId, 'confirmed') } - setTxStatusFailed (txId, reason) { + setTxStatusFailed (txId, err) { const txMeta = this.getTx(txId) - txMeta.err = reason + txMeta.err = { + message: err.toString(), + stack: err.stack, + } this.updateTx(txMeta) this._setTxStatus(txId, 'failed') } -- cgit v1.2.3 From fdffb6fedc6a29a2f952f7db669bdc2907afb854 Mon Sep 17 00:00:00 2001 From: kumavis Date: Mon, 14 Aug 2017 18:46:04 -0700 Subject: introduce tx-state-history-helper and diff-based history --- app/scripts/controllers/transactions.js | 34 ++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 58c468e22..872d11b50 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -8,6 +8,7 @@ const TxProviderUtil = require('../lib/tx-utils') const PendingTransactionTracker = require('../lib/pending-tx-tracker') const createId = require('../lib/random-id') const NonceTracker = require('../lib/nonce-tracker') +const txStateHistoryHelper = require('../lib/tx-state-history-helper') module.exports = class TransactionController extends EventEmitter { constructor (opts) { @@ -128,19 +129,17 @@ module.exports = class TransactionController extends EventEmitter { updateTx (txMeta) { // create txMeta snapshot for history - const txMetaForHistory = clone(txMeta) - // dont include previous history in this snapshot - delete txMetaForHistory.history - // add snapshot to tx history - if (!txMeta.history) txMeta.history = [] - txMeta.history.push(txMetaForHistory) - + const currentState = txStateHistoryHelper.snapshotFromTxMeta(txMeta) + // recover previous tx state obj + const previousState = txStateHistoryHelper.replayHistory(txMeta.history) + // generate history entry and add to history + const entry = txStateHistoryHelper.generateHistoryEntry(previousState, currentState) + txMeta.history.push(entry) + + // commit txMeta to state const txId = txMeta.id const txList = this.getFullTxList() const index = txList.findIndex(txData => txData.id === txId) - if (!txMeta.history) txMeta.history = [] - txMeta.history.push(txMetaForHistory) - txList[index] = txMeta this._saveTxList(txList) this.emit('update') @@ -148,16 +147,22 @@ module.exports = class TransactionController extends EventEmitter { // Adds a tx to the txlist addTx (txMeta) { - const txCount = this.getTxCount() - const network = this.getNetwork() - const fullTxList = this.getFullTxList() - const txHistoryLimit = this.txHistoryLimit + // initialize history + txMeta.history = [] + // capture initial snapshot of txMeta for history + const snapshot = txStateHistoryHelper.snapshotFromTxMeta(txMeta) + txMeta.history.push(snapshot) // checks if the length of the tx history is // longer then desired persistence limit // and then if it is removes only confirmed // or rejected tx's. // not tx's that are pending or unapproved + const txCount = this.getTxCount() + const network = this.getNetwork() + const fullTxList = this.getFullTxList() + const txHistoryLimit = this.txHistoryLimit + if (txCount > txHistoryLimit - 1) { const index = fullTxList.findIndex((metaTx) => ((metaTx.status === 'confirmed' || metaTx.status === 'rejected') && network === txMeta.metamaskNetworkId)) fullTxList.splice(index, 1) @@ -206,7 +211,6 @@ module.exports = class TransactionController extends EventEmitter { status: 'unapproved', metamaskNetworkId: this.getNetwork(), txParams: txParams, - history: [], } // add default tx params await this.addTxDefaults(txMeta) -- cgit v1.2.3 From 1af797b1b3a37d8fe00afbd0d84cb3349b8fd471 Mon Sep 17 00:00:00 2001 From: kumavis Date: Mon, 14 Aug 2017 19:15:36 -0700 Subject: tx controller - tx state history various small fixes --- app/scripts/controllers/transactions.js | 1 - 1 file changed, 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 872d11b50..1bcee60ab 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -1,6 +1,5 @@ const EventEmitter = require('events') const extend = require('xtend') -const clone = require('clone') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') const EthQuery = require('ethjs-query') -- cgit v1.2.3 From a5a32f3d5742972586893741847ea4516afa19ac Mon Sep 17 00:00:00 2001 From: frankiebee Date: Fri, 18 Aug 2017 13:54:16 -0700 Subject: use "localNonce" when the network returns a nonce that is lower then a known confirmed tx --- app/scripts/controllers/transactions.js | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 58c468e22..f21cb6e00 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -33,6 +33,13 @@ module.exports = class TransactionController extends EventEmitter { err: undefined, }) }, + getConfirmedTransactions: (address) => { + return this.getFilteredTxList({ + from: address, + status: 'confirmed', + err: undefined, + }) + }, }) this.query = new EthQuery(this.provider) this.txProviderUtil = new TxProviderUtil(this.provider) -- cgit v1.2.3 From e9712a13ecd96db0bcc9d22998fc4df2ecdeeebc Mon Sep 17 00:00:00 2001 From: frankiebee Date: Fri, 11 Aug 2017 14:19:35 -0700 Subject: Create tests for TxStateManager --- app/scripts/controllers/transactions.js | 209 +++----------------------------- 1 file changed, 17 insertions(+), 192 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 58c468e22..48a882a71 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -4,6 +4,7 @@ const clone = require('clone') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') const EthQuery = require('ethjs-query') +const TransactionStateManger = require('../lib/tx-state-manager') const TxProviderUtil = require('../lib/tx-utils') const PendingTransactionTracker = require('../lib/pending-tx-tracker') const createId = require('../lib/random-id') @@ -12,18 +13,23 @@ const NonceTracker = require('../lib/nonce-tracker') module.exports = class TransactionController extends EventEmitter { constructor (opts) { super() - this.store = new ObservableStore(extend({ - transactions: [], - }, opts.initState)) - this.memStore = new ObservableStore({}) this.networkStore = opts.networkStore || new ObservableStore({}) this.preferencesStore = opts.preferencesStore || new ObservableStore({}) - this.txHistoryLimit = opts.txHistoryLimit this.provider = opts.provider this.blockTracker = opts.blockTracker this.signEthTx = opts.signTransaction this.ethStore = opts.ethStore + this.memStore = new ObservableStore({}) + this.query = new EthQuery(this.provider) + this.txProviderUtil = new TxProviderUtil(this.provider) + + this.txStateManager = new TransactionStateManger(extend({ + transactions: [], + txHistoryLimit: opts.txHistoryLimit, + getNetwork: this.getNetwork.bind(this), + }, opts.initState)) + this.nonceTracker = new NonceTracker({ provider: this.provider, getPendingTransactions: (address) => { @@ -34,8 +40,6 @@ module.exports = class TransactionController extends EventEmitter { }) }, }) - this.query = new EthQuery(this.provider) - this.txProviderUtil = new TxProviderUtil(this.provider) this.pendingTxTracker = new PendingTransactionTracker({ provider: this.provider, @@ -69,7 +73,7 @@ module.exports = class TransactionController extends EventEmitter { this.blockTracker.on('sync', this.pendingTxTracker.queryPendingTxs.bind(this.pendingTxTracker)) // memstore is computed from a few different stores this._updateMemstore() - this.store.subscribe(() => this._updateMemstore()) + this.txStateManager.subscribe(() => this._updateMemstore()) this.networkStore.subscribe(() => this._updateMemstore()) this.preferencesStore.subscribe(() => this._updateMemstore()) } @@ -86,84 +90,27 @@ module.exports = class TransactionController extends EventEmitter { return this.preferencesStore.getState().selectedAddress } - // Returns the number of txs for the current network. - getTxCount () { - return this.getTxList().length - } - - // Returns the full tx list across all networks - getFullTxList () { - return this.store.getState().transactions - } - getUnapprovedTxCount () { return Object.keys(this.getUnapprovedTxList()).length } getPendingTxCount () { - return this.getTxsByMetaData('status', 'signed').length + return this.txStateManager.getTxsByMetaData('status', 'signed').length } // Returns the tx list - getTxList () { - const network = this.getNetwork() - const fullTxList = this.getFullTxList() - return this.getTxsByMetaData('metamaskNetworkId', network, fullTxList) - } - // gets tx by Id and returns it - getTx (txId) { - const txList = this.getTxList() - const txMeta = txList.find(txData => txData.id === txId) - return txMeta - } getUnapprovedTxList () { - const txList = this.getTxList() - return txList.filter((txMeta) => txMeta.status === 'unapproved') - .reduce((result, tx) => { + const txList = this.txStateManager.getTxsByMetaData('status', 'unapproved') + return txList.reduce((result, tx) => { result[tx.id] = tx return result }, {}) } - updateTx (txMeta) { - // create txMeta snapshot for history - const txMetaForHistory = clone(txMeta) - // dont include previous history in this snapshot - delete txMetaForHistory.history - // add snapshot to tx history - if (!txMeta.history) txMeta.history = [] - txMeta.history.push(txMetaForHistory) - - const txId = txMeta.id - const txList = this.getFullTxList() - const index = txList.findIndex(txData => txData.id === txId) - if (!txMeta.history) txMeta.history = [] - txMeta.history.push(txMetaForHistory) - - txList[index] = txMeta - this._saveTxList(txList) - this.emit('update') - } - // Adds a tx to the txlist addTx (txMeta) { - const txCount = this.getTxCount() - const network = this.getNetwork() - const fullTxList = this.getFullTxList() - const txHistoryLimit = this.txHistoryLimit - - // checks if the length of the tx history is - // longer then desired persistence limit - // and then if it is removes only confirmed - // or rejected tx's. - // not tx's that are pending or unapproved - if (txCount > txHistoryLimit - 1) { - const index = fullTxList.findIndex((metaTx) => ((metaTx.status === 'confirmed' || metaTx.status === 'rejected') && network === txMeta.metamaskNetworkId)) - fullTxList.splice(index, 1) - } - fullTxList.push(txMeta) - this._saveTxList(fullTxList) + this.txStateManager.addTx(txMeta) this.emit('update') this.once(`${txMeta.id}:signed`, function (txId) { @@ -211,7 +158,7 @@ module.exports = class TransactionController extends EventEmitter { // add default tx params await this.addTxDefaults(txMeta) // save txMeta - this.addTx(txMeta) + this.txStateManager.addTx(txMeta) return txMeta } @@ -306,133 +253,11 @@ module.exports = class TransactionController extends EventEmitter { this.updateTx(txMeta) } - /* - Takes an object of fields to search for eg: - let thingsToLookFor = { - to: '0x0..', - from: '0x0..', - status: 'signed', - err: undefined, - } - and returns a list of tx with all - options matching - - ****************HINT**************** - | `err: undefined` is like looking | - | for a tx with no err | - | so you can also search txs that | - | dont have something as well by | - | setting the value as undefined | - ************************************ - - this is for things like filtering a the tx list - for only tx's from 1 account - or for filltering for all txs from one account - and that have been 'confirmed' - */ - getFilteredTxList (opts) { - let filteredTxList - Object.keys(opts).forEach((key) => { - filteredTxList = this.getTxsByMetaData(key, opts[key], filteredTxList) - }) - return filteredTxList - } - - getTxsByMetaData (key, value, txList = this.getTxList()) { - return txList.filter((txMeta) => { - if (txMeta.txParams[key]) { - return txMeta.txParams[key] === value - } else { - return txMeta[key] === value - } - }) - } - - // STATUS METHODS - // get::set status - - // should return the status of the tx. - getTxStatus (txId) { - const txMeta = this.getTx(txId) - return txMeta.status - } - - // should update the status of the tx to 'rejected'. - setTxStatusRejected (txId) { - this._setTxStatus(txId, 'rejected') - } - - // should update the status of the tx to 'approved'. - setTxStatusApproved (txId) { - this._setTxStatus(txId, 'approved') - } - - // should update the status of the tx to 'signed'. - setTxStatusSigned (txId) { - this._setTxStatus(txId, 'signed') - } - - // should update the status of the tx to 'submitted'. - setTxStatusSubmitted (txId) { - this._setTxStatus(txId, 'submitted') - } - - // should update the status of the tx to 'confirmed'. - setTxStatusConfirmed (txId) { - this._setTxStatus(txId, 'confirmed') - } - - setTxStatusFailed (txId, err) { - const txMeta = this.getTx(txId) - txMeta.err = { - message: err.toString(), - stack: err.stack, - } - this.updateTx(txMeta) - this._setTxStatus(txId, 'failed') - } - - // merges txParams obj onto txData.txParams - // use extend to ensure that all fields are filled - updateTxParams (txId, txParams) { - const txMeta = this.getTx(txId) - txMeta.txParams = extend(txMeta.txParams, txParams) - this.updateTx(txMeta) - } - /* _____________________________________ | | | PRIVATE METHODS | |______________________________________*/ - - // Should find the tx in the tx list and - // update it. - // should set the status in txData - // - `'unapproved'` the user has not responded - // - `'rejected'` the user has responded no! - // - `'approved'` the user has approved the tx - // - `'signed'` the tx is signed - // - `'submitted'` the tx is sent to a server - // - `'confirmed'` the tx has been included in a block. - // - `'failed'` the tx failed for some reason, included on tx data. - _setTxStatus (txId, status) { - const txMeta = this.getTx(txId) - txMeta.status = status - this.emit(`${txMeta.id}:${status}`, txId) - if (status === 'submitted' || status === 'rejected') { - this.emit(`${txMeta.id}:finished`, txMeta) - } - this.updateTx(txMeta) - this.emit('updateBadge') - } - - // Saves the new/updated txList. - // Function is intended only for internal use - _saveTxList (transactions) { - this.store.updateState({ transactions }) - } - _updateMemstore () { const unapprovedTxs = this.getUnapprovedTxList() const selectedAddressTxList = this.getFilteredTxList({ -- cgit v1.2.3 From 7ea83b6bae34dcf652d85474fe1d82893d592d55 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Fri, 18 Aug 2017 12:23:35 -0700 Subject: Create TxStateManager --- app/scripts/controllers/transactions.js | 73 +++++++++++++-------------------- 1 file changed, 28 insertions(+), 45 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 48a882a71..b044948d7 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -1,6 +1,5 @@ const EventEmitter = require('events') const extend = require('xtend') -const clone = require('clone') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') const EthQuery = require('ethjs-query') @@ -24,16 +23,18 @@ module.exports = class TransactionController extends EventEmitter { this.query = new EthQuery(this.provider) this.txProviderUtil = new TxProviderUtil(this.provider) - this.txStateManager = new TransactionStateManger(extend({ - transactions: [], + this.txStateManager = new TransactionStateManger({ + initState: extend({ + transactions: [], + }, opts.initState), txHistoryLimit: opts.txHistoryLimit, getNetwork: this.getNetwork.bind(this), - }, opts.initState)) + }) this.nonceTracker = new NonceTracker({ provider: this.provider, getPendingTransactions: (address) => { - return this.getFilteredTxList({ + return this.txStateManager.getFilteredTxList({ from: address, status: 'submitted', err: undefined, @@ -52,16 +53,16 @@ module.exports = class TransactionController extends EventEmitter { publishTransaction: this.txProviderUtil.publishTransaction.bind(this.txProviderUtil), getPendingTransactions: () => { const network = this.getNetwork() - return this.getFilteredTxList({ + return this.txStateManager.getFilteredTxList({ status: 'submitted', metamaskNetworkId: network, }) }, }) - this.pendingTxTracker.on('txWarning', this.updateTx.bind(this)) - this.pendingTxTracker.on('txFailed', this.setTxStatusFailed.bind(this)) - this.pendingTxTracker.on('txConfirmed', this.setTxStatusConfirmed.bind(this)) + this.pendingTxTracker.on('txWarning', this.txStateManager.updateTx.bind(this.txStateManager)) + this.pendingTxTracker.on('txFailed', this.txStateManager.setTxStatusFailed.bind(this.txStateManager)) + this.pendingTxTracker.on('txConfirmed', this.txStateManager.setTxStatusConfirmed.bind(this.txStateManager)) this.blockTracker.on('rawBlock', this.pendingTxTracker.checkForTxInBlock.bind(this.pendingTxTracker)) // this is a little messy but until ethstore has been either @@ -91,35 +92,17 @@ module.exports = class TransactionController extends EventEmitter { } getUnapprovedTxCount () { - return Object.keys(this.getUnapprovedTxList()).length + return Object.keys(this.txStateManager.getUnapprovedTxList()).length } getPendingTxCount () { return this.txStateManager.getTxsByMetaData('status', 'signed').length } - // Returns the tx list - - getUnapprovedTxList () { - const txList = this.txStateManager.getTxsByMetaData('status', 'unapproved') - return txList.reduce((result, tx) => { - result[tx.id] = tx - return result - }, {}) - } - // Adds a tx to the txlist addTx (txMeta) { this.txStateManager.addTx(txMeta) this.emit('update') - - this.once(`${txMeta.id}:signed`, function (txId) { - this.removeAllListeners(`${txMeta.id}:rejected`) - }) - this.once(`${txMeta.id}:rejected`, function (txId) { - this.removeAllListeners(`${txMeta.id}:signed`) - }) - this.emit('updateBadge') this.emit(`${txMeta.id}:unapproved`, txMeta) } @@ -130,7 +113,7 @@ module.exports = class TransactionController extends EventEmitter { this.emit('newUnaprovedTx', txMeta) // listen for tx completion (success, fail) return new Promise((resolve, reject) => { - this.once(`${txMeta.id}:finished`, (completedTx) => { + this.txStateManager.once(`${txMeta.id}:finished`, (completedTx) => { switch (completedTx.status) { case 'submitted': return resolve(completedTx.hash) @@ -158,7 +141,7 @@ module.exports = class TransactionController extends EventEmitter { // add default tx params await this.addTxDefaults(txMeta) // save txMeta - this.txStateManager.addTx(txMeta) + this.addTx(txMeta) return txMeta } @@ -175,7 +158,7 @@ module.exports = class TransactionController extends EventEmitter { } async updateAndApproveTransaction (txMeta) { - this.updateTx(txMeta) + this.txStateManager.updateTx(txMeta) await this.approveTransaction(txMeta.id) } @@ -183,9 +166,9 @@ module.exports = class TransactionController extends EventEmitter { let nonceLock try { // approve - this.setTxStatusApproved(txId) + this.txStateManager.setTxStatusApproved(txId) // get next nonce - const txMeta = this.getTx(txId) + const txMeta = this.txStateManager.getTx(txId) const fromAddress = txMeta.txParams.from // wait for a nonce nonceLock = await this.nonceTracker.getNonceLock(fromAddress) @@ -193,14 +176,14 @@ module.exports = class TransactionController extends EventEmitter { txMeta.txParams.nonce = nonceLock.nextNonce // add nonce debugging information to txMeta txMeta.nonceDetails = nonceLock.nonceDetails - this.updateTx(txMeta) + this.txStateManager.updateTx(txMeta) // sign transaction const rawTx = await this.signTransaction(txId) await this.publishTransaction(txId, rawTx) // must set transaction to submitted/failed before releasing lock nonceLock.releaseLock() } catch (err) { - this.setTxStatusFailed(txId, err) + this.txStateManager.setTxStatusFailed(txId, err) // must set transaction to submitted/failed before releasing lock if (nonceLock) nonceLock.releaseLock() // continue with error chain @@ -209,29 +192,29 @@ module.exports = class TransactionController extends EventEmitter { } async signTransaction (txId) { - const txMeta = this.getTx(txId) + const txMeta = this.txStateManager.getTx(txId) const txParams = txMeta.txParams const fromAddress = txParams.from // add network/chain id txParams.chainId = this.getChainId() const ethTx = this.txProviderUtil.buildEthTxFromParams(txParams) await this.signEthTx(ethTx, fromAddress) - this.setTxStatusSigned(txMeta.id) + this.txStateManager.setTxStatusSigned(txMeta.id) const rawTx = ethUtil.bufferToHex(ethTx.serialize()) return rawTx } async publishTransaction (txId, rawTx) { - const txMeta = this.getTx(txId) + const txMeta = this.txStateManager.getTx(txId) txMeta.rawTx = rawTx - this.updateTx(txMeta) + this.txStateManager.updateTx(txMeta) const txHash = await this.txProviderUtil.publishTransaction(rawTx) this.setTxHash(txId, txHash) - this.setTxStatusSubmitted(txId) + this.txStateManager.setTxStatusSubmitted(txId) } async cancelTransaction (txId) { - this.setTxStatusRejected(txId) + this.txStateManager.setTxStatusRejected(txId) } @@ -248,9 +231,9 @@ module.exports = class TransactionController extends EventEmitter { // receives a txHash records the tx as signed setTxHash (txId, txHash) { // Add the tx hash to the persisted meta-tx object - const txMeta = this.getTx(txId) + const txMeta = this.txStateManager.getTx(txId) txMeta.hash = txHash - this.updateTx(txMeta) + this.txStateManager.updateTx(txMeta) } /* _____________________________________ @@ -259,8 +242,8 @@ module.exports = class TransactionController extends EventEmitter { |______________________________________*/ _updateMemstore () { - const unapprovedTxs = this.getUnapprovedTxList() - const selectedAddressTxList = this.getFilteredTxList({ + const unapprovedTxs = this.txStateManager.getUnapprovedTxList() + const selectedAddressTxList = this.txStateManager.getFilteredTxList({ from: this.getSelectedAddress(), metamaskNetworkId: this.getNetwork(), }) -- cgit v1.2.3 From 0ad310e096fe8c13553dc40f65363d296a7e84ce Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 23 Aug 2017 22:29:08 -0700 Subject: Fail transactions after a day of retries --- app/scripts/controllers/transactions.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 6f49c9633..fb3be6073 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -40,6 +40,10 @@ module.exports = class TransactionController extends EventEmitter { err: undefined, }) }, + giveUpOnTransaction: (txId) => { + const msg = `Gave up submitting after 3500 blocks un-mined.` + this.setTxStatusFailed(txId, msg) + }, }) this.query = new EthQuery(this.provider) this.txProviderUtil = new TxProviderUtil(this.provider) @@ -451,4 +455,4 @@ module.exports = class TransactionController extends EventEmitter { }) this.memStore.updateState({ unapprovedTxs, selectedAddressTxList }) } -} \ No newline at end of file +} -- cgit v1.2.3 From 15c12ca4bb6996f43518630ded12c0d7be2d571b Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 5 Sep 2017 21:50:36 -0700 Subject: add better comments --- app/scripts/controllers/transactions.js | 72 +++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 31 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 2349be1ad..6c4701283 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -2,13 +2,29 @@ const EventEmitter = require('events') const extend = require('xtend') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') +const Transaction = require('ethereumjs-tx') const EthQuery = require('ethjs-query') const TransactionStateManger = require('../lib/tx-state-manager') -const TxProviderUtil = require('../lib/tx-utils') +const TxGasUtil = require('../lib/tx-gas-utils') const PendingTransactionTracker = require('../lib/pending-tx-tracker') const createId = require('../lib/random-id') const NonceTracker = require('../lib/nonce-tracker') +/* + Transaction Controller is an aggregate of sub-controllers and trackers + composing them in a way to be exposed to the metamask controller + - txStateManager + responsible for the state of a transaction and + storing the transaction + - pendingTxTracker + watching blocks for transactions to be include + and emitting confirmed events + - txGasUtil + gas calculations and safety buffering + - nonceTracker + calculating nonces +*/ + module.exports = class TransactionController extends EventEmitter { constructor (opts) { super() @@ -21,7 +37,7 @@ module.exports = class TransactionController extends EventEmitter { this.memStore = new ObservableStore({}) this.query = new EthQuery(this.provider) - this.txProviderUtil = new TxProviderUtil(this.provider) + this.txGasUtil = new TxGasUtil(this.provider) this.txStateManager = new TransactionStateManger({ initState: extend({ @@ -37,7 +53,6 @@ module.exports = class TransactionController extends EventEmitter { return this.txStateManager.getFilteredTxList({ from: address, status: 'submitted', - err: undefined, }) }, }) @@ -50,16 +65,17 @@ module.exports = class TransactionController extends EventEmitter { if (!account) return return account.balance }, - publishTransaction: this.txProviderUtil.publishTransaction.bind(this.txProviderUtil), + publishTransaction: this.query.sendRawTransaction, getPendingTransactions: () => { - const network = this.getNetwork() - return this.txStateManager.getFilteredTxList({ - status: 'submitted', - metamaskNetworkId: network, - }) + return this.txStateManager.getFilteredTxList({ status: 'submitted' }) }, }) + this.txStateManager.subscribe(() => { + this.emit('update') + this.emit('updateBadge') + }) + this.pendingTxTracker.on('txWarning', this.txStateManager.updateTx.bind(this.txStateManager)) this.pendingTxTracker.on('txFailed', this.txStateManager.setTxStatusFailed.bind(this.txStateManager)) this.pendingTxTracker.on('txConfirmed', this.txStateManager.setTxStatusConfirmed.bind(this.txStateManager)) @@ -99,11 +115,19 @@ module.exports = class TransactionController extends EventEmitter { return this.txStateManager.getTxsByMetaData('status', 'signed').length } + getChainId () { + const networkState = this.networkStore.getState() + const getChainId = parseInt(networkState) + if (Number.isNaN(getChainId)) { + return 0 + } else { + return getChainId + } + } + // Adds a tx to the txlist addTx (txMeta) { this.txStateManager.addTx(txMeta) - this.emit('update') - this.emit('updateBadge') this.emit(`${txMeta.id}:unapproved`, txMeta) } @@ -114,7 +138,6 @@ module.exports = class TransactionController extends EventEmitter { // listen for tx completion (success, fail) return new Promise((resolve, reject) => { this.txStateManager.once(`${txMeta.id}:finished`, (completedTx) => { - this.emit('updateBadge') switch (completedTx.status) { case 'submitted': return resolve(completedTx.hash) @@ -129,7 +152,7 @@ module.exports = class TransactionController extends EventEmitter { async addUnapprovedTransaction (txParams) { // validate - await this.txProviderUtil.validateTxParams(txParams) + await this.txGasUtil.validateTxParams(txParams) // construct txMeta const txMeta = { id: createId(), @@ -148,13 +171,11 @@ module.exports = class TransactionController extends EventEmitter { async addTxDefaults (txMeta) { const txParams = txMeta.txParams // ensure value + const gasPrice = txParams.gasPrice || await this.query.gasPrice() txParams.value = txParams.value || '0x0' - if (!txParams.gasPrice) { - const gasPrice = await this.query.gasPrice() - txParams.gasPrice = gasPrice - } + txParams.gasPrice = ethUtil.addHexPrefix(gasPrice.toString(16)) // set gasLimit - return await this.txProviderUtil.analyzeGasUsage(txMeta) + return await this.txGasUtil.analyzeGasUsage(txMeta) } async updateAndApproveTransaction (txMeta) { @@ -197,7 +218,7 @@ module.exports = class TransactionController extends EventEmitter { const fromAddress = txParams.from // add network/chain id txParams.chainId = this.getChainId() - const ethTx = this.txProviderUtil.buildEthTxFromParams(txParams) + const ethTx = new Transaction(txParams) await this.signEthTx(ethTx, fromAddress) this.txStateManager.setTxStatusSigned(txMeta.id) const rawTx = ethUtil.bufferToHex(ethTx.serialize()) @@ -208,7 +229,7 @@ module.exports = class TransactionController extends EventEmitter { const txMeta = this.txStateManager.getTx(txId) txMeta.rawTx = rawTx this.txStateManager.updateTx(txMeta) - const txHash = await this.txProviderUtil.publishTransaction(rawTx) + const txHash = await this.query.sendRawTransaction(rawTx) this.setTxHash(txId, txHash) this.txStateManager.setTxStatusSubmitted(txId) } @@ -217,17 +238,6 @@ module.exports = class TransactionController extends EventEmitter { this.txStateManager.setTxStatusRejected(txId) } - - getChainId () { - const networkState = this.networkStore.getState() - const getChainId = parseInt(networkState) - if (Number.isNaN(getChainId)) { - return 0 - } else { - return getChainId - } - } - // receives a txHash records the tx as signed setTxHash (txId, txHash) { // Add the tx hash to the persisted meta-tx object -- cgit v1.2.3 From a73aecc796c2f2416227508db8e96e22915cfa65 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 6 Sep 2017 14:01:07 -0700 Subject: fix merge and errors disaperaing on update --- app/scripts/controllers/transactions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 3f2a7ce16..5aaee7be0 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -56,7 +56,7 @@ module.exports = class TransactionController extends EventEmitter { }) }, getConfirmedTransactions: (address) => { - return this.getFilteredTxList({ + return this.txStateManager.getFilteredTxList({ from: address, status: 'confirmed', err: undefined, -- cgit v1.2.3 From 50075c6df5af4441db78b47f3bc2036a65228224 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Thu, 7 Sep 2017 00:55:21 -0700 Subject: fix messy merge --- app/scripts/controllers/transactions.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 5aaee7be0..d71be37d8 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -62,10 +62,6 @@ module.exports = class TransactionController extends EventEmitter { err: undefined, }) }, - giveUpOnTransaction: (txId) => { - const msg = `Gave up submitting after 3500 blocks un-mined.` - this.setTxStatusFailed(txId, msg) - }, }) this.pendingTxTracker = new PendingTransactionTracker({ @@ -80,6 +76,10 @@ module.exports = class TransactionController extends EventEmitter { getPendingTransactions: () => { return this.txStateManager.getFilteredTxList({ status: 'submitted' }) }, + giveUpOnTransaction: (txId) => { + const msg = `Gave up submitting after 3500 blocks un-mined.` + this.setTxStatusFailed(txId, msg) + }, }) this.txStateManager.subscribe(() => { -- cgit v1.2.3 From 9b9df417246dbf332f0a7d8afadb664544ceb484 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Fri, 8 Sep 2017 14:24:40 -0700 Subject: more tests and craete a getPendingTransactions function --- app/scripts/controllers/transactions.js | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index d71be37d8..636424c64 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -49,12 +49,7 @@ module.exports = class TransactionController extends EventEmitter { this.nonceTracker = new NonceTracker({ provider: this.provider, - getPendingTransactions: (address) => { - return this.txStateManager.getFilteredTxList({ - from: address, - status: 'submitted', - }) - }, + getPendingTransactions: this.txStateManager.getPendingTransactions.bind(this.txStateManager), getConfirmedTransactions: (address) => { return this.txStateManager.getFilteredTxList({ from: address, @@ -73,9 +68,7 @@ module.exports = class TransactionController extends EventEmitter { return account.balance }, publishTransaction: this.query.sendRawTransaction, - getPendingTransactions: () => { - return this.txStateManager.getFilteredTxList({ status: 'submitted' }) - }, + getPendingTransactions: this.txStateManager.getPendingTransactions.bind(this.txStateManager), giveUpOnTransaction: (txId) => { const msg = `Gave up submitting after 3500 blocks un-mined.` this.setTxStatusFailed(txId, msg) @@ -122,8 +115,8 @@ module.exports = class TransactionController extends EventEmitter { return Object.keys(this.txStateManager.getUnapprovedTxList()).length } - getPendingTxCount () { - return this.txStateManager.getTxsByMetaData('status', 'signed').length + getPendingTxCount (account) { + return this.txStateManager.getPendingTransactions(account).length } getChainId () { -- cgit v1.2.3 From 3ad67d1b14b5b56002cf34ab6dbb18d602705827 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 12 Sep 2017 09:59:59 -0700 Subject: match other controller patterns --- app/scripts/controllers/transactions.js | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 636424c64..3cb6a609e 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -40,9 +40,7 @@ module.exports = class TransactionController extends EventEmitter { this.txGasUtil = new TxGasUtil(this.provider) this.txStateManager = new TransactionStateManger({ - initState: extend({ - transactions: [], - }, opts.initState), + initState: opts.initState, txHistoryLimit: opts.txHistoryLimit, getNetwork: this.getNetwork.bind(this), }) @@ -70,15 +68,12 @@ module.exports = class TransactionController extends EventEmitter { publishTransaction: this.query.sendRawTransaction, getPendingTransactions: this.txStateManager.getPendingTransactions.bind(this.txStateManager), giveUpOnTransaction: (txId) => { - const msg = `Gave up submitting after 3500 blocks un-mined.` - this.setTxStatusFailed(txId, msg) + const err = new Error(`Gave up submitting after 3500 blocks un-mined.`) + this.setTxStatusFailed(txId, err) }, }) - this.txStateManager.subscribe(() => { - this.emit('update') - this.emit('updateBadge') - }) + this.txStateManager.store.subscribe(() => this.emit('updateBadge')) this.pendingTxTracker.on('txWarning', this.txStateManager.updateTx.bind(this.txStateManager)) this.pendingTxTracker.on('txFailed', this.txStateManager.setTxStatusFailed.bind(this.txStateManager)) @@ -94,7 +89,7 @@ module.exports = class TransactionController extends EventEmitter { this.blockTracker.on('sync', this.pendingTxTracker.queryPendingTxs.bind(this.pendingTxTracker)) // memstore is computed from a few different stores this._updateMemstore() - this.txStateManager.subscribe(() => this._updateMemstore()) + this.txStateManager.store.subscribe(() => this._updateMemstore()) this.networkStore.subscribe(() => this._updateMemstore()) this.preferencesStore.subscribe(() => this._updateMemstore()) } @@ -250,10 +245,9 @@ module.exports = class TransactionController extends EventEmitter { this.txStateManager.updateTx(txMeta) } -/* _____________________________________ -| | -| PRIVATE METHODS | -|______________________________________*/ +// +// PRIVATE METHODS +// _updateMemstore () { const unapprovedTxs = this.txStateManager.getUnapprovedTxList() -- cgit v1.2.3 From 9e0c0745ab0f2aa207b0c062ad11efd8df1bb6c5 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 12 Sep 2017 12:19:26 -0700 Subject: linting && format fixing --- app/scripts/controllers/transactions.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 3cb6a609e..3ff53e72b 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -1,5 +1,4 @@ const EventEmitter = require('events') -const extend = require('xtend') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') const Transaction = require('ethereumjs-tx') @@ -60,17 +59,14 @@ module.exports = class TransactionController extends EventEmitter { this.pendingTxTracker = new PendingTransactionTracker({ provider: this.provider, nonceTracker: this.nonceTracker, + retryLimit: 3500, // Retry 3500 blocks, or about 1 day. getBalance: (address) => { const account = this.ethStore.getState().accounts[address] if (!account) return return account.balance }, - publishTransaction: this.query.sendRawTransaction, + publishTransaction: (rawTx) => this.query.sendRawTransaction(rawTx), getPendingTransactions: this.txStateManager.getPendingTransactions.bind(this.txStateManager), - giveUpOnTransaction: (txId) => { - const err = new Error(`Gave up submitting after 3500 blocks un-mined.`) - this.setTxStatusFailed(txId, err) - }, }) this.txStateManager.store.subscribe(() => this.emit('updateBadge')) @@ -193,7 +189,7 @@ module.exports = class TransactionController extends EventEmitter { // wait for a nonce nonceLock = await this.nonceTracker.getNonceLock(fromAddress) // add nonce to txParams - txMeta.txParams.nonce = nonceLock.nextNonce + txMeta.txParams.nonce = ethUtil.addHexPrefix(nonceLock.nextNonce.toString(16)) // add nonce debugging information to txMeta txMeta.nonceDetails = nonceLock.nonceDetails this.txStateManager.updateTx(txMeta) -- cgit v1.2.3 From e4d7fb244790d547b03d18763aa1d8e501d88b89 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 13 Sep 2017 11:39:39 -0700 Subject: Add state-labeled events to allow subscribing to any transaction's state change --- app/scripts/controllers/transactions.js | 1 + 1 file changed, 1 insertion(+) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index fb3be6073..59a3f5329 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -434,6 +434,7 @@ module.exports = class TransactionController extends EventEmitter { const txMeta = this.getTx(txId) txMeta.status = status this.emit(`${txMeta.id}:${status}`, txId) + this.emit(`${status}`, txId) if (status === 'submitted' || status === 'rejected') { this.emit(`${txMeta.id}:finished`, txMeta) } -- cgit v1.2.3 From 77a48fb0b16d7415377b02a3b7d383c9ef86fcb6 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 13 Sep 2017 14:27:27 -0700 Subject: ensure that values written to txParams are hex strings --- app/scripts/controllers/transactions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 3ff53e72b..3ee1c22aa 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -212,7 +212,7 @@ module.exports = class TransactionController extends EventEmitter { const txParams = txMeta.txParams const fromAddress = txParams.from // add network/chain id - txParams.chainId = this.getChainId() + txParams.chainId = ethUtil.addHexPrefix(this.getChainId().toString(16)) const ethTx = new Transaction(txParams) await this.signEthTx(ethTx, fromAddress) this.txStateManager.setTxStatusSigned(txMeta.id) -- cgit v1.2.3 From 11c8c07bfc6677e347873f02ae8c401f8d6c4dcf Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 22 Sep 2017 13:59:25 -0700 Subject: Refactor eth-store into account-tracker EthStore was only being used for tracking account balances and nonces now, so I removed its block-tracking duties, renamed it account-tracker, and removed it as a dependency from `KeyringController`, so that KRC can go live on without a hard dep on it. --- app/scripts/controllers/transactions.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 59a3f5329..2aff4e5ff 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -22,7 +22,7 @@ module.exports = class TransactionController extends EventEmitter { this.provider = opts.provider this.blockTracker = opts.blockTracker this.signEthTx = opts.signTransaction - this.ethStore = opts.ethStore + this.accountTracker = opts.accountTracker this.nonceTracker = new NonceTracker({ provider: this.provider, @@ -52,7 +52,7 @@ module.exports = class TransactionController extends EventEmitter { provider: this.provider, nonceTracker: this.nonceTracker, getBalance: (address) => { - const account = this.ethStore.getState().accounts[address] + const account = this.accountTracker.getState().accounts[address] if (!account) return return account.balance }, @@ -73,7 +73,7 @@ module.exports = class TransactionController extends EventEmitter { this.blockTracker.on('rawBlock', this.pendingTxTracker.checkForTxInBlock.bind(this.pendingTxTracker)) // 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 + // where accountTracker hasent been populated by the results yet this.blockTracker.once('latest', () => { this.blockTracker.on('latest', this.pendingTxTracker.resubmitPendingTxs.bind(this.pendingTxTracker)) }) -- cgit v1.2.3 From 2ed8d579daa4d33c38891ac77d1415fcd237a187 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 26 Sep 2017 13:37:13 -0700 Subject: listen for the blocke event on the block tracker instead of rawBlock on the provider --- app/scripts/controllers/transactions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index fb3be6073..4e52a3c14 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -70,7 +70,7 @@ module.exports = class TransactionController extends EventEmitter { this.pendingTxTracker.on('txFailed', this.setTxStatusFailed.bind(this)) this.pendingTxTracker.on('txConfirmed', this.setTxStatusConfirmed.bind(this)) - this.blockTracker.on('rawBlock', this.pendingTxTracker.checkForTxInBlock.bind(this.pendingTxTracker)) + this.blockTracker.on('block', this.pendingTxTracker.checkForTxInBlock.bind(this.pendingTxTracker)) // 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 -- cgit v1.2.3 From 9fd545811226c16e11e4f2dc100a348e07f094bf Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 26 Sep 2017 16:52:08 -0700 Subject: transactions: lint fixes and reveal status-update event for balance controller --- app/scripts/controllers/transactions.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index de5fa5b20..1b647a4ed 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -43,7 +43,8 @@ module.exports = class TransactionController extends EventEmitter { txHistoryLimit: opts.txHistoryLimit, getNetwork: this.getNetwork.bind(this), }) - + this.store = this.txStateManager.store + this.txStateManager.on('tx:status-update', this.emit.bind(this, 'tx:status-update')) this.nonceTracker = new NonceTracker({ provider: this.provider, getPendingTransactions: this.txStateManager.getPendingTransactions.bind(this.txStateManager), @@ -69,7 +70,7 @@ module.exports = class TransactionController extends EventEmitter { getPendingTransactions: this.txStateManager.getPendingTransactions.bind(this.txStateManager), }) - this.txStateManager.store.subscribe(() => this.emit('updateBadge')) + this.txStateManager.store.subscribe(() => this.emit('update:badge')) this.pendingTxTracker.on('txWarning', this.txStateManager.updateTx.bind(this.txStateManager)) this.pendingTxTracker.on('txFailed', this.txStateManager.setTxStatusFailed.bind(this.txStateManager)) -- cgit v1.2.3 From 80c98b16531db4c6a13a52df800967af2bc4a676 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 26 Sep 2017 16:55:11 -0700 Subject: transactions: make evnt names pretty and eaiser to read --- app/scripts/controllers/transactions.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 1b647a4ed..ec1524968 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -72,9 +72,9 @@ module.exports = class TransactionController extends EventEmitter { this.txStateManager.store.subscribe(() => this.emit('update:badge')) - this.pendingTxTracker.on('txWarning', this.txStateManager.updateTx.bind(this.txStateManager)) - this.pendingTxTracker.on('txFailed', this.txStateManager.setTxStatusFailed.bind(this.txStateManager)) - this.pendingTxTracker.on('txConfirmed', this.txStateManager.setTxStatusConfirmed.bind(this.txStateManager)) + this.pendingTxTracker.on('tx:warning', this.txStateManager.updateTx.bind(this.txStateManager)) + this.pendingTxTracker.on('tx:failed', this.txStateManager.setTxStatusFailed.bind(this.txStateManager)) + this.pendingTxTracker.on('tx:confirmed', this.txStateManager.setTxStatusConfirmed.bind(this.txStateManager)) this.blockTracker.on('rawBlock', this.pendingTxTracker.checkForTxInBlock.bind(this.pendingTxTracker)) // this is a little messy but until ethstore has been either -- cgit v1.2.3 From 508696f71d6b5b14c708a3229039f9f915ce48ce Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 26 Sep 2017 18:11:51 -0700 Subject: transactions: reveal #getFilteredTxList from txStateManage and fix accountTracker.store reference --- app/scripts/controllers/transactions.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index ec1524968..6ea2933dc 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -62,7 +62,7 @@ module.exports = class TransactionController extends EventEmitter { nonceTracker: this.nonceTracker, retryLimit: 3500, // Retry 3500 blocks, or about 1 day. getBalance: (address) => { - const account = this.accountTracker.getState().accounts[address] + const account = this.accountTracker.store.getState().accounts[address] if (!account) return return account.balance }, @@ -111,6 +111,10 @@ module.exports = class TransactionController extends EventEmitter { return this.txStateManager.getPendingTransactions(account).length } + getFilteredTxList (opts) { + return this.txStateManager.getFilteredTxList(opts) + } + getChainId () { const networkState = this.networkStore.getState() const getChainId = parseInt(networkState) -- cgit v1.2.3 From 0a94ec41d3a2877ed7cfd3c8f9e9f9d725659183 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 26 Sep 2017 22:42:59 -0700 Subject: pending-tx - move incrementing of the retryCount on the txMeta outside pending-tx-tracker --- app/scripts/controllers/transactions.js | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 6ea2933dc..3cd107031 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -75,6 +75,11 @@ module.exports = class TransactionController extends EventEmitter { this.pendingTxTracker.on('tx:warning', this.txStateManager.updateTx.bind(this.txStateManager)) this.pendingTxTracker.on('tx:failed', this.txStateManager.setTxStatusFailed.bind(this.txStateManager)) this.pendingTxTracker.on('tx:confirmed', this.txStateManager.setTxStatusConfirmed.bind(this.txStateManager)) + this.pendingTxTracker.on('tx:retry', (txMeta) => { + if (!('retryCount' in txMeta)) txMeta.retryCount = 0 + txMeta.retryCount++ + this.txStateManager.updateTx(txMeta) + }) this.blockTracker.on('rawBlock', this.pendingTxTracker.checkForTxInBlock.bind(this.pendingTxTracker)) // this is a little messy but until ethstore has been either -- cgit v1.2.3 From 1983e161c658979872bad66f8dd5e9b2c7a616b5 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 27 Sep 2017 12:29:09 -0700 Subject: Fix accountTracker store references --- app/scripts/controllers/transactions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 4cd307b07..87521c76b 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -52,7 +52,7 @@ module.exports = class TransactionController extends EventEmitter { provider: this.provider, nonceTracker: this.nonceTracker, getBalance: (address) => { - const account = this.accountTracker.getState().accounts[address] + const account = this.accountTracker.store.getState().accounts[address] if (!account) return return account.balance }, -- cgit v1.2.3 From ac80eaca1fc9923cd5696282ba2bc6bace22ff83 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Fri, 29 Sep 2017 12:54:05 -0700 Subject: pending-tx - dont check the balance to rebrodcast --- app/scripts/controllers/transactions.js | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 4f5c94675..9fdec1ead 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -32,7 +32,6 @@ module.exports = class TransactionController extends EventEmitter { this.provider = opts.provider this.blockTracker = opts.blockTracker this.signEthTx = opts.signTransaction - this.accountTracker = opts.accountTracker this.memStore = new ObservableStore({}) this.query = new EthQuery(this.provider) @@ -61,11 +60,6 @@ module.exports = class TransactionController extends EventEmitter { provider: this.provider, nonceTracker: this.nonceTracker, retryLimit: 3500, // Retry 3500 blocks, or about 1 day. - getBalance: (address) => { - const account = this.accountTracker.store.getState().accounts[address] - if (!account) return - return account.balance - }, publishTransaction: (rawTx) => this.query.sendRawTransaction(rawTx), getPendingTransactions: this.txStateManager.getPendingTransactions.bind(this.txStateManager), }) @@ -84,10 +78,7 @@ module.exports = class TransactionController extends EventEmitter { this.blockTracker.on('block', this.pendingTxTracker.checkForTxInBlock.bind(this.pendingTxTracker)) // this is a little messy but until ethstore has been either // removed or redone this is to guard against the race condition - // where accountTracker hasent been populated by the results yet - this.blockTracker.once('latest', () => { - this.blockTracker.on('latest', this.pendingTxTracker.resubmitPendingTxs.bind(this.pendingTxTracker)) - }) + this.blockTracker.on('latest', this.pendingTxTracker.resubmitPendingTxs.bind(this.pendingTxTracker)) this.blockTracker.on('sync', this.pendingTxTracker.queryPendingTxs.bind(this.pendingTxTracker)) // memstore is computed from a few different stores this._updateMemstore() -- cgit v1.2.3 From 833da191c37db5b5b470c69a6d4d438ff4719fec Mon Sep 17 00:00:00 2001 From: frankiebee Date: Mon, 2 Oct 2017 13:41:29 -0700 Subject: transaction - provide notes for history --- app/scripts/controllers/transactions.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 9fdec1ead..94e04c429 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -66,13 +66,15 @@ module.exports = class TransactionController extends EventEmitter { this.txStateManager.store.subscribe(() => this.emit('update:badge')) - this.pendingTxTracker.on('tx:warning', this.txStateManager.updateTx.bind(this.txStateManager)) + this.pendingTxTracker.on('tx:warning', (txMeta) => { + this.txStateManager.updateTx(txMeta, 'transactions/pending-tx-tracker#event: tx:warning') + }) this.pendingTxTracker.on('tx:failed', this.txStateManager.setTxStatusFailed.bind(this.txStateManager)) this.pendingTxTracker.on('tx:confirmed', this.txStateManager.setTxStatusConfirmed.bind(this.txStateManager)) this.pendingTxTracker.on('tx:retry', (txMeta) => { if (!('retryCount' in txMeta)) txMeta.retryCount = 0 txMeta.retryCount++ - this.txStateManager.updateTx(txMeta) + this.txStateManager.updateTx(txMeta, 'transactions/pending-tx-tracker#event: tx:retry') }) this.blockTracker.on('block', this.pendingTxTracker.checkForTxInBlock.bind(this.pendingTxTracker)) @@ -168,14 +170,14 @@ module.exports = class TransactionController extends EventEmitter { const txParams = txMeta.txParams // ensure value const gasPrice = txParams.gasPrice || await this.query.gasPrice() - txParams.value = txParams.value || '0x0' txParams.gasPrice = ethUtil.addHexPrefix(gasPrice.toString(16)) + txParams.value = txParams.value || '0x0' // set gasLimit return await this.txGasUtil.analyzeGasUsage(txMeta) } async updateAndApproveTransaction (txMeta) { - this.txStateManager.updateTx(txMeta) + this.txStateManager.updateTx(txMeta, 'confTx: user approved transaction') await this.approveTransaction(txMeta.id) } @@ -193,7 +195,7 @@ module.exports = class TransactionController extends EventEmitter { txMeta.txParams.nonce = ethUtil.addHexPrefix(nonceLock.nextNonce.toString(16)) // add nonce debugging information to txMeta txMeta.nonceDetails = nonceLock.nonceDetails - this.txStateManager.updateTx(txMeta) + this.txStateManager.updateTx(txMeta, 'transactions#approveTransaction') // sign transaction const rawTx = await this.signTransaction(txId) await this.publishTransaction(txId, rawTx) @@ -224,7 +226,7 @@ module.exports = class TransactionController extends EventEmitter { async publishTransaction (txId, rawTx) { const txMeta = this.txStateManager.getTx(txId) txMeta.rawTx = rawTx - this.txStateManager.updateTx(txMeta) + this.txStateManager.updateTx(txMeta, 'transactions#publishTransaction') const txHash = await this.query.sendRawTransaction(rawTx) this.setTxHash(txId, txHash) this.txStateManager.setTxStatusSubmitted(txId) @@ -239,7 +241,7 @@ module.exports = class TransactionController extends EventEmitter { // Add the tx hash to the persisted meta-tx object const txMeta = this.txStateManager.getTx(txId) txMeta.hash = txHash - this.txStateManager.updateTx(txMeta) + this.txStateManager.updateTx(txMeta, 'transactions#setTxHash') } // -- cgit v1.2.3 From 15809894ff42bacc3babfb9aaba48389417907c0 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Thu, 5 Oct 2017 09:58:04 -0700 Subject: Add indicator for specified gas price --- app/scripts/controllers/transactions.js | 1 + 1 file changed, 1 insertion(+) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 94e04c429..481dd62a5 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -169,6 +169,7 @@ module.exports = class TransactionController extends EventEmitter { async addTxDefaults (txMeta) { const txParams = txMeta.txParams // ensure value + txMeta.gasPriceSpecified = Boolean(txParams.gasPrice) const gasPrice = txParams.gasPrice || await this.query.gasPrice() txParams.gasPrice = ethUtil.addHexPrefix(gasPrice.toString(16)) txParams.value = txParams.value || '0x0' -- cgit v1.2.3 From ec9c5283135d2cc3dcb633f19dd89ea79267f34a Mon Sep 17 00:00:00 2001 From: frankiebee Date: Thu, 5 Oct 2017 10:54:28 -0700 Subject: pending-tx - check time stamp instead of block number for resubmit --- app/scripts/controllers/transactions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 94e04c429..a0f983deb 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -59,7 +59,7 @@ module.exports = class TransactionController extends EventEmitter { this.pendingTxTracker = new PendingTransactionTracker({ provider: this.provider, nonceTracker: this.nonceTracker, - retryLimit: 3500, // Retry 3500 blocks, or about 1 day. + retryTimePeriod: 86400000, // Retry 3500 blocks, or about 1 day. publishTransaction: (rawTx) => this.query.sendRawTransaction(rawTx), getPendingTransactions: this.txStateManager.getPendingTransactions.bind(this.txStateManager), }) -- cgit v1.2.3 From 94513cae7bf3c8310ae6a248e12a9b7dd73e306f Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 6 Oct 2017 12:50:33 -0700 Subject: Provide method for tx tracker to refer to all txs --- app/scripts/controllers/transactions.js | 1 + 1 file changed, 1 insertion(+) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index a0f983deb..ef659a300 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -62,6 +62,7 @@ module.exports = class TransactionController extends EventEmitter { retryTimePeriod: 86400000, // Retry 3500 blocks, or about 1 day. publishTransaction: (rawTx) => this.query.sendRawTransaction(rawTx), getPendingTransactions: this.txStateManager.getPendingTransactions.bind(this.txStateManager), + getCompletedTransactions: this.txStateManager.getConfirmedTransactions.bind(this.txStateManager), }) this.txStateManager.store.subscribe(() => this.emit('update:badge')) -- cgit v1.2.3 From dcf10f3d7559b428cc189fb4406580d816eae365 Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 11 Oct 2017 18:33:02 -0700 Subject: nonce-tracker - use blockTracker directly --- app/scripts/controllers/transactions.js | 1 + 1 file changed, 1 insertion(+) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index ef659a300..d46dee230 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -46,6 +46,7 @@ module.exports = class TransactionController extends EventEmitter { this.txStateManager.on('tx:status-update', this.emit.bind(this, 'tx:status-update')) this.nonceTracker = new NonceTracker({ provider: this.provider, + blockTracker: this.blockTracker, getPendingTransactions: this.txStateManager.getPendingTransactions.bind(this.txStateManager), getConfirmedTransactions: (address) => { return this.txStateManager.getFilteredTxList({ -- cgit v1.2.3 From 8da0d0b28a52d476da3623774159e8d6a595da2d Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 18 Oct 2017 15:09:32 -0700 Subject: Revert "NetworkController refactor for new EthClient interface" --- app/scripts/controllers/transactions.js | 1 - 1 file changed, 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index d46dee230..ef659a300 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -46,7 +46,6 @@ module.exports = class TransactionController extends EventEmitter { this.txStateManager.on('tx:status-update', this.emit.bind(this, 'tx:status-update')) this.nonceTracker = new NonceTracker({ provider: this.provider, - blockTracker: this.blockTracker, getPendingTransactions: this.txStateManager.getPendingTransactions.bind(this.txStateManager), getConfirmedTransactions: (address) => { return this.txStateManager.getFilteredTxList({ -- cgit v1.2.3 From 41fea44af3105313b33d9882859935019b6a2410 Mon Sep 17 00:00:00 2001 From: "Dora E. Mondrian" Date: Mon, 6 Nov 2017 04:35:51 -0800 Subject: newUnaprovedTx => newUnapprovedTx This typo tripped me up when I was reading through the code and trying to understand what's going on. --- app/scripts/controllers/transactions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index d5fde033b..a861c0342 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -133,7 +133,7 @@ module.exports = class TransactionController extends EventEmitter { async newUnapprovedTransaction (txParams) { log.debug(`MetaMaskController newUnapprovedTransaction ${JSON.stringify(txParams)}`) const txMeta = await this.addUnapprovedTransaction(txParams) - this.emit('newUnaprovedTx', txMeta) + this.emit('newUnapprovedTx', txMeta) // listen for tx completion (success, fail) return new Promise((resolve, reject) => { this.txStateManager.once(`${txMeta.id}:finished`, (completedTx) => { -- cgit v1.2.3 From ae2a4d78e8c7733da1963965e38e154351d54a20 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 5 Dec 2017 17:21:14 -0330 Subject: Exponentional backoff on transaction retry in pending-tx-tracker --- app/scripts/controllers/transactions.js | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index a861c0342..063ba8f65 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -72,6 +72,12 @@ module.exports = class TransactionController extends EventEmitter { }) this.pendingTxTracker.on('tx:failed', this.txStateManager.setTxStatusFailed.bind(this.txStateManager)) this.pendingTxTracker.on('tx:confirmed', this.txStateManager.setTxStatusConfirmed.bind(this.txStateManager)) + this.pendingTxTracker.on('tx:block-update', (txMeta, latestBlockNumber) => { + if (!txMeta.firstRetryBlockNumber) { + txMeta.firstRetryBlockNumber = latestBlockNumber + this.txStateManager.updateTx(txMeta, 'transactions/pending-tx-tracker#event: tx:retry') + } + }) this.pendingTxTracker.on('tx:retry', (txMeta) => { if (!('retryCount' in txMeta)) txMeta.retryCount = 0 txMeta.retryCount++ -- cgit v1.2.3 From ea23da9e75c92cbf82d0daa19847d2035361a656 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 6 Dec 2017 13:07:31 -0330 Subject: Correct note for updateTx after block-update event in transaction.js --- app/scripts/controllers/transactions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 063ba8f65..ce709bd28 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -75,7 +75,7 @@ module.exports = class TransactionController extends EventEmitter { this.pendingTxTracker.on('tx:block-update', (txMeta, latestBlockNumber) => { if (!txMeta.firstRetryBlockNumber) { txMeta.firstRetryBlockNumber = latestBlockNumber - this.txStateManager.updateTx(txMeta, 'transactions/pending-tx-tracker#event: tx:retry') + this.txStateManager.updateTx(txMeta, 'transactions/pending-tx-tracker#event: tx:block-update') } }) this.pendingTxTracker.on('tx:retry', (txMeta) => { -- cgit v1.2.3 From 7854321faeeb8184b3171e3b214f57d6e61c0814 Mon Sep 17 00:00:00 2001 From: vicnaum Date: Wed, 6 Dec 2017 22:49:24 +0100 Subject: Fix for #2644 - Specified Nonce isn't used Added nonceSpecified. And a check if nonce was specified - then we should use the specified nonce instead of generating a new one. --- app/scripts/controllers/transactions.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index ce709bd28..060484b87 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -177,6 +177,7 @@ module.exports = class TransactionController extends EventEmitter { const txParams = txMeta.txParams // ensure value txMeta.gasPriceSpecified = Boolean(txParams.gasPrice) + txMeta.nonceSpecified = Boolean(txParams.nonce) const gasPrice = txParams.gasPrice || await this.query.gasPrice() txParams.gasPrice = ethUtil.addHexPrefix(gasPrice.toString(16)) txParams.value = txParams.value || '0x0' @@ -200,7 +201,11 @@ module.exports = class TransactionController extends EventEmitter { // wait for a nonce nonceLock = await this.nonceTracker.getNonceLock(fromAddress) // add nonce to txParams - txMeta.txParams.nonce = ethUtil.addHexPrefix(nonceLock.nextNonce.toString(16)) + if (txMeta.nonceSpecified) { + txMeta.txParams.nonce = ethUtil.addHexPrefix(txMeta.txParams.nonce.toString(16)) + } else { + txMeta.txParams.nonce = ethUtil.addHexPrefix(nonceLock.nextNonce.toString(16)) + } // add nonce debugging information to txMeta txMeta.nonceDetails = nonceLock.nonceDetails this.txStateManager.updateTx(txMeta, 'transactions#approveTransaction') -- cgit v1.2.3 From 6ff580584a74c6d85f54ce7cfc500db822904957 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 6 Dec 2017 22:20:11 -0500 Subject: Add retry background method and action --- app/scripts/controllers/transactions.js | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index ce709bd28..67043b401 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -184,6 +184,10 @@ module.exports = class TransactionController extends EventEmitter { return await this.txGasUtil.analyzeGasUsage(txMeta) } + async retryTransaction (txId) { + return this.txStateManager.setTxStatusUnapproved(txId) + } + async updateAndApproveTransaction (txMeta) { this.txStateManager.updateTx(txMeta, 'confTx: user approved transaction') await this.approveTransaction(txMeta.id) -- cgit v1.2.3 From 0e25129028dd45d717d27dfe0c06db8a4052bd4e Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 6 Dec 2017 23:42:47 -0500 Subject: Enforce retry tx at minimum gas of previous tx --- app/scripts/controllers/transactions.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 67043b401..685db6269 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -185,7 +185,10 @@ module.exports = class TransactionController extends EventEmitter { } async retryTransaction (txId) { - return this.txStateManager.setTxStatusUnapproved(txId) + this.txStateManager.setTxStatusUnapproved(txId) + const txMeta = this.txStateManager.getTx(txId) + txMeta.lastGasPrice = txMeta.txParams.gasPrice + this.txStateManager.updateTx(txMeta, 'retryTransaction: manual retry') } async updateAndApproveTransaction (txMeta) { -- cgit v1.2.3 From 553d713636d317b74d819d62b5b931bdf2d112d8 Mon Sep 17 00:00:00 2001 From: vicnaum Date: Thu, 7 Dec 2017 15:30:05 +0100 Subject: A more expressive way replaced ifs with ? : --- app/scripts/controllers/transactions.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 060484b87..6bdbd2cfc 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -201,11 +201,8 @@ module.exports = class TransactionController extends EventEmitter { // wait for a nonce nonceLock = await this.nonceTracker.getNonceLock(fromAddress) // add nonce to txParams - if (txMeta.nonceSpecified) { - txMeta.txParams.nonce = ethUtil.addHexPrefix(txMeta.txParams.nonce.toString(16)) - } else { - txMeta.txParams.nonce = ethUtil.addHexPrefix(nonceLock.nextNonce.toString(16)) - } + const nonce = txMeta.nonceSpecified ? txMeta.txParams.nonce : nonceLock.nextNonce + txMeta.txParams.nonce = ethUtil.addHexPrefix(nonce.toString(16)) // add nonce debugging information to txMeta txMeta.nonceDetails = nonceLock.nonceDetails this.txStateManager.updateTx(txMeta, 'transactions#approveTransaction') -- cgit v1.2.3 From 950ec9596c931055c3e0f2212f2733c9ca07739d Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 7 Dec 2017 16:13:38 -0500 Subject: Do not allow nonces larger than the next valid nonce To avoid situations where a user signs a transaction that will become surprisingly valid in the future. --- app/scripts/controllers/transactions.js | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index bb408d445..6110b9c75 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -209,6 +209,10 @@ module.exports = class TransactionController extends EventEmitter { nonceLock = await this.nonceTracker.getNonceLock(fromAddress) // add nonce to txParams const nonce = txMeta.nonceSpecified ? txMeta.txParams.nonce : nonceLock.nextNonce + if (nonce > nonceLock.nextNonce) { + const message = `Specified nonce may not be larger than account's next valid nonce.` + throw new Error(message) + } txMeta.txParams.nonce = ethUtil.addHexPrefix(nonce.toString(16)) // add nonce debugging information to txMeta txMeta.nonceDetails = nonceLock.nonceDetails -- cgit v1.2.3 From a91200fd08b429c81d4096de17cdd9066a632ade Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 7 Dec 2017 18:04:14 -0500 Subject: tx-controller - failed state is a finished state --- app/scripts/controllers/transactions.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 6110b9c75..f95b5e39a 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -138,18 +138,20 @@ module.exports = class TransactionController extends EventEmitter { async newUnapprovedTransaction (txParams) { log.debug(`MetaMaskController newUnapprovedTransaction ${JSON.stringify(txParams)}`) - const txMeta = await this.addUnapprovedTransaction(txParams) - this.emit('newUnapprovedTx', txMeta) + const initialTxMeta = await this.addUnapprovedTransaction(txParams) + this.emit('newUnapprovedTx', initialTxMeta) // listen for tx completion (success, fail) return new Promise((resolve, reject) => { - this.txStateManager.once(`${txMeta.id}:finished`, (completedTx) => { - switch (completedTx.status) { + this.txStateManager.once(`${initialTxMeta.id}:finished`, (finishedTxMeta) => { + switch (finishedTxMeta.status) { case 'submitted': - return resolve(completedTx.hash) + return resolve(finishedTxMeta.hash) case 'rejected': return reject(new Error('MetaMask Tx Signature: User denied transaction signature.')) + case 'failed': + return reject(new Error(finishedTxMeta.err.message)) default: - return reject(new Error(`MetaMask Tx Signature: Unknown problem: ${JSON.stringify(completedTx.txParams)}`)) + return reject(new Error(`MetaMask Tx Signature: Unknown problem: ${JSON.stringify(finishedTxMeta.txParams)}`)) } }) }) -- cgit v1.2.3 From 1f1fc2c49ecbb5c6a0a1d925d5c02cf48f795b2f Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 19 Dec 2017 11:16:11 -0330 Subject: Canceled, edited transactions show edited amount. --- app/scripts/controllers/transactions.js | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index ce709bd28..0d6b97d51 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -189,6 +189,11 @@ module.exports = class TransactionController extends EventEmitter { await this.approveTransaction(txMeta.id) } + async updateAndCancelTransaction (txMeta) { + this.txStateManager.updateTx(txMeta, 'confTx: user rejected transaction') + await this.cancelTransaction(txMeta.id) + } + async approveTransaction (txId) { let nonceLock try { -- cgit v1.2.3 From bf4043c59bb67ea93599207d91cb7a4f4426e75f Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 20 Dec 2017 13:47:16 -0330 Subject: Adds updateTransaction to background and used it to update after editing in send-v2. --- app/scripts/controllers/transactions.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 0d6b97d51..5b687f67a 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -184,16 +184,15 @@ module.exports = class TransactionController extends EventEmitter { return await this.txGasUtil.analyzeGasUsage(txMeta) } + async updateTransaction (txMeta) { + this.txStateManager.updateTx(txMeta, 'confTx: user updated transaction') + } + async updateAndApproveTransaction (txMeta) { this.txStateManager.updateTx(txMeta, 'confTx: user approved transaction') await this.approveTransaction(txMeta.id) } - async updateAndCancelTransaction (txMeta) { - this.txStateManager.updateTx(txMeta, 'confTx: user rejected transaction') - await this.cancelTransaction(txMeta.id) - } - async approveTransaction (txId) { let nonceLock try { -- cgit v1.2.3 From 33dbee3db9f6d66777039579789f36618c95c5fe Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 21 Dec 2017 14:15:17 -0800 Subject: Remove retryTimePeriod from tx controller --- app/scripts/controllers/transactions.js | 1 - 1 file changed, 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index f95b5e39a..7c7efb84d 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -59,7 +59,6 @@ module.exports = class TransactionController extends EventEmitter { this.pendingTxTracker = new PendingTransactionTracker({ provider: this.provider, nonceTracker: this.nonceTracker, - retryTimePeriod: 86400000, // Retry 3500 blocks, or about 1 day. publishTransaction: (rawTx) => this.query.sendRawTransaction(rawTx), getPendingTransactions: this.txStateManager.getPendingTransactions.bind(this.txStateManager), getCompletedTransactions: this.txStateManager.getConfirmedTransactions.bind(this.txStateManager), -- cgit v1.2.3 From 4bca98d588869fb58796a6b2f29dca48605ceeba Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 5 Jan 2018 21:24:20 -0800 Subject: Derive gas price estimate from previous transactions Return the 50th percentile lowest gas price of the previous 20 blocks. --- app/scripts/controllers/transactions.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 7c7efb84d..be7e7221f 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -32,6 +32,7 @@ module.exports = class TransactionController extends EventEmitter { this.provider = opts.provider this.blockTracker = opts.blockTracker this.signEthTx = opts.signTransaction + this.getGasPrice = opts.getGasPrice this.memStore = new ObservableStore({}) this.query = new EthQuery(this.provider) @@ -179,7 +180,7 @@ module.exports = class TransactionController extends EventEmitter { // ensure value txMeta.gasPriceSpecified = Boolean(txParams.gasPrice) txMeta.nonceSpecified = Boolean(txParams.nonce) - const gasPrice = txParams.gasPrice || await this.query.gasPrice() + const gasPrice = txParams.gasPrice || this.getGasPrice() txParams.gasPrice = ethUtil.addHexPrefix(gasPrice.toString(16)) txParams.value = txParams.value || '0x0' // set gasLimit -- cgit v1.2.3 From aec24ec81e4785ceea93375d562458f62be69266 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 5 Jan 2018 22:08:03 -0800 Subject: Fix feature to work --- app/scripts/controllers/transactions.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index be7e7221f..469deb670 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -180,7 +180,8 @@ module.exports = class TransactionController extends EventEmitter { // ensure value txMeta.gasPriceSpecified = Boolean(txParams.gasPrice) txMeta.nonceSpecified = Boolean(txParams.nonce) - const gasPrice = txParams.gasPrice || this.getGasPrice() + const gasPrice = txParams.gasPrice || this.getGasPrice ? this.getGasPrice() + : await this.query.gasPrice() txParams.gasPrice = ethUtil.addHexPrefix(gasPrice.toString(16)) txParams.value = txParams.value || '0x0' // set gasLimit -- cgit v1.2.3 From 9a8670309d2791b212d04ee795f70040cc5f40fc Mon Sep 17 00:00:00 2001 From: kumavis Date: Mon, 8 Jan 2018 13:19:18 -0800 Subject: bugfix - transactions controller - breakout logic and fix order of operations bug --- app/scripts/controllers/transactions.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 469deb670..ded9739a8 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -180,8 +180,10 @@ module.exports = class TransactionController extends EventEmitter { // ensure value txMeta.gasPriceSpecified = Boolean(txParams.gasPrice) txMeta.nonceSpecified = Boolean(txParams.nonce) - const gasPrice = txParams.gasPrice || this.getGasPrice ? this.getGasPrice() - : await this.query.gasPrice() + let gasPrice = txParams.gasPrice + if (!gasPrice) { + gasPrice = this.getGasPrice ? this.getGasPrice() : await this.query.gasPrice() + } txParams.gasPrice = ethUtil.addHexPrefix(gasPrice.toString(16)) txParams.value = txParams.value || '0x0' // set gasLimit -- cgit v1.2.3 From f0dd4f19238d63875fbdfa3a9b31fa7b9d8925ed Mon Sep 17 00:00:00 2001 From: frankiebee Date: Sun, 14 Jan 2018 14:00:17 -0800 Subject: transactions - emit 'newUnapprovedTx' before estimateGas finishes --- app/scripts/controllers/transactions.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index ded9739a8..bb9253175 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -139,7 +139,6 @@ module.exports = class TransactionController extends EventEmitter { async newUnapprovedTransaction (txParams) { log.debug(`MetaMaskController newUnapprovedTransaction ${JSON.stringify(txParams)}`) const initialTxMeta = await this.addUnapprovedTransaction(txParams) - this.emit('newUnapprovedTx', initialTxMeta) // listen for tx completion (success, fail) return new Promise((resolve, reject) => { this.txStateManager.once(`${initialTxMeta.id}:finished`, (finishedTxMeta) => { @@ -167,11 +166,16 @@ module.exports = class TransactionController extends EventEmitter { status: 'unapproved', metamaskNetworkId: this.getNetwork(), txParams: txParams, + loadingDefaults: true, } + this.addTx(txMeta) + this.emit('newUnapprovedTx', txMeta) // add default tx params await this.addTxDefaults(txMeta) + + txMeta.loadingDefaults = false // save txMeta - this.addTx(txMeta) + this.txStateManager.updateTx(txMeta) return txMeta } -- cgit v1.2.3 From 9f19fea8e08415c670ce3df5d7e363baac366d2c Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 17 Jan 2018 15:42:01 -0800 Subject: transactions - wrap addTxDefaults in a try catch and re try addTxDefaults on boot if they did not complete --- app/scripts/controllers/transactions.js | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index bb9253175..4c9a4cd80 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -43,6 +43,18 @@ module.exports = class TransactionController extends EventEmitter { txHistoryLimit: opts.txHistoryLimit, getNetwork: this.getNetwork.bind(this), }) + + this.txStateManager.getFilteredTxList({ + status: 'unapproved', + loadingDefaults: true, + }).forEach((tx) => { + this.addTxDefaults(tx) + .then((txMeta) => { + txMeta.loadingDefaults = false + this.txStateManager.updateTx(txMeta, 'transactions: gas estimation for tx on boot') + }) + }) + this.store = this.txStateManager.store this.txStateManager.on('tx:status-update', this.emit.bind(this, 'tx:status-update')) this.nonceTracker = new NonceTracker({ @@ -171,11 +183,17 @@ module.exports = class TransactionController extends EventEmitter { this.addTx(txMeta) this.emit('newUnapprovedTx', txMeta) // add default tx params - await this.addTxDefaults(txMeta) - + try { + await this.addTxDefaults(txMeta) + } catch (error) { + console.log(error) + this.txStateManager.setTxStatusFailed(txMeta.id, error) + throw error + } txMeta.loadingDefaults = false // save txMeta this.txStateManager.updateTx(txMeta) + return txMeta } -- cgit v1.2.3 From be8d9244326443fb7f54df271d4e2a2abda90f6f Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 17 Jan 2018 15:48:37 -0800 Subject: transactions - fail txs on boot who fail addTxDefaults --- app/scripts/controllers/transactions.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 4c9a4cd80..73aadb292 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -52,6 +52,8 @@ module.exports = class TransactionController extends EventEmitter { .then((txMeta) => { txMeta.loadingDefaults = false this.txStateManager.updateTx(txMeta, 'transactions: gas estimation for tx on boot') + }).catch((error) => { + this.txStateManager.setTxStatusFailed(tx.id, error) }) }) -- cgit v1.2.3 From 234c2417ca2480fc3025030bc19ef007ea8e8d30 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 17 Jan 2018 16:49:38 -0800 Subject: transactions - transtion approved transactions to failed transactions on boot --- app/scripts/controllers/transactions.js | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 73aadb292..c1909d95c 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -57,6 +57,14 @@ module.exports = class TransactionController extends EventEmitter { }) }) + this.txStateManager.getFilteredTxList({ + status: 'approved', + }).forEach((txMeta) => { + const txSignError = new Error('Transaction was interrupted during signing process') + this.txStateManager.setTxStatusFailed(txMeta.id, txSignError) + }) + + this.store = this.txStateManager.store this.txStateManager.on('tx:status-update', this.emit.bind(this, 'tx:status-update')) this.nonceTracker = new NonceTracker({ -- cgit v1.2.3 From 96fc916024cf16790a19472f31d3861168b8433b Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 17 Jan 2018 17:56:31 -0800 Subject: Update transactions.js --- app/scripts/controllers/transactions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index c1909d95c..9c3618e60 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -60,7 +60,7 @@ module.exports = class TransactionController extends EventEmitter { this.txStateManager.getFilteredTxList({ status: 'approved', }).forEach((txMeta) => { - const txSignError = new Error('Transaction was interrupted during signing process') + const txSignError = new Error('Transaction found as "approved" during boot - possibly stuck during signing') this.txStateManager.setTxStatusFailed(txMeta.id, txSignError) }) -- cgit v1.2.3 From e6fda855a556a6aa0325556b074612ff76925e5d Mon Sep 17 00:00:00 2001 From: Bruno Barbieri Date: Wed, 31 Jan 2018 03:33:15 -0500 Subject: added reset account feature --- app/scripts/controllers/transactions.js | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 9c3618e60..7ca04caf1 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -152,6 +152,10 @@ module.exports = class TransactionController extends EventEmitter { } } + wipeTransactions(){ + this.txStateManager.wipeTransactions(); + } + // Adds a tx to the txlist addTx (txMeta) { this.txStateManager.addTx(txMeta) -- cgit v1.2.3 From 03d17c75ae47806e9afa562cf664819b83a2b926 Mon Sep 17 00:00:00 2001 From: Bruno Barbieri Date: Wed, 31 Jan 2018 04:25:32 -0500 Subject: wipe only transactions for current account --- app/scripts/controllers/transactions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/scripts/controllers/transactions.js') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 7ca04caf1..a3670155a 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -152,8 +152,8 @@ module.exports = class TransactionController extends EventEmitter { } } - wipeTransactions(){ - this.txStateManager.wipeTransactions(); + wipeTransactions (address) { + this.txStateManager.wipeTransactions(address) } // Adds a tx to the txlist -- cgit v1.2.3