use provider stub

feature/default_network_editable
frankiebee 7 years ago
parent be4011c310
commit e761fb0ef7
  1. 119
      test/unit/pending-tx-test.js
  2. 34
      test/unit/tx-controller-test.js

@ -3,19 +3,20 @@ const ethUtil = require('ethereumjs-util')
const EthTx = require('ethereumjs-tx') const EthTx = require('ethereumjs-tx')
const ObservableStore = require('obs-store') const ObservableStore = require('obs-store')
const clone = require('clone') const clone = require('clone')
const PendingTransactionWatcher = require('../../app/scripts/lib/pending-tx-watchers') const { createStubedProvider } = require('../stub/provider')
const PendingTransactionTracker = require('../../app/scripts/lib/pending-tx-tracker')
const noop = () => true const noop = () => true
const currentNetworkId = 42 const currentNetworkId = 42
const otherNetworkId = 36 const otherNetworkId = 36
const privKey = new Buffer('8718b9618a37d1fc78c436511fc6df3c8258d3250635bba617f33003270ec03e', 'hex') const privKey = new Buffer('8718b9618a37d1fc78c436511fc6df3c8258d3250635bba617f33003270ec03e', 'hex')
describe('PendingTransactionWatcher', function () { describe('PendingTransactionTracker', function () {
let pendingTxWatcher, txMeta, txMetaNoHash, txMetaNoRawTx let pendingTxTracker, txMeta, txMetaNoHash, txMetaNoRawTx, providerResultStub, provider
this.timeout(10000) this.timeout(10000)
beforeEach(function () { beforeEach(function () {
txMeta = { txMeta = {
id: 1, id: 1,
hash: '0x0593ee121b92e10d63150ad08b4b8f9c7857d1bd160195ee648fb9a0f8d00eebBlock', hash: '0x0593ee121b92e10d63150ad08b4b8f9c7857d1bd160195ee648fb9a0f8d00eeb',
status: 'signed', status: 'signed',
txParams: { txParams: {
from: '0x1678a085c290ebd122dc42cba69373b5953b831d', from: '0x1678a085c290ebd122dc42cba69373b5953b831d',
@ -30,13 +31,15 @@ describe('PendingTransactionWatcher', function () {
txParams: { from: '0x1678a085c290ebd122dc42cba69373b5953b831d'}, txParams: { from: '0x1678a085c290ebd122dc42cba69373b5953b831d'},
} }
txMetaNoRawTx = { txMetaNoRawTx = {
hash: '0x0593ee121b92e10d63150ad08b4b8f9c7857d1bd160195ee648fb9a0f8d00eebBlock', hash: '0x0593ee121b92e10d63150ad08b4b8f9c7857d1bd160195ee648fb9a0f8d00eeb',
status: 'signed', status: 'signed',
txParams: { from: '0x1678a085c290ebd122dc42cba69373b5953b831d'}, txParams: { from: '0x1678a085c290ebd122dc42cba69373b5953b831d'},
} }
providerResultStub = {}
provider = createStubedProvider(providerResultStub)
pendingTxWatcher = new PendingTransactionWatcher({ pendingTxTracker = new PendingTransactionTracker({
provider: { sendAsync: noop }, provider,
getBalance: () => {}, getBalance: () => {},
nonceTracker: { nonceTracker: {
getGlobalLock: async () => { getGlobalLock: async () => {
@ -47,20 +50,6 @@ describe('PendingTransactionWatcher', function () {
sufficientBalance: () => {}, sufficientBalance: () => {},
publishTransaction: () => {}, publishTransaction: () => {},
}) })
pendingTxWatcher.query = new Proxy({}, {
get: (queryStubResult, key) => {
if (key === 'stubResult') {
return function (method, ...args) {
queryStubResult[method] = args
}
} else {
const returnValues = queryStubResult[key]
return () => Promise.resolve(...returnValues)
}
},
})
}) })
describe('#checkForTxInBlock', function () { describe('#checkForTxInBlock', function () {
@ -68,77 +57,77 @@ describe('PendingTransactionWatcher', function () {
// throw a type error if it trys to do anything on the block // throw a type error if it trys to do anything on the block
// thus failing the test // thus failing the test
const block = Proxy.revocable({}, {}).revoke() const block = Proxy.revocable({}, {}).revoke()
pendingTxWatcher.checkForTxInBlock(block) pendingTxTracker.checkForTxInBlock(block)
}) })
it('should emit \'txFailed\' if the txMeta does not have a hash', function (done) { it('should emit \'txFailed\' if the txMeta does not have a hash', function (done) {
const block = Proxy.revocable({}, {}).revoke() const block = Proxy.revocable({}, {}).revoke()
pendingTxWatcher.getPendingTransactions = () => [txMetaNoHash] pendingTxTracker.getPendingTransactions = () => [txMetaNoHash]
pendingTxWatcher.once('txFailed', (txId, err) => { pendingTxTracker.once('txFailed', (txId, err) => {
assert(txId, txMetaNoHash.id, 'should pass txId') assert(txId, txMetaNoHash.id, 'should pass txId')
done() done()
}) })
pendingTxWatcher.checkForTxInBlock(block) pendingTxTracker.checkForTxInBlock(block)
}) })
it('should emit \'txConfirmed\' if the tx is in the block', function (done) { it('should emit \'txConfirmed\' if the tx is in the block', function (done) {
const block = { transactions: [txMeta]} const block = { transactions: [txMeta]}
pendingTxWatcher.getPendingTransactions = () => [txMeta] pendingTxTracker.getPendingTransactions = () => [txMeta]
pendingTxWatcher.once('txConfirmed', (txId) => { pendingTxTracker.once('txConfirmed', (txId) => {
assert(txId, txMeta.id, 'should pass txId') assert(txId, txMeta.id, 'should pass txId')
done() done()
}) })
pendingTxWatcher.once('txFailed', (_, err) => { done(err) }) pendingTxTracker.once('txFailed', (_, err) => { done(err) })
pendingTxWatcher.checkForTxInBlock(block) pendingTxTracker.checkForTxInBlock(block)
}) })
}) })
describe('#queryPendingTxs', function () { describe('#queryPendingTxs', function () {
it('should call #_checkPendingTxs if their is no oldBlock', function (done) { it('should call #_checkPendingTxs if their is no oldBlock', function (done) {
let newBlock, oldBlock let newBlock, oldBlock
newBlock = { number: '0x01' } newBlock = { number: '0x01' }
pendingTxWatcher._checkPendingTxs = done pendingTxTracker._checkPendingTxs = done
pendingTxWatcher.queryPendingTxs({oldBlock, newBlock}) pendingTxTracker.queryPendingTxs({oldBlock, newBlock})
}) })
it('should call #_checkPendingTxs if oldBlock and the newBlock have a diff of greater then 1', function (done) { it('should call #_checkPendingTxs if oldBlock and the newBlock have a diff of greater then 1', function (done) {
let newBlock, oldBlock let newBlock, oldBlock
oldBlock = { number: '0x01' } oldBlock = { number: '0x01' }
newBlock = { number: '0x03' } newBlock = { number: '0x03' }
pendingTxWatcher._checkPendingTxs = done pendingTxTracker._checkPendingTxs = done
pendingTxWatcher.queryPendingTxs({oldBlock, newBlock}) pendingTxTracker.queryPendingTxs({oldBlock, newBlock})
}) })
it('should not call #_checkPendingTxs if oldBlock and the newBlock have a diff of 1 or less', function (done) { it('should not call #_checkPendingTxs if oldBlock and the newBlock have a diff of 1 or less', function (done) {
let newBlock, oldBlock let newBlock, oldBlock
oldBlock = { number: '0x1' } oldBlock = { number: '0x1' }
newBlock = { number: '0x2' } newBlock = { number: '0x2' }
pendingTxWatcher._checkPendingTxs = () => { pendingTxTracker._checkPendingTxs = () => {
const err = new Error('should not call #_checkPendingTxs if oldBlock and the newBlock have a diff of 1 or less') const err = new Error('should not call #_checkPendingTxs if oldBlock and the newBlock have a diff of 1 or less')
done(err) done(err)
} }
pendingTxWatcher.queryPendingTxs({oldBlock, newBlock}) pendingTxTracker.queryPendingTxs({oldBlock, newBlock})
done() done()
}) })
}) })
describe('#_checkPendingTx', function () { describe('#_checkPendingTx', function () {
it('should emit \'txFailed\' if the txMeta does not have a hash', function (done) { it('should emit \'txFailed\' if the txMeta does not have a hash', function (done) {
pendingTxWatcher.once('txFailed', (txId, err) => { pendingTxTracker.once('txFailed', (txId, err) => {
assert(txId, txMetaNoHash.id, 'should pass txId') assert(txId, txMetaNoHash.id, 'should pass txId')
done() done()
}) })
pendingTxWatcher._checkPendingTx(txMetaNoHash) pendingTxTracker._checkPendingTx(txMetaNoHash)
}) })
it('should should return if query does not return txParams', function () { it('should should return if query does not return txParams', function () {
pendingTxWatcher.query.stubResult('getTransactionByHash', null) providerResultStub.eth_getTransactionByHash = null
pendingTxWatcher._checkPendingTx(txMeta) pendingTxTracker._checkPendingTx(txMeta)
}) })
it('should emit \'txConfirmed\'', function (done) { it('should emit \'txConfirmed\'', function (done) {
pendingTxWatcher.query.stubResult('getTransactionByHash', {blockNumber: '0x01'}) providerResultStub.eth_getTransactionByHash = {blockNumber: '0x01'}
pendingTxWatcher.once('txConfirmed', (txId) => { pendingTxTracker.once('txConfirmed', (txId) => {
assert(txId, txMeta.id, 'should pass txId') assert(txId, txMeta.id, 'should pass txId')
done() done()
}) })
pendingTxWatcher.once('txFailed', (_, err) => { done(err) }) pendingTxTracker.once('txFailed', (_, err) => { done(err) })
pendingTxWatcher._checkPendingTx(txMeta) pendingTxTracker._checkPendingTx(txMeta)
}) })
}) })
@ -154,14 +143,14 @@ describe('PendingTransactionWatcher', function () {
}) })
it('should warp all txMeta\'s in #_checkPendingTx', function (done) { it('should warp all txMeta\'s in #_checkPendingTx', function (done) {
pendingTxWatcher.getPendingTransactions = () => txList pendingTxTracker.getPendingTransactions = () => txList
pendingTxWatcher._checkPendingTx = (tx) => { tx.resolve(tx) } pendingTxTracker._checkPendingTx = (tx) => { tx.resolve(tx) }
const list = txList.map const list = txList.map
Promise.all(txList.map((tx) => tx.processed)) Promise.all(txList.map((tx) => tx.processed))
.then((txCompletedList) => done()) .then((txCompletedList) => done())
.catch(done) .catch(done)
pendingTxWatcher._checkPendingTxs() pendingTxTracker._checkPendingTxs()
}) })
}) })
@ -175,15 +164,15 @@ describe('PendingTransactionWatcher', function () {
}) })
it('should return if no pending transactions', function () { it('should return if no pending transactions', function () {
pendingTxWatcher.resubmitPendingTxs() pendingTxTracker.resubmitPendingTxs()
}) })
it('should call #_resubmitTx for all pending tx\'s', function (done) { it('should call #_resubmitTx for all pending tx\'s', function (done) {
pendingTxWatcher.getPendingTransactions = () => txList pendingTxTracker.getPendingTransactions = () => txList
pendingTxWatcher._resubmitTx = async (tx) => { tx.resolve(tx) } pendingTxTracker._resubmitTx = async (tx) => { tx.resolve(tx) }
Promise.all(txList.map((tx) => tx.processed)) Promise.all(txList.map((tx) => tx.processed))
.then((txCompletedList) => done()) .then((txCompletedList) => done())
.catch(done) .catch(done)
pendingTxWatcher.resubmitPendingTxs() pendingTxTracker.resubmitPendingTxs()
}) })
it('should not emit \'txFailed\' if the txMeta throws a known txError', function (done) { it('should not emit \'txFailed\' if the txMeta throws a known txError', function (done) {
knownErrors =[ knownErrors =[
@ -199,10 +188,10 @@ describe('PendingTransactionWatcher', function () {
] ]
const enoughForAllErrors = txList.concat(txList) const enoughForAllErrors = txList.concat(txList)
pendingTxWatcher.on('txFailed', (_, err) => done(err)) pendingTxTracker.on('txFailed', (_, err) => done(err))
pendingTxWatcher.getPendingTransactions = () => enoughForAllErrors pendingTxTracker.getPendingTransactions = () => enoughForAllErrors
pendingTxWatcher._resubmitTx = async (tx) => { pendingTxTracker._resubmitTx = async (tx) => {
tx.resolve() tx.resolve()
throw new Error(knownErrors.pop()) throw new Error(knownErrors.pop())
} }
@ -210,38 +199,38 @@ describe('PendingTransactionWatcher', function () {
.then((txCompletedList) => done()) .then((txCompletedList) => done())
.catch(done) .catch(done)
pendingTxWatcher.resubmitPendingTxs() pendingTxTracker.resubmitPendingTxs()
}) })
it('should emit \'txFailed\' if it encountered a real error', function (done) { it('should emit \'txFailed\' if it encountered a real error', function (done) {
pendingTxWatcher.once('txFailed', (id, err) => err.message === 'im some real error' ? txList[id - 1].resolve() : done(err)) pendingTxTracker.once('txFailed', (id, err) => err.message === 'im some real error' ? txList[id - 1].resolve() : done(err))
pendingTxWatcher.getPendingTransactions = () => txList pendingTxTracker.getPendingTransactions = () => txList
pendingTxWatcher._resubmitTx = async (tx) => { throw new TypeError('im some real error') } pendingTxTracker._resubmitTx = async (tx) => { throw new TypeError('im some real error') }
Promise.all(txList.map((tx) => tx.processed)) Promise.all(txList.map((tx) => tx.processed))
.then((txCompletedList) => done()) .then((txCompletedList) => done())
.catch(done) .catch(done)
pendingTxWatcher.resubmitPendingTxs() pendingTxTracker.resubmitPendingTxs()
}) })
}) })
describe('#_resubmitTx with a too-low balance', function () { describe('#_resubmitTx with a too-low balance', function () {
it('should return before publishing the transaction because to low of balance', function (done) { it('should return before publishing the transaction because to low of balance', function (done) {
const lowBalance = '0x0' const lowBalance = '0x0'
pendingTxWatcher.getBalance = (address) => { pendingTxTracker.getBalance = (address) => {
assert.equal(address, txMeta.txParams.from, 'Should pass the address') assert.equal(address, txMeta.txParams.from, 'Should pass the address')
return lowBalance return lowBalance
} }
pendingTxWatcher.publishTransaction = async (rawTx) => { pendingTxTracker.publishTransaction = async (rawTx) => {
done(new Error('tried to publish transaction')) done(new Error('tried to publish transaction'))
} }
// Stubbing out current account state: // Stubbing out current account state:
// Adding the fake tx: // Adding the fake tx:
pendingTxWatcher.once('txFailed', (txId, err) => { pendingTxTracker.once('txFailed', (txId, err) => {
assert(err, 'Should have a error') assert(err, 'Should have a error')
done() done()
}) })
pendingTxWatcher._resubmitTx(txMeta) pendingTxTracker._resubmitTx(txMeta)
.catch((err) => { .catch((err) => {
assert.ifError(err, 'should not throw an error') assert.ifError(err, 'should not throw an error')
done(err) done(err)
@ -250,17 +239,17 @@ describe('PendingTransactionWatcher', function () {
it('should publishing the transaction', function (done) { it('should publishing the transaction', function (done) {
const enoughBalance = '0x100000' const enoughBalance = '0x100000'
pendingTxWatcher.getBalance = (address) => { pendingTxTracker.getBalance = (address) => {
assert.equal(address, txMeta.txParams.from, 'Should pass the address') assert.equal(address, txMeta.txParams.from, 'Should pass the address')
return enoughBalance return enoughBalance
} }
pendingTxWatcher.publishTransaction = async (rawTx) => { pendingTxTracker.publishTransaction = async (rawTx) => {
assert.equal(rawTx, txMeta.rawTx, 'Should pass the rawTx') assert.equal(rawTx, txMeta.rawTx, 'Should pass the rawTx')
} }
// Stubbing out current account state: // Stubbing out current account state:
// Adding the fake tx: // Adding the fake tx:
pendingTxWatcher._resubmitTx(txMeta) pendingTxTracker._resubmitTx(txMeta)
.then(() => done()) .then(() => done())
.catch((err) => { .catch((err) => {
assert.ifError(err, 'should not throw an error') assert.ifError(err, 'should not throw an error')

@ -10,16 +10,20 @@ const noop = () => true
const currentNetworkId = 42 const currentNetworkId = 42
const otherNetworkId = 36 const otherNetworkId = 36
const privKey = new Buffer('8718b9618a37d1fc78c436511fc6df3c8258d3250635bba617f33003270ec03e', 'hex') const privKey = new Buffer('8718b9618a37d1fc78c436511fc6df3c8258d3250635bba617f33003270ec03e', 'hex')
const { createStubedProvider } = require('../stub/provider')
describe('Transaction Controller', function () { describe('Transaction Controller', function () {
let txController let txController, engine, provider, providerResultStub
beforeEach(function () { beforeEach(function () {
providerResultStub = {}
provider = createStubedProvider(providerResultStub)
txController = new TransactionController({ txController = new TransactionController({
provider,
networkStore: new ObservableStore(currentNetworkId), networkStore: new ObservableStore(currentNetworkId),
txHistoryLimit: 10, txHistoryLimit: 10,
blockTracker: { getCurrentBlock: noop, on: noop, once: noop }, blockTracker: { getCurrentBlock: noop, on: noop, once: noop },
provider: { sendAsync: noop },
ethStore: { getState: noop }, ethStore: { getState: noop },
signTransaction: (ethTx) => new Promise((resolve) => { signTransaction: (ethTx) => new Promise((resolve) => {
ethTx.sign(privKey) ethTx.sign(privKey)
@ -28,19 +32,6 @@ describe('Transaction Controller', function () {
}) })
txController.nonceTracker.getNonceLock = () => Promise.resolve({ nextNonce: 0, releaseLock: noop }) txController.nonceTracker.getNonceLock = () => Promise.resolve({ nextNonce: 0, releaseLock: noop })
txController.txProviderUtils = new TxProvideUtils(txController.provider) txController.txProviderUtils = new TxProvideUtils(txController.provider)
txController.query = txController.txProviderUtils.query = new Proxy({}, {
get: (queryStubResult, key) => {
if (key === 'stubResult') {
return function (method, ...args) {
queryStubResult[method] = args
}
} else {
const returnValues = queryStubResult[key]
return () => Promise.resolve(...returnValues)
}
},
})
}) })
describe('#newUnapprovedTransaction', function () { describe('#newUnapprovedTransaction', function () {
@ -132,11 +123,9 @@ describe('Transaction Controller', function () {
'to':'0xc684832530fcbddae4b4230a47e991ddcec2831d', 'to':'0xc684832530fcbddae4b4230a47e991ddcec2831d',
}, },
} }
providerResultStub.eth_gasPrice = '4a817c800'
txController.query.stubResult('gasPrice', '0x4a817c800') providerResultStub.eth_getBlockByNumber = { gasLimit: '47b784' }
txController.query.stubResult('getBlockByNumber', { gasLimit: '0x47b784' }) providerResultStub.eth_estimateGas = '5209'
txController.query.stubResult('estimateGas', '0x5209')
txController.addTxDefaults(txMeta) txController.addTxDefaults(txMeta)
.then((txMetaWithDefaults) => { .then((txMetaWithDefaults) => {
assert(txMetaWithDefaults.txParams.value, '0x0','should have added 0x0 as the value') assert(txMetaWithDefaults.txParams.value, '0x0','should have added 0x0 as the value')
@ -393,9 +382,8 @@ describe('Transaction Controller', function () {
const wrongValue = '0x05' const wrongValue = '0x05'
txController.addTx(txMeta) txController.addTx(txMeta)
providerResultStub.eth_gasPrice = wrongValue
txController.query.stubResult('estimateGas', wrongValue) providerResultStub.eth_estimateGas = '0x5209'
txController.query.stubResult('gasPrice', wrongValue)
const signStub = sinon.stub(txController, 'signTransaction').callsFake(() => Promise.resolve()) const signStub = sinon.stub(txController, 'signTransaction').callsFake(() => Promise.resolve())

Loading…
Cancel
Save