aboutsummaryrefslogtreecommitdiffstats
path: root/app/scripts/controllers
diff options
context:
space:
mode:
authorkumavis <aaron@kumavis.me>2018-05-29 05:29:31 +0800
committerkumavis <aaron@kumavis.me>2018-05-29 05:29:31 +0800
commit5be154ea2035810462ff0e7051e537870bfc1afb (patch)
tree438d5c4cf20001645adff24151d9f0222bbf5782 /app/scripts/controllers
parent9f8d5f05470d68a7a9a5474a5b1f4587398e94a3 (diff)
downloadtangerine-wallet-browser-5be154ea2035810462ff0e7051e537870bfc1afb.tar
tangerine-wallet-browser-5be154ea2035810462ff0e7051e537870bfc1afb.tar.gz
tangerine-wallet-browser-5be154ea2035810462ff0e7051e537870bfc1afb.tar.bz2
tangerine-wallet-browser-5be154ea2035810462ff0e7051e537870bfc1afb.tar.lz
tangerine-wallet-browser-5be154ea2035810462ff0e7051e537870bfc1afb.tar.xz
tangerine-wallet-browser-5be154ea2035810462ff0e7051e537870bfc1afb.tar.zst
tangerine-wallet-browser-5be154ea2035810462ff0e7051e537870bfc1afb.zip
controllers - transactions - merge @frankiebee's work with mine
Diffstat (limited to 'app/scripts/controllers')
-rw-r--r--app/scripts/controllers/transactions/index.js46
-rw-r--r--app/scripts/controllers/transactions/nonce-tracker.js16
-rw-r--r--app/scripts/controllers/transactions/pending-tx-tracker.js89
3 files changed, 55 insertions, 96 deletions
diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js
index 7cb8af3a8..f84fd95ff 100644
--- a/app/scripts/controllers/transactions/index.js
+++ b/app/scripts/controllers/transactions/index.js
@@ -78,7 +78,7 @@ class TransactionController extends EventEmitter {
})
this.txStateManager.store.subscribe(() => this.emit('update:badge'))
- this._setupListners()
+ this._setupListeners()
// memstore is computed from a few different stores
this._updateMemstore()
this.txStateManager.store.subscribe(() => this._updateMemstore())
@@ -382,8 +382,9 @@ class TransactionController extends EventEmitter {
is called in constructor applies the listeners for pendingTxTracker txStateManager
and blockTracker
*/
- _setupListners () {
+ _setupListeners () {
this.txStateManager.on('tx:status-update', this.emit.bind(this, 'tx:status-update'))
+ this._setupBlockTrackerListener()
this.pendingTxTracker.on('tx:warning', (txMeta) => {
this.txStateManager.updateTx(txMeta, 'transactions/pending-tx-tracker#event: tx:warning')
})
@@ -399,13 +400,6 @@ class TransactionController extends EventEmitter {
txMeta.retryCount++
this.txStateManager.updateTx(txMeta, 'transactions/pending-tx-tracker#event: tx:retry')
})
-
- 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
- this.blockTracker.on('latest', this.pendingTxTracker.resubmitPendingTxs.bind(this.pendingTxTracker))
- this.blockTracker.on('sync', this.pendingTxTracker.queryPendingTxs.bind(this.pendingTxTracker))
-
}
/**
@@ -429,6 +423,40 @@ class TransactionController extends EventEmitter {
})
}
+ _setupBlockTrackerListener () {
+ let listenersAreActive = false
+ const latestBlockHandler = this._onLatestBlock.bind(this)
+ const blockTracker = this.blockTracker
+ const txStateManager = this.txStateManager
+
+ txStateManager.on('tx:status-update', updateSubscription)
+ updateSubscription()
+
+ function updateSubscription() {
+ const pendingTxs = txStateManager.getPendingTransactions()
+ if (!listenersAreActive && pendingTxs.length > 0) {
+ blockTracker.on('latest', latestBlockHandler)
+ listenersAreActive = true
+ } else if (listenersAreActive && !pendingTxs.length) {
+ blockTracker.removeListener('latest', latestBlockHandler)
+ listenersAreActive = false
+ }
+ }
+ }
+
+ async _onLatestBlock (blockNumber) {
+ try {
+ await this.pendingTxTracker.updatePendingTxs()
+ } catch (err) {
+ log.error(err)
+ }
+ try {
+ await this.pendingTxTracker.resubmitPendingTxs(blockNumber)
+ } catch (err) {
+ log.error(err)
+ }
+ }
+
/**
Updates the memStore in transaction controller
*/
diff --git a/app/scripts/controllers/transactions/nonce-tracker.js b/app/scripts/controllers/transactions/nonce-tracker.js
index 490118c89..fe2d25fca 100644
--- a/app/scripts/controllers/transactions/nonce-tracker.js
+++ b/app/scripts/controllers/transactions/nonce-tracker.js
@@ -35,7 +35,7 @@ class NonceTracker {
* @typedef NonceDetails
* @property {number} highestLocallyConfirmed - A hex string of the highest nonce on a confirmed transaction.
* @property {number} nextNetworkNonce - The next nonce suggested by the eth_getTransactionCount method.
- * @property {number} highetSuggested - The maximum between the other two, the number returned.
+ * @property {number} highestSuggested - The maximum between the other two, the number returned.
*/
/**
@@ -75,14 +75,6 @@ class NonceTracker {
return { nextNonce, nonceDetails, releaseLock }
}
- async _getCurrentBlock () {
- const currentBlock = this.blockTracker.getCurrentBlock()
- if (currentBlock) return currentBlock
- return await new Promise((reject, resolve) => {
- this.blockTracker.once('latest', resolve)
- })
- }
-
async _globalMutexFree () {
const globalMutex = this._lookupMutex('global')
const release = await globalMutex.acquire()
@@ -108,9 +100,8 @@ class NonceTracker {
// calculate next nonce
// we need to make sure our base count
// and pending count are from the same block
- const currentBlock = await this._getCurrentBlock()
- const blockNumber = currentBlock.blockNumber
- const baseCountBN = await this.ethQuery.getTransactionCount(address, blockNumber || 'latest')
+ const blockNumber = await this.blockTracker.getLatestBlock()
+ const baseCountBN = await this.ethQuery.getTransactionCount(address, blockNumber)
const baseCount = baseCountBN.toNumber()
assert(Number.isInteger(baseCount), `nonce-tracker - baseCount is not an integer - got: (${typeof baseCount}) "${baseCount}"`)
const nonceDetails = { blockNumber, baseCount }
@@ -171,6 +162,7 @@ class NonceTracker {
return { name: 'local', nonce: highest, details: { startPoint, highest } }
}
+
}
module.exports = NonceTracker
diff --git a/app/scripts/controllers/transactions/pending-tx-tracker.js b/app/scripts/controllers/transactions/pending-tx-tracker.js
index e1bb67c90..e981e2991 100644
--- a/app/scripts/controllers/transactions/pending-tx-tracker.js
+++ b/app/scripts/controllers/transactions/pending-tx-tracker.js
@@ -24,60 +24,27 @@ class PendingTransactionTracker extends EventEmitter {
super()
this.query = new EthQuery(config.provider)
this.nonceTracker = config.nonceTracker
- // default is one day
this.getPendingTransactions = config.getPendingTransactions
this.getCompletedTransactions = config.getCompletedTransactions
this.publishTransaction = config.publishTransaction
this.confirmTransaction = config.confirmTransaction
- this._checkPendingTxs()
+ this.updatePendingTxs()
}
/**
- checks if a signed tx is in a block and
- if it is included emits tx status as 'confirmed'
- @param block {object}, a full block
- @emits tx:confirmed
- @emits tx:failed
- */
- async checkForTxInBlock (blockNumber) {
- const block = await this._getBlock(blockNumber)
- const signedTxList = this.getPendingTransactions()
- 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.emit('tx:failed', txId, noTxHashErr)
- return
- }
-
- if (!block.transactions.length) return
-
- block.transactions.forEach((hash) => {
- if (hash === txHash) {
- this.confirmTransaction(txId)
- }
- })
- })
- }
-
- /**
- asks the network for the transaction to see if a block number is included on it
- if we have skipped/missed blocks
- @param object - oldBlock newBlock
+ checks the network for signed txs and releases the nonce global lock if it is
*/
- queryPendingTxs ({ oldBlock, newBlock }) {
- // check pending transactions on start
- if (!oldBlock) {
- this._checkPendingTxs()
- return
+ async updatePendingTxs () {
+ const pendingTxs = this.getPendingTransactions()
+ // in order to keep the nonceTracker accurate we block it while updating pending transactions
+ const nonceGlobalLock = await this.nonceTracker.getGlobalLock()
+ try {
+ await Promise.all(pendingTxs.map((txMeta) => this._checkPendingTx(txMeta)))
+ } catch (err) {
+ log.error('PendingTransactionTracker - Error updating pending transactions')
+ log.error(err)
}
- // if we synced by more than one block, check for missed pending transactions
- const diff = Number.parseInt(newBlock, 16) - Number.parseInt(oldBlock, 16)
- if (diff > 1) this._checkPendingTxs()
+ nonceGlobalLock.releaseLock()
}
/**
@@ -151,6 +118,7 @@ class PendingTransactionTracker extends EventEmitter {
this.emit('tx:retry', txMeta)
return txHash
}
+
/**
Ask the network for the transaction to see if it has been include in a block
@param txMeta {Object} - the txMeta object
@@ -180,9 +148,8 @@ class PendingTransactionTracker extends EventEmitter {
}
// get latest transaction status
- let txParams
try {
- txParams = await this.query.getTransactionByHash(txHash)
+ const txParams = await this.query.getTransactionByHash(txHash)
if (!txParams) return
if (txParams.blockNumber) {
this.confirmTransaction(txId)
@@ -197,34 +164,6 @@ class PendingTransactionTracker extends EventEmitter {
}
/**
- checks the network for signed txs and releases the nonce global lock if it is
- */
- async _checkPendingTxs () {
- const signedTxList = this.getPendingTransactions()
- // 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) {
- log.error('PendingTransactionWatcher - Error updating pending transactions')
- log.error(err)
- }
- nonceGlobalLock.releaseLock()
- }
-
- async _getBlock (blockNumber) {
- let block
- while (!block) {
- // block requests will sometimes return null due do the infura api
- // being backed by multiple out-of-sync clients
- block = await this.query.getBlockByNumber(blockNumber, false)
- // if block is null, wait 1 sec then try again
- if (!block) await timeout(1000)
- }
- return block
- }
-
- /**
checks to see if a confirmed txMeta has the same nonce
@param txMeta {Object} - txMeta object
@returns {boolean}