aboutsummaryrefslogtreecommitdiffstats
path: root/app/scripts/lib/nonce-tracker.js
diff options
context:
space:
mode:
authorFrankie <frankie.diamond@gmail.com>2017-07-14 03:48:50 +0800
committerGitHub <noreply@github.com>2017-07-14 03:48:50 +0800
commit9d3207fb7302e74d3d2f8ffad12d50dfd3885fdc (patch)
tree7fcde7cce82116803a9df3586ad5d91fe812d870 /app/scripts/lib/nonce-tracker.js
parent43b7d5f0ebd420d39eb9257b1edc235d58b0099d (diff)
parent7eccf5905a830853bbb1932dde9a7f4536d43f55 (diff)
downloadtangerine-wallet-browser-9d3207fb7302e74d3d2f8ffad12d50dfd3885fdc.tar
tangerine-wallet-browser-9d3207fb7302e74d3d2f8ffad12d50dfd3885fdc.tar.gz
tangerine-wallet-browser-9d3207fb7302e74d3d2f8ffad12d50dfd3885fdc.tar.bz2
tangerine-wallet-browser-9d3207fb7302e74d3d2f8ffad12d50dfd3885fdc.tar.lz
tangerine-wallet-browser-9d3207fb7302e74d3d2f8ffad12d50dfd3885fdc.tar.xz
tangerine-wallet-browser-9d3207fb7302e74d3d2f8ffad12d50dfd3885fdc.tar.zst
tangerine-wallet-browser-9d3207fb7302e74d3d2f8ffad12d50dfd3885fdc.zip
Merge pull request #1617 from MetaMask/nonce-tracker
transaction controller - use nonce-tracker
Diffstat (limited to 'app/scripts/lib/nonce-tracker.js')
-rw-r--r--app/scripts/lib/nonce-tracker.js59
1 files changed, 59 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..ab2893b10
--- /dev/null
+++ b/app/scripts/lib/nonce-tracker.js
@@ -0,0 +1,59 @@
+const EthQuery = require('eth-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
+ // we need to make sure our base count
+ // and pending count are from the same block
+ const currentBlock = await this._getCurrentBlock()
+ const pendingTransactions = this.getPendingTransactions(address)
+ const baseCount = await this._getTxCount(address, currentBlock)
+ const nextNonce = parseInt(baseCount) + pendingTransactions.length
+ // return next nonce and release cb
+ return { nextNonce: nextNonce.toString(16), 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((resolve, reject) => { releaseLock = resolve })
+ this.lockMap[lockId] = lock
+ // setup lock teardown
+ lock.then(() => delete this.lockMap[lockId])
+ return releaseLock
+ }
+
+ async _getTxCount (address, currentBlock) {
+ const blockNumber = currentBlock.number
+ return new Promise((resolve, reject) => {
+ this.ethQuery.getTransactionCount(address, blockNumber, (err, result) => {
+ err ? reject(err) : resolve(result)
+ })
+ })
+ }
+
+}
+
+module.exports = NonceTracker