diff options
Diffstat (limited to 'app/scripts/controllers/transactions.js')
-rw-r--r-- | app/scripts/controllers/transactions.js | 103 |
1 files changed, 68 insertions, 35 deletions
diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 07fe2bb26..f6dea34e7 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -24,11 +24,12 @@ 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('block', this.resubmitPendingTxs.bind(this)) + this.blockTracker.on('rawBlock', this.checkForTxInBlock.bind(this)) + 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() this.store.subscribe(() => this._updateMemstore()) @@ -338,12 +339,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,24 +353,24 @@ 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) }) }) } + 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() + } + // PRIVATE METHODS // Should find the tx in the tx list and @@ -411,38 +413,69 @@ 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) { - txMeta.err = { - isWarning: true, - message: 'Gave up submitting tx.', - } - this.updateTx(txMeta) - return log.error(txMeta.err.message) - } + if (txMeta.retryCount > RETRY_LIMIT) return + // Increment a try counter. txMeta.retryCount++ const rawTx = txMeta.rawTx 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 + 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) + } + }) + }) + } + } |