From 613fada49f9d168fb949a370b884367f99deb401 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 19 Dec 2017 14:15:14 +0100 Subject: Add etherToken.getLogsAsync and etherToken.subscribe with tests --- packages/0x.js/test/ether_token_wrapper_test.ts | 171 +++++++++++++++++++++++- packages/0x.js/test/token_wrapper_test.ts | 3 +- packages/0x.js/test/utils/token_utils.ts | 7 + 3 files changed, 179 insertions(+), 2 deletions(-) (limited to 'packages/0x.js/test') diff --git a/packages/0x.js/test/ether_token_wrapper_test.ts b/packages/0x.js/test/ether_token_wrapper_test.ts index b5ed19308..cdb6ef3b6 100644 --- a/packages/0x.js/test/ether_token_wrapper_test.ts +++ b/packages/0x.js/test/ether_token_wrapper_test.ts @@ -4,11 +4,23 @@ import * as chai from 'chai'; import 'mocha'; import * as Web3 from 'web3'; -import {ZeroEx, ZeroExError} from '../src'; +import { + ApprovalContractEventArgs, + BlockParamLiteral, + BlockRange, + DecodedLogEvent, + EtherTokenEvents, + Token, + TransferContractEventArgs, + ZeroEx, + ZeroExError, +} from '../src'; import {artifacts} from '../src/artifacts'; +import {DoneCallback} from '../src/types'; import {chaiSetup} from './utils/chai_setup'; import {constants} from './utils/constants'; +import {TokenUtils} from './utils/token_utils'; import {web3Factory} from './utils/web3_factory'; chaiSetup.configure(); @@ -24,11 +36,13 @@ const MAX_REASONABLE_GAS_COST_IN_WEI = 62517; describe('EtherTokenWrapper', () => { let web3: Web3; let zeroEx: ZeroEx; + let tokens: Token[]; let userAddresses: string[]; let addressWithETH: string; let wethContractAddress: string; let depositWeiAmount: BigNumber; let decimalPlaces: number; + let addressWithoutFunds: string; const gasPrice = new BigNumber(1); const zeroExConfig = { gasPrice, @@ -37,11 +51,13 @@ describe('EtherTokenWrapper', () => { before(async () => { web3 = web3Factory.create(); zeroEx = new ZeroEx(web3.currentProvider, zeroExConfig); + tokens = await zeroEx.tokenRegistry.getTokensAsync(); userAddresses = await zeroEx.getAvailableAddressesAsync(); addressWithETH = userAddresses[0]; wethContractAddress = (zeroEx.etherToken as any)._getContractAddress(artifacts.EtherTokenArtifact); depositWeiAmount = (zeroEx as any)._web3Wrapper.toWei(new BigNumber(5)); decimalPlaces = 7; + addressWithoutFunds = userAddresses[1]; }); beforeEach(async () => { await blockchainLifecycle.startAsync(); @@ -113,4 +129,157 @@ describe('EtherTokenWrapper', () => { ).to.be.rejectedWith(ZeroExError.InsufficientWEthBalanceForWithdrawal); }); }); + describe('#subscribe', () => { + const indexFilterValues = {}; + let etherTokenAddress: string; + const transferAmount = new BigNumber(42); + const allowanceAmount = new BigNumber(42); + before(() => { + const tokenUtils = new TokenUtils(tokens); + const etherToken = tokenUtils.getWethTokenOrThrow(); + etherTokenAddress = etherToken.address; + }); + afterEach(() => { + zeroEx.etherToken.unsubscribeAll(); + }); + // Hack: Mocha does not allow a test to be both async and have a `done` callback + // Since we need to await the receipt of the event in the `subscribe` callback, + // we do need both. A hack is to make the top-level a sync fn w/ a done callback and then + // wrap the rest of the test in an async block + // Source: https://github.com/mochajs/mocha/issues/2407 + it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => { + (async () => { + const callback = (err: Error, logEvent: DecodedLogEvent) => { + expect(logEvent).to.not.be.undefined(); + expect(logEvent.isRemoved).to.be.false(); + expect(logEvent.log.logIndex).to.be.equal(0); + expect(logEvent.log.transactionIndex).to.be.equal(0); + expect(logEvent.log.blockNumber).to.be.a('number'); + const args = logEvent.log.args; + expect(args._from).to.be.equal(addressWithETH); + expect(args._to).to.be.equal(addressWithoutFunds); + expect(args._value).to.be.bignumber.equal(transferAmount); + done(); + }; + await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH); + zeroEx.etherToken.subscribe( + etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callback); + await zeroEx.token.transferAsync( + etherTokenAddress, addressWithETH, addressWithoutFunds, transferAmount, + ); + })().catch(done); + }); + it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => { + (async () => { + const callback = (err: Error, logEvent: DecodedLogEvent) => { + expect(logEvent).to.not.be.undefined(); + expect(logEvent.isRemoved).to.be.false(); + const args = logEvent.log.args; + expect(args._owner).to.be.equal(addressWithETH); + expect(args._spender).to.be.equal(addressWithoutFunds); + expect(args._value).to.be.bignumber.equal(allowanceAmount); + done(); + }; + zeroEx.etherToken.subscribe( + etherTokenAddress, EtherTokenEvents.Approval, indexFilterValues, callback); + await zeroEx.token.setAllowanceAsync( + etherTokenAddress, addressWithETH, addressWithoutFunds, allowanceAmount, + ); + })().catch(done); + }); + it('Outstanding subscriptions are cancelled when zeroEx.setProvider called', (done: DoneCallback) => { + (async () => { + const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent) => { + done(new Error('Expected this subscription to have been cancelled')); + }; + zeroEx.etherToken.subscribe( + etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled, + ); + const callbackToBeCalled = (err: Error, logEvent: DecodedLogEvent) => { + done(); + }; + const newProvider = web3Factory.getRpcProvider(); + zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID); + await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH); + zeroEx.etherToken.subscribe( + etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callbackToBeCalled, + ); + await zeroEx.token.transferAsync( + etherTokenAddress, addressWithETH, addressWithoutFunds, transferAmount, + ); + })().catch(done); + }); + it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => { + (async () => { + const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent) => { + done(new Error('Expected this subscription to have been cancelled')); + }; + await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH); + const subscriptionToken = zeroEx.etherToken.subscribe( + etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled); + zeroEx.etherToken.unsubscribe(subscriptionToken); + await zeroEx.token.transferAsync( + etherTokenAddress, addressWithETH, addressWithoutFunds, transferAmount, + ); + done(); + })().catch(done); + }); + }); + describe('#getLogsAsync', () => { + let etherTokenAddress: string; + let tokenTransferProxyAddress: string; + const blockRange: BlockRange = { + fromBlock: 0, + toBlock: BlockParamLiteral.Latest, + }; + let txHash: string; + before(() => { + addressWithETH = userAddresses[0]; + const tokenUtils = new TokenUtils(tokens); + const etherToken = tokenUtils.getWethTokenOrThrow(); + etherTokenAddress = etherToken.address; + tokenTransferProxyAddress = zeroEx.proxy.getContractAddress(); + }); + it('should get logs with decoded args emitted by Approval', async () => { + txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithETH); + await zeroEx.awaitTransactionMinedAsync(txHash); + const eventName = EtherTokenEvents.Approval; + const indexFilterValues = {}; + const logs = await zeroEx.etherToken.getLogsAsync( + etherTokenAddress, eventName, blockRange, indexFilterValues, + ); + expect(logs).to.have.length(1); + const args = logs[0].args; + expect(logs[0].event).to.be.equal(eventName); + expect(args._owner).to.be.equal(addressWithETH); + expect(args._spender).to.be.equal(tokenTransferProxyAddress); + expect(args._value).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); + }); + it('should only get the logs with the correct event name', async () => { + txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithETH); + await zeroEx.awaitTransactionMinedAsync(txHash); + const differentEventName = EtherTokenEvents.Transfer; + const indexFilterValues = {}; + const logs = await zeroEx.etherToken.getLogsAsync( + etherTokenAddress, differentEventName, blockRange, indexFilterValues, + ); + expect(logs).to.have.length(0); + }); + it('should only get the logs with the correct indexed fields', async () => { + txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithETH); + await zeroEx.awaitTransactionMinedAsync(txHash); + txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithoutFunds); + await zeroEx.awaitTransactionMinedAsync(txHash); + const eventName = EtherTokenEvents.Approval; + const indexFilterValues = { + _owner: addressWithETH, + }; + const logs = await zeroEx.etherToken.getLogsAsync( + etherTokenAddress, eventName, blockRange, indexFilterValues, + ); + expect(logs).to.have.length(1); + const args = logs[0].args; + expect(args._owner).to.be.equal(addressWithETH); + }); + }); }); diff --git a/packages/0x.js/test/token_wrapper_test.ts b/packages/0x.js/test/token_wrapper_test.ts index 48742b663..a43cef675 100644 --- a/packages/0x.js/test/token_wrapper_test.ts +++ b/packages/0x.js/test/token_wrapper_test.ts @@ -7,6 +7,7 @@ import * as Web3 from 'web3'; import { ApprovalContractEventArgs, + BlockParamLiteral, BlockRange, DecodedLogEvent, Token, @@ -15,7 +16,7 @@ import { ZeroEx, ZeroExError, } from '../src'; -import {BlockParamLiteral, DoneCallback} from '../src/types'; +import {DoneCallback} from '../src/types'; import {chaiSetup} from './utils/chai_setup'; import {constants} from './utils/constants'; diff --git a/packages/0x.js/test/utils/token_utils.ts b/packages/0x.js/test/utils/token_utils.ts index 4634899a7..7da7f466c 100644 --- a/packages/0x.js/test/utils/token_utils.ts +++ b/packages/0x.js/test/utils/token_utils.ts @@ -17,6 +17,13 @@ export class TokenUtils { } return zrxToken; } + public getWethTokenOrThrow(): Token { + const wethToken = _.find(this.tokens, {symbol: WETH_TOKEN_SYMBOL}); + if (_.isUndefined(wethToken)) { + throw new Error(InternalZeroExError.WethNotInTokenRegistry); + } + return wethToken; + } public getDummyTokens(): Token[] { const dummyTokens = _.filter(this.tokens, token => { return !_.includes([PROTOCOL_TOKEN_SYMBOL, WETH_TOKEN_SYMBOL], token.symbol); -- cgit v1.2.3 From 78eb79396efcdf803d5be054b28816967fd340e0 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 19 Dec 2017 20:12:46 +0100 Subject: Fix a typo --- packages/0x.js/test/ether_token_wrapper_test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/0x.js/test') diff --git a/packages/0x.js/test/ether_token_wrapper_test.ts b/packages/0x.js/test/ether_token_wrapper_test.ts index cdb6ef3b6..f3feb39c6 100644 --- a/packages/0x.js/test/ether_token_wrapper_test.ts +++ b/packages/0x.js/test/ether_token_wrapper_test.ts @@ -144,7 +144,7 @@ describe('EtherTokenWrapper', () => { }); // Hack: Mocha does not allow a test to be both async and have a `done` callback // Since we need to await the receipt of the event in the `subscribe` callback, - // we do need both. A hack is to make the top-level a sync fn w/ a done callback and then + // we do need both. A hack is to make the top-level async fn w/ a done callback and then // wrap the rest of the test in an async block // Source: https://github.com/mochajs/mocha/issues/2407 it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => { -- cgit v1.2.3 From d639a22cffebed137d703ad76b30f5bcb42de9a4 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 20 Dec 2017 14:01:35 +0100 Subject: Add WETH9 tests --- packages/0x.js/test/ether_token_wrapper_test.ts | 58 ++++++++++++++++++++++++- packages/0x.js/test/utils/token_utils.ts | 2 +- 2 files changed, 57 insertions(+), 3 deletions(-) (limited to 'packages/0x.js/test') diff --git a/packages/0x.js/test/ether_token_wrapper_test.ts b/packages/0x.js/test/ether_token_wrapper_test.ts index f3feb39c6..03f5216ee 100644 --- a/packages/0x.js/test/ether_token_wrapper_test.ts +++ b/packages/0x.js/test/ether_token_wrapper_test.ts @@ -9,9 +9,11 @@ import { BlockParamLiteral, BlockRange, DecodedLogEvent, + DepositContractEventArgs, EtherTokenEvents, Token, TransferContractEventArgs, + WithdrawalContractEventArgs, ZeroEx, ZeroExError, } from '../src'; @@ -48,6 +50,10 @@ describe('EtherTokenWrapper', () => { gasPrice, networkId: constants.TESTRPC_NETWORK_ID, }; + const transferAmount = new BigNumber(42); + const allowanceAmount = new BigNumber(42); + const depositAmount = new BigNumber(42); + const withdrawalAmount = new BigNumber(42); before(async () => { web3 = web3Factory.create(); zeroEx = new ZeroEx(web3.currentProvider, zeroExConfig); @@ -132,8 +138,6 @@ describe('EtherTokenWrapper', () => { describe('#subscribe', () => { const indexFilterValues = {}; let etherTokenAddress: string; - const transferAmount = new BigNumber(42); - const allowanceAmount = new BigNumber(42); before(() => { const tokenUtils = new TokenUtils(tokens); const etherToken = tokenUtils.getWethTokenOrThrow(); @@ -187,6 +191,43 @@ describe('EtherTokenWrapper', () => { ); })().catch(done); }); + it('Should receive the Deposit event when ether is being deposited', (done: DoneCallback) => { + (async () => { + const callback = (err: Error, logEvent: DecodedLogEvent) => { + expect(logEvent).to.not.be.undefined(); + expect(logEvent.isRemoved).to.be.false(); + const args = logEvent.log.args; + expect(args._owner).to.be.equal(addressWithETH); + expect(args._value).to.be.bignumber.equal(depositAmount); + done(); + }; + zeroEx.etherToken.subscribe( + etherTokenAddress, EtherTokenEvents.Deposit, indexFilterValues, callback); + await zeroEx.etherToken.depositAsync( + etherTokenAddress, depositAmount, addressWithETH, + ); + })().catch(done); + }); + it('Should receive the Withdrawal event when ether is being withdrewn', (done: DoneCallback) => { + (async () => { + const callback = (err: Error, logEvent: DecodedLogEvent) => { + expect(logEvent).to.not.be.undefined(); + expect(logEvent.isRemoved).to.be.false(); + const args = logEvent.log.args; + expect(args._owner).to.be.equal(addressWithETH); + expect(args._value).to.be.bignumber.equal(depositAmount); + done(); + }; + await zeroEx.etherToken.depositAsync( + etherTokenAddress, depositAmount, addressWithETH, + ); + zeroEx.etherToken.subscribe( + etherTokenAddress, EtherTokenEvents.Withdrawal, indexFilterValues, callback); + await zeroEx.etherToken.withdrawAsync( + etherTokenAddress, withdrawalAmount, addressWithETH, + ); + })().catch(done); + }); it('Outstanding subscriptions are cancelled when zeroEx.setProvider called', (done: DoneCallback) => { (async () => { const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent) => { @@ -255,6 +296,19 @@ describe('EtherTokenWrapper', () => { expect(args._spender).to.be.equal(tokenTransferProxyAddress); expect(args._value).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); }); + it('should get logs with decoded args emitted by Deposit', async () => { + await zeroEx.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH); + const eventName = EtherTokenEvents.Deposit; + const indexFilterValues = {}; + const logs = await zeroEx.etherToken.getLogsAsync( + etherTokenAddress, eventName, blockRange, indexFilterValues, + ); + expect(logs).to.have.length(1); + const args = logs[0].args; + expect(logs[0].event).to.be.equal(eventName); + expect(args._owner).to.be.equal(addressWithETH); + expect(args._value).to.be.bignumber.equal(depositAmount); + }); it('should only get the logs with the correct event name', async () => { txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithETH); await zeroEx.awaitTransactionMinedAsync(txHash); diff --git a/packages/0x.js/test/utils/token_utils.ts b/packages/0x.js/test/utils/token_utils.ts index 7da7f466c..8774925bc 100644 --- a/packages/0x.js/test/utils/token_utils.ts +++ b/packages/0x.js/test/utils/token_utils.ts @@ -3,7 +3,7 @@ import * as _ from 'lodash'; import {InternalZeroExError, Token} from '../../src/types'; const PROTOCOL_TOKEN_SYMBOL = 'ZRX'; -const WETH_TOKEN_SYMBOL = 'WETH'; +const WETH_TOKEN_SYMBOL = 'WETH9'; export class TokenUtils { private tokens: Token[]; -- cgit v1.2.3 From 2a7cafbf20e4ceb42ab79303213a324261dadc0c Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 20 Dec 2017 14:44:54 +0100 Subject: Add err==null assertions --- packages/0x.js/test/ether_token_wrapper_test.ts | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'packages/0x.js/test') diff --git a/packages/0x.js/test/ether_token_wrapper_test.ts b/packages/0x.js/test/ether_token_wrapper_test.ts index 03f5216ee..b64c53283 100644 --- a/packages/0x.js/test/ether_token_wrapper_test.ts +++ b/packages/0x.js/test/ether_token_wrapper_test.ts @@ -154,6 +154,7 @@ describe('EtherTokenWrapper', () => { it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => { (async () => { const callback = (err: Error, logEvent: DecodedLogEvent) => { + expect(err).to.be.null(); expect(logEvent).to.not.be.undefined(); expect(logEvent.isRemoved).to.be.false(); expect(logEvent.log.logIndex).to.be.equal(0); @@ -176,6 +177,7 @@ describe('EtherTokenWrapper', () => { it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => { (async () => { const callback = (err: Error, logEvent: DecodedLogEvent) => { + expect(err).to.be.null(); expect(logEvent).to.not.be.undefined(); expect(logEvent.isRemoved).to.be.false(); const args = logEvent.log.args; @@ -194,6 +196,7 @@ describe('EtherTokenWrapper', () => { it('Should receive the Deposit event when ether is being deposited', (done: DoneCallback) => { (async () => { const callback = (err: Error, logEvent: DecodedLogEvent) => { + expect(err).to.be.null(); expect(logEvent).to.not.be.undefined(); expect(logEvent.isRemoved).to.be.false(); const args = logEvent.log.args; @@ -211,6 +214,7 @@ describe('EtherTokenWrapper', () => { it('Should receive the Withdrawal event when ether is being withdrewn', (done: DoneCallback) => { (async () => { const callback = (err: Error, logEvent: DecodedLogEvent) => { + expect(err).to.be.null(); expect(logEvent).to.not.be.undefined(); expect(logEvent.isRemoved).to.be.false(); const args = logEvent.log.args; -- cgit v1.2.3 From 01bc254cd0cc96d2657aec61a21bddae44bb5d0e Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 20 Dec 2017 14:45:13 +0100 Subject: Fix a typo --- packages/0x.js/test/ether_token_wrapper_test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/0x.js/test') diff --git a/packages/0x.js/test/ether_token_wrapper_test.ts b/packages/0x.js/test/ether_token_wrapper_test.ts index b64c53283..4d12f9f88 100644 --- a/packages/0x.js/test/ether_token_wrapper_test.ts +++ b/packages/0x.js/test/ether_token_wrapper_test.ts @@ -211,7 +211,7 @@ describe('EtherTokenWrapper', () => { ); })().catch(done); }); - it('Should receive the Withdrawal event when ether is being withdrewn', (done: DoneCallback) => { + it('Should receive the Withdrawal event when ether is being withdrawn', (done: DoneCallback) => { (async () => { const callback = (err: Error, logEvent: DecodedLogEvent) => { expect(err).to.be.null(); -- cgit v1.2.3 From 455f74d449738d43abb5caee3aa02ea86286866c Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 20 Dec 2017 14:45:35 +0100 Subject: Fix test description --- packages/0x.js/test/ether_token_wrapper_test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/0x.js/test') diff --git a/packages/0x.js/test/ether_token_wrapper_test.ts b/packages/0x.js/test/ether_token_wrapper_test.ts index 4d12f9f88..4fcb37409 100644 --- a/packages/0x.js/test/ether_token_wrapper_test.ts +++ b/packages/0x.js/test/ether_token_wrapper_test.ts @@ -232,7 +232,7 @@ describe('EtherTokenWrapper', () => { ); })().catch(done); }); - it('Outstanding subscriptions are cancelled when zeroEx.setProvider called', (done: DoneCallback) => { + it('should cancel outstanding subscriptions when ZeroEx.setProvider is called', (done: DoneCallback) => { (async () => { const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent) => { done(new Error('Expected this subscription to have been cancelled')); -- cgit v1.2.3 From d05a36deed7c79cd31656d0d7977ba7be7784243 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 20 Dec 2017 15:02:22 +0100 Subject: Fix WETH symbol --- packages/0x.js/test/utils/token_utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/0x.js/test') diff --git a/packages/0x.js/test/utils/token_utils.ts b/packages/0x.js/test/utils/token_utils.ts index 8774925bc..7da7f466c 100644 --- a/packages/0x.js/test/utils/token_utils.ts +++ b/packages/0x.js/test/utils/token_utils.ts @@ -3,7 +3,7 @@ import * as _ from 'lodash'; import {InternalZeroExError, Token} from '../../src/types'; const PROTOCOL_TOKEN_SYMBOL = 'ZRX'; -const WETH_TOKEN_SYMBOL = 'WETH9'; +const WETH_TOKEN_SYMBOL = 'WETH'; export class TokenUtils { private tokens: Token[]; -- cgit v1.2.3