diff options
author | Frankie <frankie.diamond@gmail.com> | 2017-07-14 03:48:50 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-07-14 03:48:50 +0800 |
commit | 9d3207fb7302e74d3d2f8ffad12d50dfd3885fdc (patch) | |
tree | 7fcde7cce82116803a9df3586ad5d91fe812d870 /app/scripts/lib | |
parent | 43b7d5f0ebd420d39eb9257b1edc235d58b0099d (diff) | |
parent | 7eccf5905a830853bbb1932dde9a7f4536d43f55 (diff) | |
download | tangerine-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')
-rw-r--r-- | app/scripts/lib/nodeify.js | 27 | ||||
-rw-r--r-- | app/scripts/lib/nonce-tracker.js | 59 | ||||
-rw-r--r-- | app/scripts/lib/tx-utils.js | 17 |
3 files changed, 76 insertions, 27 deletions
diff --git a/app/scripts/lib/nodeify.js b/app/scripts/lib/nodeify.js index 51d89a8fb..299bfe624 100644 --- a/app/scripts/lib/nodeify.js +++ b/app/scripts/lib/nodeify.js @@ -1,24 +1,9 @@ -module.exports = function (promiseFn) { - return function () { - var args = [] - for (var i = 0; i < arguments.length - 1; i++) { - args.push(arguments[i]) - } - var cb = arguments[arguments.length - 1] +const promiseToCallback = require('promise-to-callback') - const nodeified = promiseFn.apply(this, args) - - if (!nodeified) { - const methodName = String(promiseFn).split('(')[0] - throw new Error(`The ${methodName} did not return a Promise, but was nodeified.`) - } - nodeified.then(function (result) { - cb(null, result) - }) - .catch(function (reason) { - cb(reason) - }) - - return nodeified +module.exports = function(fn, context) { + return function(){ + const args = [].slice.call(arguments) + const callback = args.pop() + promiseToCallback(fn.apply(context, args))(callback) } } 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 diff --git a/app/scripts/lib/tx-utils.js b/app/scripts/lib/tx-utils.js index 4e780fcc0..8f6943937 100644 --- a/app/scripts/lib/tx-utils.js +++ b/app/scripts/lib/tx-utils.js @@ -106,8 +106,13 @@ module.exports = class txProviderUtils { return ethTx } - publishTransaction (rawTx, cb) { - this.query.sendRawTransaction(rawTx, cb) + publishTransaction (rawTx) { + return new Promise((resolve, reject) => { + this.query.sendRawTransaction(rawTx, (err, ress) => { + if (err) reject(err) + else resolve(ress) + }) + }) } validateTxParams (txParams, cb) { @@ -118,11 +123,11 @@ module.exports = class txProviderUtils { } } - sufficientBalance (tx, hexBalance) { + sufficientBalance (txParams, hexBalance) { const balance = hexToBn(hexBalance) - const value = hexToBn(tx.value) - const gasLimit = hexToBn(tx.gas) - const gasPrice = hexToBn(tx.gasPrice) + const value = hexToBn(txParams.value) + const gasLimit = hexToBn(txParams.gas) + const gasPrice = hexToBn(txParams.gasPrice) const maxCost = value.add(gasLimit.mul(gasPrice)) return balance.gte(maxCost) |