aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkumavis <aaron@kumavis.me>2017-06-15 13:16:14 +0800
committerkumavis <aaron@kumavis.me>2017-06-15 13:16:14 +0800
commitdab2fccc78ad76095cc12ce0a1056d9b7a9d6001 (patch)
treee93fe99e11b2922fbff30d2c75794cd6efc32b03
parent1a4f982739a09a4fd757b5f45fcaeef1a93dd4a3 (diff)
downloadtangerine-wallet-browser-dab2fccc78ad76095cc12ce0a1056d9b7a9d6001.tar
tangerine-wallet-browser-dab2fccc78ad76095cc12ce0a1056d9b7a9d6001.tar.gz
tangerine-wallet-browser-dab2fccc78ad76095cc12ce0a1056d9b7a9d6001.tar.bz2
tangerine-wallet-browser-dab2fccc78ad76095cc12ce0a1056d9b7a9d6001.tar.lz
tangerine-wallet-browser-dab2fccc78ad76095cc12ce0a1056d9b7a9d6001.tar.xz
tangerine-wallet-browser-dab2fccc78ad76095cc12ce0a1056d9b7a9d6001.tar.zst
tangerine-wallet-browser-dab2fccc78ad76095cc12ce0a1056d9b7a9d6001.zip
introduce nonce-tracker
-rw-r--r--app/scripts/lib/nonce-tracker.js49
1 files changed, 49 insertions, 0 deletions
diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js
new file mode 100644
index 000000000..6e9d094bc
--- /dev/null
+++ b/app/scripts/lib/nonce-tracker.js
@@ -0,0 +1,49 @@
+const EthQuery = require('ethjs-query')
+
+class NonceTracker {
+
+ constructor({ blockTracker, provider, getPendingTransactions }) {
+ this.blockTracker = blockTracker
+ this.ethQuery = new EthQuery(provider)
+ this.getPendingTransactions = getPendingTransactions
+ this.lockMap = {}
+ }
+
+ // releaseLock must be called
+ // releaseLock must be called after adding signed tx to pending transactions (or discarding)
+ async getNonceLock(address) {
+ // await lock free
+ await this.lockMap[address]
+ // take lock
+ const releaseLock = this._takeLock(address)
+ // calculate next nonce
+ const currentBlock = await this._getCurrentBlock()
+ const blockNumber = currentBlock.number
+ const pendingTransactions = this.getPendingTransactions(address)
+ const baseCount = await this.ethQuery.getTransactionCount(address, blockNumber)
+ const nextNonce = baseCount + pendingTransactions
+ // return next nonce and release cb
+ return { nextNonce, releaseLock }
+ }
+
+ async _getCurrentBlock() {
+ const currentBlock = this.blockTracker.getCurrentBlock()
+ if (currentBlock) return currentBlock
+ return await Promise((reject, resolve) => {
+ this.blockTracker.once('latest', resolve)
+ })
+ }
+
+ _takeLock(lockId) {
+ let releaseLock = null
+ // create and store lock
+ const lock = new Promise((reject, resolve) => { releaseLock = resolve })
+ this.lockMap[lockId] = lock
+ // setup lock teardown
+ lock.then(() => delete this.lockMap[lockId])
+ return releaseLock
+ }
+
+}
+
+module.exports = NonceTracker