aboutsummaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
authorFrankie <frankie.diamond@gmail.com>2019-05-16 13:36:53 +0800
committerGitHub <noreply@github.com>2019-05-16 13:36:53 +0800
commita34103987a5a3b75588eb23ab4e1a73d6669cbc2 (patch)
tree4875115e87d1dc4f7d0673107e5583a5e85ec12b /app
parentcb584a6ce526fed5ee1466dc048164cea7807d7b (diff)
downloadtangerine-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.js1
-rw-r--r--app/scripts/controllers/transactions/pending-tx-tracker.js53
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