1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 01:39:44 +01:00

fix nonceTracker

This commit is contained in:
frankiebee 2017-06-21 19:51:00 -07:00
parent fa8c74fe9b
commit 92df9965eb
3 changed files with 25 additions and 58 deletions

View File

@ -25,7 +25,7 @@ module.exports = class TransactionController extends EventEmitter {
this.blockTracker = opts.blockTracker this.blockTracker = opts.blockTracker
this.nonceTracker = new NonceTracker({ this.nonceTracker = new NonceTracker({
provider: this.provider, provider: this.provider,
blockTracker: this.blockTracker, blockTracker: this.provider._blockTracker,
getPendingTransactions: (address) => this.getFilteredTxList({ from: address, status: 'submitted' }), getPendingTransactions: (address) => this.getFilteredTxList({ from: address, status: 'submitted' }),
}) })
this.query = opts.ethQuery this.query = opts.ethQuery
@ -176,33 +176,7 @@ module.exports = class TransactionController extends EventEmitter {
}, {}) }, {})
} }
// approveTransaction (txId, cb = warn) { async approveTransaction (txId, cb = warn) {
// promiseToCallback((async () => {
// // approve
// self.setTxStatusApproved(txId)
// // get next nonce
// const txMeta = this.getTx(txId)
// const fromAddress = txMeta.txParams.from
// const { nextNonce, releaseLock } = await this.nonceTracker.getNonceLock(fromAddress)
// txMeta.txParams.nonce = nonce
// this.updateTx(txMeta)
// // sign transaction
// const rawTx = await denodeify(self.signTransaction.bind(self))(txId)
// await denodeify(self.publishTransaction.bind(self))(txId, rawTx)
// })())((err) => {
// if (err) {
// this.setTxStatusFailed(txId, {
// errCode: err.errCode || err,
// message: err.message || 'Transaction failed during approval',
// })
// }
// // must set transaction to submitted/failed before releasing lock
// releaseLock()
// cb(err)
// })
// }
async approveTransaction (txId) {
let nonceLock let nonceLock
try { try {
// approve // approve
@ -215,9 +189,10 @@ module.exports = class TransactionController extends EventEmitter {
this.updateTx(txMeta) this.updateTx(txMeta)
// sign transaction // sign transaction
const rawTx = await denodeify(this.signTransaction.bind(this))(txId) const rawTx = await denodeify(this.signTransaction.bind(this))(txId)
await denodeify(this.publishTransaction.bind(this))(txId, rawTx) await this.publishTransaction(txId, rawTx)
// must set transaction to submitted/failed before releasing lock // must set transaction to submitted/failed before releasing lock
nonceLock.releaseLock() nonceLock.releaseLock()
cb()
} catch (err) { } catch (err) {
this.setTxStatusFailed(txId, { this.setTxStatusFailed(txId, {
errCode: err.errCode || err, errCode: err.errCode || err,
@ -226,7 +201,7 @@ module.exports = class TransactionController extends EventEmitter {
// must set transaction to submitted/failed before releasing lock // must set transaction to submitted/failed before releasing lock
if (nonceLock) nonceLock.releaseLock() if (nonceLock) nonceLock.releaseLock()
// continue with error chain // continue with error chain
throw err cb(err)
} }
} }
@ -260,16 +235,17 @@ module.exports = class TransactionController extends EventEmitter {
}) })
} }
publishTransaction (txId, rawTx, cb = warn) { publishTransaction (txId, rawTx) {
const txMeta = this.getTx(txId) const txMeta = this.getTx(txId)
txMeta.rawTx = rawTx txMeta.rawTx = rawTx
this.updateTx(txMeta) this.updateTx(txMeta)
return new Promise((resolve, reject) => {
this.txProviderUtils.publishTransaction(rawTx, (err, txHash) => { this.txProviderUtils.publishTransaction(rawTx, (err, txHash) => {
if (err) return cb(err) if (err) reject(err)
this.setTxHash(txId, txHash) this.setTxHash(txId, txHash)
this.setTxStatusSubmitted(txId) this.setTxStatusSubmitted(txId)
cb() resolve()
})
}) })
} }
@ -414,7 +390,6 @@ module.exports = class TransactionController extends EventEmitter {
this.emit(`${txMeta.id}:${status}`, txId) this.emit(`${txMeta.id}:${status}`, txId)
if (status === 'submitted' || status === 'rejected') { if (status === 'submitted' || status === 'rejected') {
this.emit(`${txMeta.id}:finished`, txMeta) this.emit(`${txMeta.id}:finished`, txMeta)
} }
this.updateTx(txMeta) this.updateTx(txMeta)
this.emit('updateBadge') this.emit('updateBadge')

View File

@ -2,7 +2,7 @@ const EthQuery = require('eth-query')
class NonceTracker { class NonceTracker {
constructor({ blockTracker, provider, getPendingTransactions }) { constructor ({ blockTracker, provider, getPendingTransactions }) {
this.blockTracker = blockTracker this.blockTracker = blockTracker
this.ethQuery = new EthQuery(provider) this.ethQuery = new EthQuery(provider)
this.getPendingTransactions = getPendingTransactions this.getPendingTransactions = getPendingTransactions
@ -11,7 +11,7 @@ class NonceTracker {
// releaseLock must be called // releaseLock must be called
// releaseLock must be called after adding signed tx to pending transactions (or discarding) // releaseLock must be called after adding signed tx to pending transactions (or discarding)
async getNonceLock(address) { async getNonceLock (address) {
// await lock free // await lock free
await this.lockMap[address] await this.lockMap[address]
// take lock // take lock
@ -21,12 +21,12 @@ class NonceTracker {
const blockNumber = currentBlock.number const blockNumber = currentBlock.number
const pendingTransactions = this.getPendingTransactions(address) const pendingTransactions = this.getPendingTransactions(address)
const baseCount = await this._getTxCount(address, blockNumber) const baseCount = await this._getTxCount(address, blockNumber)
const nextNonce = parseInt(baseCount) + pendingTransactions.length + 1 const nextNonce = parseInt(baseCount) + pendingTransactions.length
// return next nonce and release cb // return next nonce and release cb
return { nextNonce: nextNonce.toString(16), releaseLock } return { nextNonce: nextNonce.toString(16), releaseLock }
} }
async _getCurrentBlock() { async _getCurrentBlock () {
const currentBlock = this.blockTracker.getCurrentBlock() const currentBlock = this.blockTracker.getCurrentBlock()
if (currentBlock) return currentBlock if (currentBlock) return currentBlock
return await Promise((reject, resolve) => { return await Promise((reject, resolve) => {
@ -34,15 +34,13 @@ class NonceTracker {
}) })
} }
_takeLock(lockId) { _takeLock (lockId) {
let releaseLock = null let releaseLock = null
// create and store lock // create and store lock
const lock = new Promise((resolve, reject) => { releaseLock = resolve }) const lock = new Promise((resolve, reject) => { releaseLock = resolve })
this.lockMap[lockId] = lock this.lockMap[lockId] = lock
// setup lock teardown // setup lock teardown
lock.then(() => { lock.then(() => delete this.lockMap[lockId])
delete this.lockMap[lockId]
})
return releaseLock return releaseLock
} }

View File

@ -3,31 +3,25 @@ const NonceTracker = require('../../app/scripts/lib/nonce-tracker')
describe('Nonce Tracker', function () { describe('Nonce Tracker', function () {
let nonceTracker, provider, getPendingTransactions, pendingTxs let nonceTracker, provider, getPendingTransactions, pendingTxs
const noop = () => {}
beforeEach(function () { beforeEach(function () {
pendingTxs =[{ pendingTxs = [{
'status': 'submitted', 'status': 'submitted',
'txParams': { 'txParams': {
'from': '0x7d3517b0d011698406d6e0aed8453f0be2697926', 'from': '0x7d3517b0d011698406d6e0aed8453f0be2697926',
'gas': '0x30d40', 'gas': '0x30d40',
'value': '0x0', 'value': '0x0',
'nonce': '0x1', 'nonce': '0x0',
}, },
}] }]
getPendingTransactions = () => pendingTxs getPendingTransactions = () => pendingTxs
provider = { sendAsync: (_, cb) => { cb(undefined , {result: '0x0'}) }, } provider = { sendAsync: (_, cb) => { cb(undefined, {result: '0x0'}) } }
nonceTracker = new NonceTracker({ nonceTracker = new NonceTracker({
blockTracker: { blockTracker: {
getCurrentBlock: () => '0x11b568', getCurrentBlock: () => '0x11b568',
once: (...args) => {
setTimeout(() => {
args.pop()()
}, 5000)
}
}, },
provider, provider,
getPendingTransactions, getPendingTransactions,
@ -38,8 +32,8 @@ describe('Nonce Tracker', function () {
it('should work', async function (done) { it('should work', async function (done) {
this.timeout(15000) this.timeout(15000)
const nonceLock = await nonceTracker.getNonceLock('0x7d3517b0d011698406d6e0aed8453f0be2697926') const nonceLock = await nonceTracker.getNonceLock('0x7d3517b0d011698406d6e0aed8453f0be2697926')
assert.equal(nonceLock.nextNonce, '2', 'nonce should be 2') assert.equal(nonceLock.nextNonce, '1', 'nonce should be 1')
nonceLock.releaseLock() await nonceLock.releaseLock()
done() done()
}) })
}) })