diff options
author | Frankie <frankie.diamond@gmail.com> | 2019-05-16 13:36:53 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-16 13:36:53 +0800 |
commit | a34103987a5a3b75588eb23ab4e1a73d6669cbc2 (patch) | |
tree | 4875115e87d1dc4f7d0673107e5583a5e85ec12b /app | |
parent | cb584a6ce526fed5ee1466dc048164cea7807d7b (diff) | |
download | tangerine-wallet-browser-a34103987a5a3b75588eb23ab4e1a73d6669cbc2.tar tangerine-wallet-browser-a34103987a5a3b75588eb23ab4e1a73d6669cbc2.tar.gz tangerine-wallet-browser-a34103987a5a3b75588eb23ab4e1a73d6669cbc2.tar.bz2 tangerine-wallet-browser-a34103987a5a3b75588eb23ab4e1a73d6669cbc2.tar.lz tangerine-wallet-browser-a34103987a5a3b75588eb23ab4e1a73d6669cbc2.tar.xz tangerine-wallet-browser-a34103987a5a3b75588eb23ab4e1a73d6669cbc2.tar.zst tangerine-wallet-browser-a34103987a5a3b75588eb23ab4e1a73d6669cbc2.zip |
drop transactions who's nonce is lower then the known network nonce but were not included in a block (#6388)
* transactions/pending - check nonce against the network and mark as dropped if not included in a block
* transactions/pending - unifiy "dropped" txs
* transactions/pending - test - fix for new expected behavior
* fix comment
* transactions/pending - clean up dropped event
* fix spelling
Co-Authored-By: frankiebee <frankie.diamond@gmail.com>
* nit fix
* test/tx-pending - clarify test description
Diffstat (limited to 'app')
-rw-r--r-- | app/scripts/controllers/transactions/index.js | 1 | ||||
-rw-r--r-- | app/scripts/controllers/transactions/pending-tx-tracker.js | 53 |
2 files changed, 46 insertions, 8 deletions
diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index 79dba7833..dd497a11e 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -555,6 +555,7 @@ class TransactionController extends EventEmitter { }) this.pendingTxTracker.on('tx:failed', this.txStateManager.setTxStatusFailed.bind(this.txStateManager)) this.pendingTxTracker.on('tx:confirmed', (txId) => this.confirmTransaction(txId)) + this.pendingTxTracker.on('tx:dropped', this.txStateManager.setTxStatusDropped.bind(this.txStateManager)) this.pendingTxTracker.on('tx:block-update', (txMeta, latestBlockNumber) => { if (!txMeta.firstRetryBlockNumber) { txMeta.firstRetryBlockNumber = latestBlockNumber diff --git a/app/scripts/controllers/transactions/pending-tx-tracker.js b/app/scripts/controllers/transactions/pending-tx-tracker.js index 4bf40b1db..bc11f6633 100644 --- a/app/scripts/controllers/transactions/pending-tx-tracker.js +++ b/app/scripts/controllers/transactions/pending-tx-tracker.js @@ -22,6 +22,7 @@ const EthQuery = require('ethjs-query') class PendingTransactionTracker extends EventEmitter { constructor (config) { super() + this.droppedBuffer = {} this.query = new EthQuery(config.provider) this.nonceTracker = config.nonceTracker this.getPendingTransactions = config.getPendingTransactions @@ -139,22 +140,42 @@ class PendingTransactionTracker extends EventEmitter { const noTxHashErr = new Error('We had an error while submitting this transaction, please try again.') noTxHashErr.name = 'NoTxHashError' this.emit('tx:failed', txId, noTxHashErr) + return } - // If another tx with the same nonce is mined, set as failed. + // If another tx with the same nonce is mined, set as dropped. const taken = await this._checkIfNonceIsTaken(txMeta) - if (taken) { - const nonceTakenErr = new Error('Another transaction with this nonce has been mined.') - nonceTakenErr.name = 'NonceTakenErr' - return this.emit('tx:failed', txId, nonceTakenErr) + let dropped + try { + // check the network if the nonce is ahead the tx + // and the tx has not been mined into a block + + dropped = await this._checkIftxWasDropped(txMeta) + // the dropped buffer is in case we ask a node for the tx + // that is behind the node we asked for tx count + // IS A SECURITY FOR HITTING NODES IN INFURA THAT COULD GO OUT + // OF SYNC. + // on the next block event it will return fire as dropped + if (dropped && !this.droppedBuffer[txHash]) { + this.droppedBuffer[txHash] = true + dropped = false + } else if (dropped && this.droppedBuffer[txHash]) { + // clean up + delete this.droppedBuffer[txHash] + } + + } catch (e) { + log.error(e) + } + if (taken || dropped) { + return this.emit('tx:dropped', txId) } // get latest transaction status try { - const txParams = await this.query.getTransactionByHash(txHash) - if (!txParams) return - if (txParams.blockNumber) { + const { blockNumber } = await this.query.getTransactionByHash(txHash) || {} + if (blockNumber) { this.emit('tx:confirmed', txId) } } catch (err) { @@ -165,6 +186,22 @@ class PendingTransactionTracker extends EventEmitter { this.emit('tx:warning', txMeta, err) } } + /** + checks to see if if the tx's nonce has been used by another transaction + @param txMeta {Object} - txMeta object + @emits tx:dropped + @returns {boolean} + */ + + async _checkIftxWasDropped (txMeta) { + const { txParams: { nonce, from }, hash } = txMeta + const nextNonce = await this.query.getTransactionCount(from) + const { blockNumber } = await this.query.getTransactionByHash(hash) || {} + if (!blockNumber && parseInt(nextNonce) > parseInt(nonce)) { + return true + } + return false + } /** checks to see if a confirmed txMeta has the same nonce |