aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorFabio Berger <me@fabioberger.com>2017-11-13 11:17:18 +0800
committerFabio Berger <me@fabioberger.com>2017-11-13 11:17:18 +0800
commitc4ee2d73865a1444c079b9e2836b7630a0adf03e (patch)
treeb9c7794e7022fb189675d914f5fe58dcabd67dec /test
parenta74ec0effa818a86233fe64cb0dad2c61bbb4bb6 (diff)
downloaddexon-0x-contracts-c4ee2d73865a1444c079b9e2836b7630a0adf03e.tar.gz
dexon-0x-contracts-c4ee2d73865a1444c079b9e2836b7630a0adf03e.tar.zst
dexon-0x-contracts-c4ee2d73865a1444c079b9e2836b7630a0adf03e.zip
Switch over to Lerna + Yarn Workspaces setup for a mono-repo approach
Diffstat (limited to 'test')
-rw-r--r--test/0x.js_test.ts259
-rw-r--r--test/artifacts_test.ts49
-rw-r--r--test/assert_test.ts34
-rw-r--r--test/ether_token_wrapper_test.ts111
-rw-r--r--test/event_watcher_test.ts127
-rw-r--r--test/exchange_transfer_simulator_test.ts87
-rw-r--r--test/exchange_wrapper_test.ts824
-rw-r--r--test/order_state_watcher_test.ts356
-rw-r--r--test/order_validation_test.ts327
-rw-r--r--test/subscription_test.ts95
-rw-r--r--test/token_registry_wrapper_test.ts123
-rw-r--r--test/token_transfer_proxy_wrapper_test.ts31
-rw-r--r--test/token_wrapper_test.ts477
-rw-r--r--test/utils/blockchain_lifecycle.ts26
-rw-r--r--test/utils/chai_setup.ts13
-rw-r--r--test/utils/constants.ts8
-rw-r--r--test/utils/fill_scenarios.ts114
-rw-r--r--test/utils/order_factory.ts42
-rw-r--r--test/utils/report_callback_errors.ts14
-rw-r--r--test/utils/rpc.ts57
-rw-r--r--test/utils/token_utils.ts24
-rw-r--r--test/utils/web3_factory.ts31
-rw-r--r--test/web3_wrapper_test.ts29
23 files changed, 0 insertions, 3258 deletions
diff --git a/test/0x.js_test.ts b/test/0x.js_test.ts
deleted file mode 100644
index d56acc38b..000000000
--- a/test/0x.js_test.ts
+++ /dev/null
@@ -1,259 +0,0 @@
-import * as _ from 'lodash';
-import * as chai from 'chai';
-import {chaiSetup} from './utils/chai_setup';
-import 'mocha';
-import BigNumber from 'bignumber.js';
-import * as Sinon from 'sinon';
-import {ZeroEx, Order, ZeroExError, LogWithDecodedArgs, ApprovalContractEventArgs, TokenEvents} from '../src';
-import {constants} from './utils/constants';
-import {TokenUtils} from './utils/token_utils';
-import {web3Factory} from './utils/web3_factory';
-import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
-
-const blockchainLifecycle = new BlockchainLifecycle();
-chaiSetup.configure();
-const expect = chai.expect;
-
-describe('ZeroEx library', () => {
- const web3 = web3Factory.create();
- const zeroEx = new ZeroEx(web3.currentProvider);
- describe('#setProvider', () => {
- it('overrides provider in nested web3s and invalidates contractInstances', async () => {
- // Instantiate the contract instances with the current provider
- await (zeroEx.exchange as any)._getExchangeContractAsync();
- await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync();
- expect((zeroEx.exchange as any)._exchangeContractIfExists).to.not.be.undefined();
- expect((zeroEx.tokenRegistry as any)._tokenRegistryContractIfExists).to.not.be.undefined();
-
- const newProvider = web3Factory.getRpcProvider();
- // Add property to newProvider so that we can differentiate it from old provider
- (newProvider as any).zeroExTestId = 1;
- await zeroEx.setProviderAsync(newProvider);
-
- // Check that contractInstances with old provider are removed after provider update
- expect((zeroEx.exchange as any)._exchangeContractIfExists).to.be.undefined();
- expect((zeroEx.tokenRegistry as any)._tokenRegistryContractIfExists).to.be.undefined();
-
- // Check that all nested web3 wrapper instances return the updated provider
- const nestedWeb3WrapperProvider = (zeroEx as any)._web3Wrapper.getCurrentProvider();
- expect((nestedWeb3WrapperProvider as any).zeroExTestId).to.be.a('number');
- const exchangeWeb3WrapperProvider = (zeroEx.exchange as any)._web3Wrapper.getCurrentProvider();
- expect((exchangeWeb3WrapperProvider as any).zeroExTestId).to.be.a('number');
- const tokenRegistryWeb3WrapperProvider = (zeroEx.tokenRegistry as any)._web3Wrapper.getCurrentProvider();
- expect((tokenRegistryWeb3WrapperProvider as any).zeroExTestId).to.be.a('number');
- });
- });
- describe('#isValidSignature', () => {
- // The Exchange smart contract `isValidSignature` method only validates orderHashes and assumes
- // the length of the data is exactly 32 bytes. Thus for these tests, we use data of this size.
- const dataHex = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
- const signature = {
- v: 27,
- r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
- s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
- };
- const address = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
- it('should return false if the data doesn\'t pertain to the signature & address', async () => {
- expect(ZeroEx.isValidSignature('0x0', signature, address)).to.be.false();
- return expect(
- (zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync('0x0', signature, address),
- ).to.become(false);
- });
- it('should return false if the address doesn\'t pertain to the signature & data', async () => {
- const validUnrelatedAddress = '0x8b0292b11a196601ed2ce54b665cafeca0347d42';
- expect(ZeroEx.isValidSignature(dataHex, signature, validUnrelatedAddress)).to.be.false();
- return expect(
- (zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, signature,
- validUnrelatedAddress),
- ).to.become(false);
- });
- it('should return false if the signature doesn\'t pertain to the dataHex & address', async () => {
- const wrongSignature = _.assign({}, signature, {v: 28});
- expect(ZeroEx.isValidSignature(dataHex, wrongSignature, address)).to.be.false();
- return expect(
- (zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, wrongSignature, address),
- ).to.become(false);
- });
- it('should return true if the signature does pertain to the dataHex & address', async () => {
- const isValidSignatureLocal = ZeroEx.isValidSignature(dataHex, signature, address);
- expect(isValidSignatureLocal).to.be.true();
- const isValidSignatureOnContract = await (zeroEx.exchange as any)
- ._isValidSignatureUsingContractCallAsync(dataHex, signature, address);
- return expect(isValidSignatureOnContract).to.be.true();
- });
- });
- describe('#generateSalt', () => {
- it('generates different salts', () => {
- const equal = ZeroEx.generatePseudoRandomSalt().eq(ZeroEx.generatePseudoRandomSalt());
- expect(equal).to.be.false();
- });
- it('generates salt in range [0..2^256)', () => {
- const salt = ZeroEx.generatePseudoRandomSalt();
- expect(salt.greaterThanOrEqualTo(0)).to.be.true();
- const twoPow256 = new BigNumber(2).pow(256);
- expect(salt.lessThan(twoPow256)).to.be.true();
- });
- });
- describe('#isValidOrderHash', () => {
- it('returns false if the value is not a hex string', () => {
- const isValid = ZeroEx.isValidOrderHash('not a hex');
- expect(isValid).to.be.false();
- });
- it('returns false if the length is wrong', () => {
- const isValid = ZeroEx.isValidOrderHash('0xdeadbeef');
- expect(isValid).to.be.false();
- });
- it('returns true if order hash is correct', () => {
- const isValid = ZeroEx.isValidOrderHash('0x' + Array(65).join('0'));
- expect(isValid).to.be.true();
- });
- });
- describe('#toUnitAmount', () => {
- it('Should return the expected unit amount for the decimals passed in', () => {
- const baseUnitAmount = new BigNumber(1000000000);
- const decimals = 6;
- const unitAmount = ZeroEx.toUnitAmount(baseUnitAmount, decimals);
- const expectedUnitAmount = new BigNumber(1000);
- expect(unitAmount).to.be.bignumber.equal(expectedUnitAmount);
- });
- });
- describe('#toBaseUnitAmount', () => {
- it('Should return the expected base unit amount for the decimals passed in', () => {
- const unitAmount = new BigNumber(1000);
- const decimals = 6;
- const baseUnitAmount = ZeroEx.toBaseUnitAmount(unitAmount, decimals);
- const expectedUnitAmount = new BigNumber(1000000000);
- expect(baseUnitAmount).to.be.bignumber.equal(expectedUnitAmount);
- });
- });
- describe('#getOrderHashHex', () => {
- const expectedOrderHash = '0x39da987067a3c9e5f1617694f1301326ba8c8b0498ebef5df4863bed394e3c83';
- const fakeExchangeContractAddress = '0xb69e673309512a9d726f87304c6984054f87a93b';
- const order: Order = {
- maker: constants.NULL_ADDRESS,
- taker: constants.NULL_ADDRESS,
- feeRecipient: constants.NULL_ADDRESS,
- makerTokenAddress: constants.NULL_ADDRESS,
- takerTokenAddress: constants.NULL_ADDRESS,
- exchangeContractAddress: fakeExchangeContractAddress,
- salt: new BigNumber(0),
- makerFee: new BigNumber(0),
- takerFee: new BigNumber(0),
- makerTokenAmount: new BigNumber(0),
- takerTokenAmount: new BigNumber(0),
- expirationUnixTimestampSec: new BigNumber(0),
- };
- it('calculates the order hash', async () => {
- const orderHash = ZeroEx.getOrderHashHex(order);
- expect(orderHash).to.be.equal(expectedOrderHash);
- });
- });
- describe('#signOrderHashAsync', () => {
- let stubs: Sinon.SinonStub[] = [];
- let makerAddress: string;
- before(async () => {
- const availableAddreses = await zeroEx.getAvailableAddressesAsync();
- makerAddress = availableAddreses[0];
- });
- afterEach(() => {
- // clean up any stubs after the test has completed
- _.each(stubs, s => s.restore());
- stubs = [];
- });
- it('Should return the correct ECSignature', async () => {
- const orderHash = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
- const expectedECSignature = {
- v: 27,
- r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
- s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
- };
- const ecSignature = await zeroEx.signOrderHashAsync(orderHash, makerAddress);
- expect(ecSignature).to.deep.equal(expectedECSignature);
- });
- it('should return the correct ECSignature for signatureHex concatenated as R + S + V', async () => {
- const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004';
- // tslint:disable-next-line: max-line-length
- const signature = '0x22109d11d79cb8bf96ed88625e1cd9558800c4073332a9a02857499883ee5ce3050aa3cc1f2c435e67e114cdce54b9527b4f50548342401bc5d2b77adbdacb021b';
- const expectedECSignature = {
- v: 27,
- r: '0x22109d11d79cb8bf96ed88625e1cd9558800c4073332a9a02857499883ee5ce3',
- s: '0x050aa3cc1f2c435e67e114cdce54b9527b4f50548342401bc5d2b77adbdacb02',
- };
- stubs = [
- Sinon.stub((zeroEx as any)._web3Wrapper, 'signTransactionAsync')
- .returns(Promise.resolve(signature)),
- Sinon.stub(ZeroEx, 'isValidSignature').returns(true),
- ];
-
- const ecSignature = await zeroEx.signOrderHashAsync(orderHash, makerAddress);
- expect(ecSignature).to.deep.equal(expectedECSignature);
- });
- it('should return the correct ECSignature for signatureHex concatenated as V + R + S', async () => {
- const orderHash = '0xc793e33ffded933b76f2f48d9aa3339fc090399d5e7f5dec8d3660f5480793f7';
- // tslint:disable-next-line: max-line-length
- const signature = '0x1bc80bedc6756722672753413efdd749b5adbd4fd552595f59c13427407ee9aee02dea66f25a608bbae457e020fb6decb763deb8b7192abab624997242da248960';
- const expectedECSignature = {
- v: 27,
- r: '0xc80bedc6756722672753413efdd749b5adbd4fd552595f59c13427407ee9aee0',
- s: '0x2dea66f25a608bbae457e020fb6decb763deb8b7192abab624997242da248960',
- };
- stubs = [
- Sinon.stub((zeroEx as any)._web3Wrapper, 'signTransactionAsync')
- .returns(Promise.resolve(signature)),
- Sinon.stub(ZeroEx, 'isValidSignature').returns(true),
- ];
-
- const ecSignature = await zeroEx.signOrderHashAsync(orderHash, makerAddress);
- expect(ecSignature).to.deep.equal(expectedECSignature);
- });
- });
- describe('#awaitTransactionMinedAsync', () => {
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
- it('returns transaction receipt with decoded logs', async () => {
- const availableAddresses = await zeroEx.getAvailableAddressesAsync();
- const coinbase = availableAddresses[0];
- const tokens = await zeroEx.tokenRegistry.getTokensAsync();
- const tokenUtils = new TokenUtils(tokens);
- const zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address;
- const proxyAddress = await zeroEx.proxy.getContractAddressAsync();
- const txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(zrxTokenAddress, coinbase);
- const txReceiptWithDecodedLogs = await zeroEx.awaitTransactionMinedAsync(txHash);
- const log = txReceiptWithDecodedLogs.logs[0] as LogWithDecodedArgs<ApprovalContractEventArgs>;
- expect(log.event).to.be.equal(TokenEvents.Approval);
- expect(log.args._owner).to.be.equal(coinbase);
- expect(log.args._spender).to.be.equal(proxyAddress);
- expect(log.args._value).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
- });
- });
- describe('#config', () => {
- it('allows to specify exchange contract address', async () => {
- const config = {
- exchangeContractAddress: ZeroEx.NULL_ADDRESS,
- };
- const zeroExWithWrongExchangeAddress = new ZeroEx(web3.currentProvider, config);
- return expect(zeroExWithWrongExchangeAddress.exchange.getContractAddressAsync())
- .to.be.rejectedWith(ZeroExError.ContractDoesNotExist);
- });
- it('allows to specify ether token contract address', async () => {
- const config = {
- etherTokenContractAddress: ZeroEx.NULL_ADDRESS,
- };
- const zeroExWithWrongEtherTokenAddress = new ZeroEx(web3.currentProvider, config);
- return expect(zeroExWithWrongEtherTokenAddress.etherToken.getContractAddressAsync())
- .to.be.rejectedWith(ZeroExError.ContractDoesNotExist);
- });
- it('allows to specify token registry token contract address', async () => {
- const config = {
- tokenRegistryContractAddress: ZeroEx.NULL_ADDRESS,
- };
- const zeroExWithWrongTokenRegistryAddress = new ZeroEx(web3.currentProvider, config);
- return expect(zeroExWithWrongTokenRegistryAddress.tokenRegistry.getContractAddressAsync())
- .to.be.rejectedWith(ZeroExError.ContractDoesNotExist);
- });
- });
-});
diff --git a/test/artifacts_test.ts b/test/artifacts_test.ts
deleted file mode 100644
index b2866a1d6..000000000
--- a/test/artifacts_test.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import * as fs from 'fs';
-import * as chai from 'chai';
-import {chaiSetup} from './utils/chai_setup';
-import HDWalletProvider = require('truffle-hdwallet-provider');
-import {ZeroEx} from '../src';
-import {constants} from './utils/constants';
-
-chaiSetup.configure();
-const expect = chai.expect;
-
-// Those tests are slower cause they're talking to a remote node
-const TIMEOUT = 10000;
-
-describe('Artifacts', () => {
- describe('contracts are deployed on kovan', () => {
- const kovanRpcUrl = constants.KOVAN_RPC_URL;
- const packageJSONContent = fs.readFileSync('package.json', 'utf-8');
- const packageJSON = JSON.parse(packageJSONContent);
- const mnemonic = packageJSON.config.mnemonic;
- const web3Provider = new HDWalletProvider(mnemonic, kovanRpcUrl);
- const zeroEx = new ZeroEx(web3Provider);
- it('token registry contract is deployed', async () => {
- await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync();
- }).timeout(TIMEOUT);
- it('proxy contract is deployed', async () => {
- await (zeroEx.token as any)._getTokenTransferProxyAddressAsync();
- }).timeout(TIMEOUT);
- it('exchange contract is deployed', async () => {
- await zeroEx.exchange.getContractAddressAsync();
- }).timeout(TIMEOUT);
- });
- describe('contracts are deployed on ropsten', () => {
- const ropstenRpcUrl = constants.ROPSTEN_RPC_URL;
- const packageJSONContent = fs.readFileSync('package.json', 'utf-8');
- const packageJSON = JSON.parse(packageJSONContent);
- const mnemonic = packageJSON.config.mnemonic;
- const web3Provider = new HDWalletProvider(mnemonic, ropstenRpcUrl);
- const zeroEx = new ZeroEx(web3Provider);
- it('token registry contract is deployed', async () => {
- await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync();
- }).timeout(TIMEOUT);
- it('proxy contract is deployed', async () => {
- await (zeroEx.token as any)._getTokenTransferProxyAddressAsync();
- }).timeout(TIMEOUT);
- it('exchange contract is deployed', async () => {
- await zeroEx.exchange.getContractAddressAsync();
- }).timeout(TIMEOUT);
- });
-});
diff --git a/test/assert_test.ts b/test/assert_test.ts
deleted file mode 100644
index bfca95d9c..000000000
--- a/test/assert_test.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import * as chai from 'chai';
-import 'mocha';
-import {ZeroEx} from '../src';
-import {assert} from '../src/utils/assert';
-import {web3Factory} from './utils/web3_factory';
-
-const expect = chai.expect;
-
-describe('Assertion library', () => {
- const web3 = web3Factory.create();
- const zeroEx = new ZeroEx(web3.currentProvider);
- describe('#isSenderAddressHexAsync', () => {
- it('throws when address is invalid', async () => {
- const address = '0xdeadbeef';
- const varName = 'address';
- return expect(assert.isSenderAddressAsync(varName, address, (zeroEx as any)._web3Wrapper))
- .to.be.rejectedWith(`Expected ${varName} to be of type ETHAddressHex, encountered: ${address}`);
- });
- it('throws when address is unavailable', async () => {
- const validUnrelatedAddress = '0x8b0292b11a196601eddce54b665cafeca0347d42';
- const varName = 'address';
- return expect(assert.isSenderAddressAsync(varName, validUnrelatedAddress, (zeroEx as any)._web3Wrapper))
- .to.be.rejectedWith(
- `Specified ${varName} ${validUnrelatedAddress} isn't available through the supplied web3 provider`,
- );
- });
- it('doesn\'t throw if address is available', async () => {
- const availableAddress = (await zeroEx.getAvailableAddressesAsync())[0];
- const varName = 'address';
- return expect(assert.isSenderAddressAsync(varName, availableAddress, (zeroEx as any)._web3Wrapper))
- .to.become(undefined);
- });
- });
-});
diff --git a/test/ether_token_wrapper_test.ts b/test/ether_token_wrapper_test.ts
deleted file mode 100644
index ba679d1a1..000000000
--- a/test/ether_token_wrapper_test.ts
+++ /dev/null
@@ -1,111 +0,0 @@
-import 'mocha';
-import * as chai from 'chai';
-import {chaiSetup} from './utils/chai_setup';
-import * as Web3 from 'web3';
-import BigNumber from 'bignumber.js';
-import {web3Factory} from './utils/web3_factory';
-import {ZeroEx, ZeroExError} from '../src';
-import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
-
-chaiSetup.configure();
-const expect = chai.expect;
-const blockchainLifecycle = new BlockchainLifecycle();
-
-// Since the address depositing/withdrawing ETH/WETH also needs to pay gas costs for the transaction,
-// a small amount of ETH will be used to pay this gas cost. We therefore check that the difference between
-// the expected balance and actual balance (given the amount of ETH deposited), only deviates by the amount
-// required to pay gas costs.
-const MAX_REASONABLE_GAS_COST_IN_WEI = 62237;
-
-describe('EtherTokenWrapper', () => {
- let web3: Web3;
- let zeroEx: ZeroEx;
- let userAddresses: string[];
- let addressWithETH: string;
- let wethContractAddress: string;
- let depositWeiAmount: BigNumber;
- let decimalPlaces: number;
- const gasPrice = new BigNumber(1);
- const zeroExConfig = {
- gasPrice,
- };
- before(async () => {
- web3 = web3Factory.create();
- zeroEx = new ZeroEx(web3.currentProvider, zeroExConfig);
- userAddresses = await zeroEx.getAvailableAddressesAsync();
- addressWithETH = userAddresses[0];
- wethContractAddress = await zeroEx.etherToken.getContractAddressAsync();
- depositWeiAmount = (zeroEx as any)._web3Wrapper.toWei(new BigNumber(5));
- decimalPlaces = 7;
- });
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
- describe('#depositAsync', () => {
- it('should successfully deposit ETH and issue Wrapped ETH tokens', async () => {
- const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
- const preWETHBalance = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH);
- expect(preETHBalance).to.be.bignumber.gt(0);
- expect(preWETHBalance).to.be.bignumber.equal(0);
-
- const txHash = await zeroEx.etherToken.depositAsync(depositWeiAmount, addressWithETH);
- await zeroEx.awaitTransactionMinedAsync(txHash);
-
- const postETHBalanceInWei = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
- const postWETHBalanceInBaseUnits = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH);
-
- expect(postWETHBalanceInBaseUnits).to.be.bignumber.equal(depositWeiAmount);
- const remainingETHInWei = preETHBalance.minus(depositWeiAmount);
- const gasCost = remainingETHInWei.minus(postETHBalanceInWei);
- expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI);
- });
- it('should throw if user has insufficient ETH balance for deposit', async () => {
- const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
-
- const extraETHBalance = (zeroEx as any)._web3Wrapper.toWei(5, 'ether');
- const overETHBalanceinWei = preETHBalance.add(extraETHBalance);
-
- return expect(
- zeroEx.etherToken.depositAsync(overETHBalanceinWei, addressWithETH),
- ).to.be.rejectedWith(ZeroExError.InsufficientEthBalanceForDeposit);
- });
- });
- describe('#withdrawAsync', () => {
- it('should successfully withdraw ETH in return for Wrapped ETH tokens', async () => {
- const ETHBalanceInWei = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
-
- await zeroEx.etherToken.depositAsync(depositWeiAmount, addressWithETH);
-
- const expectedPreETHBalance = ETHBalanceInWei.minus(depositWeiAmount);
- const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
- const preWETHBalance = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH);
- let gasCost = expectedPreETHBalance.minus(preETHBalance);
- expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI);
- expect(preWETHBalance).to.be.bignumber.equal(depositWeiAmount);
-
- const txHash = await zeroEx.etherToken.withdrawAsync(depositWeiAmount, addressWithETH);
- await zeroEx.awaitTransactionMinedAsync(txHash);
-
- const postETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
- const postWETHBalanceInBaseUnits = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH);
-
- expect(postWETHBalanceInBaseUnits).to.be.bignumber.equal(0);
- const expectedETHBalance = preETHBalance.add(depositWeiAmount).round(decimalPlaces);
- gasCost = expectedETHBalance.minus(postETHBalance);
- expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI);
- });
- it('should throw if user has insufficient WETH balance for withdrawl', async () => {
- const preWETHBalance = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH);
- expect(preWETHBalance).to.be.bignumber.equal(0);
-
- const overWETHBalance = preWETHBalance.add(999999999);
-
- return expect(
- zeroEx.etherToken.withdrawAsync(overWETHBalance, addressWithETH),
- ).to.be.rejectedWith(ZeroExError.InsufficientWEthBalanceForWithdrawal);
- });
- });
-});
diff --git a/test/event_watcher_test.ts b/test/event_watcher_test.ts
deleted file mode 100644
index b4164fe63..000000000
--- a/test/event_watcher_test.ts
+++ /dev/null
@@ -1,127 +0,0 @@
-import 'mocha';
-import * as chai from 'chai';
-import * as _ from 'lodash';
-import * as Sinon from 'sinon';
-import * as Web3 from 'web3';
-import BigNumber from 'bignumber.js';
-import {chaiSetup} from './utils/chai_setup';
-import {web3Factory} from './utils/web3_factory';
-import {Web3Wrapper} from '../src/web3_wrapper';
-import {EventWatcher} from '../src/order_watcher/event_watcher';
-import {
- ZeroEx,
- LogEvent,
- DecodedLogEvent,
-} from '../src';
-import {DoneCallback} from '../src/types';
-
-chaiSetup.configure();
-const expect = chai.expect;
-
-describe('EventWatcher', () => {
- let web3: Web3;
- let stubs: Sinon.SinonStub[] = [];
- let eventWatcher: EventWatcher;
- let web3Wrapper: Web3Wrapper;
- const numConfirmations = 0;
- const logA: Web3.LogEntry = {
- address: '0x71d271f8b14adef568f8f28f1587ce7271ac4ca5',
- blockHash: null,
- blockNumber: null,
- data: '',
- logIndex: null,
- topics: [],
- transactionHash: '0x004881d38cd4a8f72f1a0d68c8b9b8124504706041ff37019c1d1ed6bfda8e17',
- transactionIndex: 0,
- };
- const logB: Web3.LogEntry = {
- address: '0x8d12a197cb00d4747a1fe03395095ce2a5cc6819',
- blockHash: null,
- blockNumber: null,
- data: '',
- logIndex: null,
- topics: [ '0xf341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567' ],
- transactionHash: '0x01ef3c048b18d9b09ea195b4ed94cf8dd5f3d857a1905ff886b152cfb1166f25',
- transactionIndex: 0,
- };
- const logC: Web3.LogEntry = {
- address: '0x1d271f8b174adef58f1587ce68f8f27271ac4ca5',
- blockHash: null,
- blockNumber: null,
- data: '',
- logIndex: null,
- topics: [ '0xf341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567' ],
- transactionHash: '0x01ef3c048b18d9b09ea195b4ed94cf8dd5f3d857a1905ff886b152cfb1166f25',
- transactionIndex: 0,
- };
- before(async () => {
- web3 = web3Factory.create();
- const pollingIntervalMs = 10;
- web3Wrapper = new Web3Wrapper(web3.currentProvider);
- eventWatcher = new EventWatcher(web3Wrapper, pollingIntervalMs);
- });
- afterEach(() => {
- // clean up any stubs after the test has completed
- _.each(stubs, s => s.restore());
- stubs = [];
- eventWatcher.unsubscribe();
- });
- it('correctly emits initial log events', (done: DoneCallback) => {
- const logs: Web3.LogEntry[] = [logA, logB];
- const expectedLogEvents = [
- {
- removed: false,
- ...logA,
- },
- {
- removed: false,
- ...logB,
- },
- ];
- const getLogsStub = Sinon.stub(web3Wrapper, 'getLogsAsync');
- getLogsStub.onCall(0).returns(logs);
- stubs.push(getLogsStub);
- const callback = (event: LogEvent) => {
- const expectedLogEvent = expectedLogEvents.shift();
- expect(event).to.be.deep.equal(expectedLogEvent);
- if (_.isEmpty(expectedLogEvents)) {
- done();
- }
- };
- eventWatcher.subscribe(callback);
- });
- it('correctly computes the difference and emits only changes', (done: DoneCallback) => {
- const initialLogs: Web3.LogEntry[] = [logA, logB];
- const changedLogs: Web3.LogEntry[] = [logA, logC];
- const expectedLogEvents = [
- {
- removed: false,
- ...logA,
- },
- {
- removed: false,
- ...logB,
- },
- {
- removed: true,
- ...logB,
- },
- {
- removed: false,
- ...logC,
- },
- ];
- const getLogsStub = Sinon.stub(web3Wrapper, 'getLogsAsync');
- getLogsStub.onCall(0).returns(initialLogs);
- getLogsStub.onCall(1).returns(changedLogs);
- stubs.push(getLogsStub);
- const callback = (event: LogEvent) => {
- const expectedLogEvent = expectedLogEvents.shift();
- expect(event).to.be.deep.equal(expectedLogEvent);
- if (_.isEmpty(expectedLogEvents)) {
- done();
- }
- };
- eventWatcher.subscribe(callback);
- });
-});
diff --git a/test/exchange_transfer_simulator_test.ts b/test/exchange_transfer_simulator_test.ts
deleted file mode 100644
index 99cb7fb4f..000000000
--- a/test/exchange_transfer_simulator_test.ts
+++ /dev/null
@@ -1,87 +0,0 @@
-import * as chai from 'chai';
-import BigNumber from 'bignumber.js';
-import {chaiSetup} from './utils/chai_setup';
-import {web3Factory} from './utils/web3_factory';
-import {ZeroEx, ExchangeContractErrs, Token} from '../src';
-import {TradeSide, TransferType} from '../src/types';
-import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
-import {ExchangeTransferSimulator} from '../src/utils/exchange_transfer_simulator';
-
-chaiSetup.configure();
-const expect = chai.expect;
-const blockchainLifecycle = new BlockchainLifecycle();
-
-describe('ExchangeTransferSimulator', () => {
- const web3 = web3Factory.create();
- const zeroEx = new ZeroEx(web3.currentProvider);
- const transferAmount = new BigNumber(5);
- let userAddresses: string[];
- let tokens: Token[];
- let coinbase: string;
- let sender: string;
- let recipient: string;
- let exampleTokenAddress: string;
- let exchangeTransferSimulator: ExchangeTransferSimulator;
- let txHash: string;
- before(async () => {
- userAddresses = await zeroEx.getAvailableAddressesAsync();
- [coinbase, sender, recipient] = userAddresses;
- tokens = await zeroEx.tokenRegistry.getTokensAsync();
- exampleTokenAddress = tokens[0].address;
- });
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
- describe('#transferFromAsync', () => {
- beforeEach(() => {
- exchangeTransferSimulator = new ExchangeTransferSimulator(zeroEx.token);
- });
- it('throws if the user doesn\'t have enough allowance', async () => {
- return expect(exchangeTransferSimulator.transferFromAsync(
- exampleTokenAddress, sender, recipient, transferAmount, TradeSide.Taker, TransferType.Trade,
- )).to.be.rejectedWith(ExchangeContractErrs.InsufficientTakerAllowance);
- });
- it('throws if the user doesn\'t have enough balance', async () => {
- txHash = await zeroEx.token.setProxyAllowanceAsync(exampleTokenAddress, sender, transferAmount);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- return expect(exchangeTransferSimulator.transferFromAsync(
- exampleTokenAddress, sender, recipient, transferAmount, TradeSide.Maker, TransferType.Trade,
- )).to.be.rejectedWith(ExchangeContractErrs.InsufficientMakerBalance);
- });
- it('updates balances and proxyAllowance after transfer', async () => {
- txHash = await zeroEx.token.transferAsync(exampleTokenAddress, coinbase, sender, transferAmount);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- txHash = await zeroEx.token.setProxyAllowanceAsync(exampleTokenAddress, sender, transferAmount);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- await exchangeTransferSimulator.transferFromAsync(
- exampleTokenAddress, sender, recipient, transferAmount, TradeSide.Taker, TransferType.Trade,
- );
- const store = (exchangeTransferSimulator as any).store;
- const senderBalance = await store.getBalanceAsync(exampleTokenAddress, sender);
- const recipientBalance = await store.getBalanceAsync(exampleTokenAddress, recipient);
- const senderProxyAllowance = await store.getProxyAllowanceAsync(exampleTokenAddress, sender);
- expect(senderBalance).to.be.bignumber.equal(0);
- expect(recipientBalance).to.be.bignumber.equal(transferAmount);
- expect(senderProxyAllowance).to.be.bignumber.equal(0);
- });
- it('doesn\'t update proxyAllowance after transfer if unlimited', async () => {
- txHash = await zeroEx.token.transferAsync(exampleTokenAddress, coinbase, sender, transferAmount);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(exampleTokenAddress, sender);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- await exchangeTransferSimulator.transferFromAsync(
- exampleTokenAddress, sender, recipient, transferAmount, TradeSide.Taker, TransferType.Trade,
- );
- const store = (exchangeTransferSimulator as any).store;
- const senderBalance = await store.getBalanceAsync(exampleTokenAddress, sender);
- const recipientBalance = await store.getBalanceAsync(exampleTokenAddress, recipient);
- const senderProxyAllowance = await store.getProxyAllowanceAsync(exampleTokenAddress, sender);
- expect(senderBalance).to.be.bignumber.equal(0);
- expect(recipientBalance).to.be.bignumber.equal(transferAmount);
- expect(senderProxyAllowance).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
- });
- });
-});
diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts
deleted file mode 100644
index 26b8c1e0e..000000000
--- a/test/exchange_wrapper_test.ts
+++ /dev/null
@@ -1,824 +0,0 @@
-import 'mocha';
-import * as chai from 'chai';
-import * as Web3 from 'web3';
-import BigNumber from 'bignumber.js';
-import {chaiSetup} from './utils/chai_setup';
-import {web3Factory} from './utils/web3_factory';
-import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
-import {
- ZeroEx,
- Token,
- SignedOrder,
- SubscriptionOpts,
- ExchangeEvents,
- ExchangeContractErrs,
- OrderCancellationRequest,
- OrderFillRequest,
- LogFillContractEventArgs,
- LogCancelContractEventArgs,
- LogEvent,
- DecodedLogEvent,
-} from '../src';
-import {DoneCallback, BlockParamLiteral} from '../src/types';
-import {FillScenarios} from './utils/fill_scenarios';
-import {TokenUtils} from './utils/token_utils';
-
-chaiSetup.configure();
-const expect = chai.expect;
-const blockchainLifecycle = new BlockchainLifecycle();
-
-const NON_EXISTENT_ORDER_HASH = '0x79370342234e7acd6bbeac335bd3bb1d368383294b64b8160a00f4060e4d3777';
-
-describe('ExchangeWrapper', () => {
- let web3: Web3;
- let zeroEx: ZeroEx;
- let tokenUtils: TokenUtils;
- let tokens: Token[];
- let userAddresses: string[];
- let zrxTokenAddress: string;
- let fillScenarios: FillScenarios;
- let exchangeContractAddress: string;
- before(async () => {
- web3 = web3Factory.create();
- zeroEx = new ZeroEx(web3.currentProvider);
- exchangeContractAddress = await zeroEx.exchange.getContractAddressAsync();
- userAddresses = await zeroEx.getAvailableAddressesAsync();
- tokens = await zeroEx.tokenRegistry.getTokensAsync();
- tokenUtils = new TokenUtils(tokens);
- zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address;
- fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress);
- });
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
- describe('fillOrKill order(s)', () => {
- let makerTokenAddress: string;
- let takerTokenAddress: string;
- let coinbase: string;
- let makerAddress: string;
- let takerAddress: string;
- let feeRecipient: string;
- const takerTokenFillAmount = new BigNumber(5);
- before(async () => {
- [coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses;
- tokens = await zeroEx.tokenRegistry.getTokensAsync();
- const [makerToken, takerToken] = tokenUtils.getNonProtocolTokens();
- makerTokenAddress = makerToken.address;
- takerTokenAddress = takerToken.address;
- });
- describe('#batchFillOrKillAsync', () => {
- it('successfully batch fillOrKill', async () => {
- const fillableAmount = new BigNumber(5);
- const partialFillTakerAmount = new BigNumber(2);
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- const anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- const orderFillRequests = [
- {
- signedOrder,
- takerTokenFillAmount: partialFillTakerAmount,
- },
- {
- signedOrder: anotherSignedOrder,
- takerTokenFillAmount: partialFillTakerAmount,
- },
- ];
- await zeroEx.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress);
- });
- describe('order transaction options', () => {
- let signedOrder: SignedOrder;
- let orderFillRequests: OrderFillRequest[];
- const fillableAmount = new BigNumber(5);
- beforeEach(async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- orderFillRequests = [
- {
- signedOrder,
- takerTokenFillAmount: new BigNumber(0),
- },
- ];
- });
- it('should validate when orderTransactionOptions are not present', async () => {
- return expect(zeroEx.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress))
- .to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- it('should validate when orderTransactionOptions specify to validate', async () => {
- return expect(zeroEx.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress, {
- shouldValidate: true,
- })).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- it('should not validate when orderTransactionOptions specify not to validate', async () => {
- return expect(zeroEx.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress, {
- shouldValidate: false,
- })).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- });
- });
- describe('#fillOrKillOrderAsync', () => {
- let signedOrder: SignedOrder;
- const fillableAmount = new BigNumber(5);
- beforeEach(async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- });
- describe('successful fills', () => {
- it('should fill a valid order', async () => {
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress))
- .to.be.bignumber.equal(fillableAmount);
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress))
- .to.be.bignumber.equal(0);
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress))
- .to.be.bignumber.equal(0);
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress))
- .to.be.bignumber.equal(fillableAmount);
- await zeroEx.exchange.fillOrKillOrderAsync(signedOrder, takerTokenFillAmount, takerAddress);
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress))
- .to.be.bignumber.equal(fillableAmount.minus(takerTokenFillAmount));
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress))
- .to.be.bignumber.equal(takerTokenFillAmount);
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress))
- .to.be.bignumber.equal(takerTokenFillAmount);
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress))
- .to.be.bignumber.equal(fillableAmount.minus(takerTokenFillAmount));
- });
- it('should partially fill a valid order', async () => {
- const partialFillAmount = new BigNumber(3);
- await zeroEx.exchange.fillOrKillOrderAsync(signedOrder, partialFillAmount, takerAddress);
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress))
- .to.be.bignumber.equal(fillableAmount.minus(partialFillAmount));
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress))
- .to.be.bignumber.equal(partialFillAmount);
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress))
- .to.be.bignumber.equal(partialFillAmount);
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress))
- .to.be.bignumber.equal(fillableAmount.minus(partialFillAmount));
- });
- });
- describe('order transaction options', () => {
- const emptyFillableAmount = new BigNumber(0);
- it('should validate when orderTransactionOptions are not present', async () => {
- return expect(zeroEx.exchange.fillOrKillOrderAsync(signedOrder, emptyFillableAmount, takerAddress))
- .to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- it('should validate when orderTransactionOptions specify to validate', async () => {
- return expect(zeroEx.exchange.fillOrKillOrderAsync(signedOrder, emptyFillableAmount, takerAddress, {
- shouldValidate: true,
- })).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- it('should not validate when orderTransactionOptions specify not to validate', async () => {
- return expect(zeroEx.exchange.fillOrKillOrderAsync(signedOrder, emptyFillableAmount, takerAddress, {
- shouldValidate: false,
- })).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- });
- });
- });
- describe('fill order(s)', () => {
- let makerTokenAddress: string;
- let takerTokenAddress: string;
- let coinbase: string;
- let makerAddress: string;
- let takerAddress: string;
- let feeRecipient: string;
- const fillableAmount = new BigNumber(5);
- const takerTokenFillAmount = new BigNumber(5);
- const shouldThrowOnInsufficientBalanceOrAllowance = true;
- before(async () => {
- [coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses;
- tokens = await zeroEx.tokenRegistry.getTokensAsync();
- const [makerToken, takerToken] = tokenUtils.getNonProtocolTokens();
- makerTokenAddress = makerToken.address;
- takerTokenAddress = takerToken.address;
- });
- describe('#fillOrderAsync', () => {
- describe('successful fills', () => {
- it('should fill a valid order', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress))
- .to.be.bignumber.equal(fillableAmount);
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress))
- .to.be.bignumber.equal(0);
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress))
- .to.be.bignumber.equal(0);
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress))
- .to.be.bignumber.equal(fillableAmount);
- const txHash = await zeroEx.exchange.fillOrderAsync(
- signedOrder, takerTokenFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress))
- .to.be.bignumber.equal(fillableAmount.minus(takerTokenFillAmount));
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress))
- .to.be.bignumber.equal(takerTokenFillAmount);
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress))
- .to.be.bignumber.equal(takerTokenFillAmount);
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress))
- .to.be.bignumber.equal(fillableAmount.minus(takerTokenFillAmount));
- });
- it('should partially fill the valid order', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- const partialFillAmount = new BigNumber(3);
- const txHash = await zeroEx.exchange.fillOrderAsync(
- signedOrder, partialFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress))
- .to.be.bignumber.equal(fillableAmount.minus(partialFillAmount));
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress))
- .to.be.bignumber.equal(partialFillAmount);
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress))
- .to.be.bignumber.equal(partialFillAmount);
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress))
- .to.be.bignumber.equal(fillableAmount.minus(partialFillAmount));
- });
- it('should fill the valid orders with fees', async () => {
- const makerFee = new BigNumber(1);
- const takerFee = new BigNumber(2);
- const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
- makerTokenAddress, takerTokenAddress, makerFee, takerFee,
- makerAddress, takerAddress, fillableAmount, feeRecipient,
- );
- const txHash = await zeroEx.exchange.fillOrderAsync(
- signedOrder, takerTokenFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- expect(await zeroEx.token.getBalanceAsync(zrxTokenAddress, feeRecipient))
- .to.be.bignumber.equal(makerFee.plus(takerFee));
- });
- });
- describe('order transaction options', () => {
- let signedOrder: SignedOrder;
- const emptyFillTakerAmount = new BigNumber(0);
- beforeEach(async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- });
- it('should validate when orderTransactionOptions are not present', async () => {
- return expect(zeroEx.exchange.fillOrderAsync(
- signedOrder, emptyFillTakerAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
- )).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- it('should validate when orderTransactionOptions specify to validate', async () => {
- return expect(zeroEx.exchange.fillOrderAsync(
- signedOrder, emptyFillTakerAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, {
- shouldValidate: true,
- })).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- it('should not validate when orderTransactionOptions specify not to validate', async () => {
- return expect(zeroEx.exchange.fillOrderAsync(
- signedOrder, emptyFillTakerAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, {
- shouldValidate: false,
- })).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- });
- });
- describe('#batchFillOrdersAsync', () => {
- let signedOrder: SignedOrder;
- let signedOrderHashHex: string;
- let anotherSignedOrder: SignedOrder;
- let anotherOrderHashHex: string;
- let orderFillBatch: OrderFillRequest[];
- beforeEach(async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- signedOrderHashHex = ZeroEx.getOrderHashHex(signedOrder);
- anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- anotherOrderHashHex = ZeroEx.getOrderHashHex(anotherSignedOrder);
- });
- describe('successful batch fills', () => {
- beforeEach(() => {
- orderFillBatch = [
- {
- signedOrder,
- takerTokenFillAmount,
- },
- {
- signedOrder: anotherSignedOrder,
- takerTokenFillAmount,
- },
- ];
- });
- it('should throw if a batch is empty', async () => {
- return expect(zeroEx.exchange.batchFillOrdersAsync(
- [], shouldThrowOnInsufficientBalanceOrAllowance, takerAddress),
- ).to.be.rejectedWith(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
- });
- it('should successfully fill multiple orders', async () => {
- const txHash = await zeroEx.exchange.batchFillOrdersAsync(
- orderFillBatch, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(signedOrderHashHex);
- const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(anotherOrderHashHex);
- expect(filledAmount).to.be.bignumber.equal(takerTokenFillAmount);
- expect(anotherFilledAmount).to.be.bignumber.equal(takerTokenFillAmount);
- });
- });
- describe('order transaction options', () => {
- beforeEach(async () => {
- const emptyFillTakerAmount = new BigNumber(0);
- orderFillBatch = [
- {
- signedOrder,
- takerTokenFillAmount: emptyFillTakerAmount,
- },
- {
- signedOrder: anotherSignedOrder,
- takerTokenFillAmount: emptyFillTakerAmount,
- },
- ];
- });
- it('should validate when orderTransactionOptions are not present', async () => {
- return expect(zeroEx.exchange.batchFillOrdersAsync(
- orderFillBatch, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress),
- ).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- it('should validate when orderTransactionOptions specify to validate', async () => {
- return expect(zeroEx.exchange.batchFillOrdersAsync(
- orderFillBatch, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, {
- shouldValidate: true,
- })).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- it('should not validate when orderTransactionOptions specify not to validate', async () => {
- return expect(zeroEx.exchange.batchFillOrdersAsync(
- orderFillBatch, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, {
- shouldValidate: false,
- })).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- });
- });
- describe('#fillOrdersUpTo', () => {
- let signedOrder: SignedOrder;
- let signedOrderHashHex: string;
- let anotherSignedOrder: SignedOrder;
- let anotherOrderHashHex: string;
- let signedOrders: SignedOrder[];
- const fillUpToAmount = fillableAmount.plus(fillableAmount).minus(1);
- beforeEach(async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- signedOrderHashHex = ZeroEx.getOrderHashHex(signedOrder);
- anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- anotherOrderHashHex = ZeroEx.getOrderHashHex(anotherSignedOrder);
- signedOrders = [signedOrder, anotherSignedOrder];
- });
- describe('successful batch fills', () => {
- it('should throw if a batch is empty', async () => {
- return expect(zeroEx.exchange.fillOrdersUpToAsync(
- [], fillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress),
- ).to.be.rejectedWith(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
- });
- it('should successfully fill up to specified amount', async () => {
- const txHash = await zeroEx.exchange.fillOrdersUpToAsync(
- signedOrders, fillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
- );
- await zeroEx.awaitTransactionMinedAsync(txHash);
- const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(signedOrderHashHex);
- const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(anotherOrderHashHex);
- expect(filledAmount).to.be.bignumber.equal(fillableAmount);
- const remainingFillAmount = fillableAmount.minus(1);
- expect(anotherFilledAmount).to.be.bignumber.equal(remainingFillAmount);
- });
- });
- describe('order transaction options', () => {
- const emptyFillUpToAmount = new BigNumber(0);
- it('should validate when orderTransactionOptions are not present', async () => {
- return expect(zeroEx.exchange.fillOrdersUpToAsync(
- signedOrders, emptyFillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
- )).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- it('should validate when orderTransactionOptions specify to validate', async () => {
- return expect(zeroEx.exchange.fillOrdersUpToAsync(
- signedOrders, emptyFillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, {
- shouldValidate: true,
- })).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- it('should not validate when orderTransactionOptions specify not to validate', async () => {
- return expect(zeroEx.exchange.fillOrdersUpToAsync(
- signedOrders, emptyFillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, {
- shouldValidate: false,
- })).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- });
- });
- });
- describe('cancel order(s)', () => {
- let makerTokenAddress: string;
- let takerTokenAddress: string;
- let coinbase: string;
- let makerAddress: string;
- let takerAddress: string;
- const fillableAmount = new BigNumber(5);
- let signedOrder: SignedOrder;
- let orderHashHex: string;
- const cancelAmount = new BigNumber(3);
- beforeEach(async () => {
- [coinbase, makerAddress, takerAddress] = userAddresses;
- const [makerToken, takerToken] = tokenUtils.getNonProtocolTokens();
- makerTokenAddress = makerToken.address;
- takerTokenAddress = takerToken.address;
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- orderHashHex = ZeroEx.getOrderHashHex(signedOrder);
- });
- describe('#cancelOrderAsync', () => {
- describe('successful cancels', () => {
- it('should cancel an order', async () => {
- const txHash = await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelAmount);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- const cancelledAmount = await zeroEx.exchange.getCanceledTakerAmountAsync(orderHashHex);
- expect(cancelledAmount).to.be.bignumber.equal(cancelAmount);
- });
- });
- describe('order transaction options', () => {
- const emptyCancelTakerTokenAmount = new BigNumber(0);
- it('should validate when orderTransactionOptions are not present', async () => {
- return expect(zeroEx.exchange.cancelOrderAsync(signedOrder, emptyCancelTakerTokenAmount))
- .to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
- });
- it('should validate when orderTransactionOptions specify to validate', async () => {
- return expect(zeroEx.exchange.cancelOrderAsync(signedOrder, emptyCancelTakerTokenAmount, {
- shouldValidate: true,
- })).to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
- });
- it('should not validate when orderTransactionOptions specify not to validate', async () => {
- return expect(zeroEx.exchange.cancelOrderAsync(signedOrder, emptyCancelTakerTokenAmount, {
- shouldValidate: false,
- })).to.not.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
- });
- });
- });
- describe('#batchCancelOrdersAsync', () => {
- let anotherSignedOrder: SignedOrder;
- let anotherOrderHashHex: string;
- let cancelBatch: OrderCancellationRequest[];
- beforeEach(async () => {
- anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- anotherOrderHashHex = ZeroEx.getOrderHashHex(anotherSignedOrder);
- cancelBatch = [
- {
- order: signedOrder,
- takerTokenCancelAmount: cancelAmount,
- },
- {
- order: anotherSignedOrder,
- takerTokenCancelAmount: cancelAmount,
- },
- ];
- });
- describe('failed batch cancels', () => {
- it('should throw when orders have different makers', async () => {
- const signedOrderWithDifferentMaker = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, takerAddress, takerAddress, fillableAmount,
- );
- return expect(zeroEx.exchange.batchCancelOrdersAsync([
- cancelBatch[0],
- {
- order: signedOrderWithDifferentMaker,
- takerTokenCancelAmount: cancelAmount,
- },
- ])).to.be.rejectedWith(ExchangeContractErrs.MultipleMakersInSingleCancelBatchDisallowed);
- });
- });
- describe('successful batch cancels', () => {
- it('should cancel a batch of orders', async () => {
- await zeroEx.exchange.batchCancelOrdersAsync(cancelBatch);
- const cancelledAmount = await zeroEx.exchange.getCanceledTakerAmountAsync(orderHashHex);
- const anotherCancelledAmount = await zeroEx.exchange.getCanceledTakerAmountAsync(
- anotherOrderHashHex,
- );
- expect(cancelledAmount).to.be.bignumber.equal(cancelAmount);
- expect(anotherCancelledAmount).to.be.bignumber.equal(cancelAmount);
- });
- });
- describe('order transaction options', () => {
- beforeEach(async () => {
- const emptyTakerTokenCancelAmount = new BigNumber(0);
- cancelBatch = [
- {
- order: signedOrder,
- takerTokenCancelAmount: emptyTakerTokenCancelAmount,
- },
- {
- order: anotherSignedOrder,
- takerTokenCancelAmount: emptyTakerTokenCancelAmount,
- },
- ];
- });
- it('should validate when orderTransactionOptions are not present', async () => {
- return expect(zeroEx.exchange.batchCancelOrdersAsync(cancelBatch))
- .to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
- });
- it('should validate when orderTransactionOptions specify to validate', async () => {
- return expect(zeroEx.exchange.batchCancelOrdersAsync(cancelBatch, {
- shouldValidate: true,
- })).to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
- });
- it('should not validate when orderTransactionOptions specify not to validate', async () => {
- return expect(zeroEx.exchange.batchCancelOrdersAsync(cancelBatch, {
- shouldValidate: false,
- })).to.not.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
- });
- });
- });
- });
- describe('tests that require partially filled order', () => {
- let makerTokenAddress: string;
- let takerTokenAddress: string;
- let takerAddress: string;
- let fillableAmount: BigNumber;
- let partialFillAmount: BigNumber;
- let signedOrder: SignedOrder;
- let orderHash: string;
- before(() => {
- takerAddress = userAddresses[1];
- const [makerToken, takerToken] = tokens;
- makerTokenAddress = makerToken.address;
- takerTokenAddress = takerToken.address;
- });
- beforeEach(async () => {
- fillableAmount = new BigNumber(5);
- partialFillAmount = new BigNumber(2);
- signedOrder = await fillScenarios.createPartiallyFilledSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, takerAddress, fillableAmount, partialFillAmount,
- );
- orderHash = ZeroEx.getOrderHashHex(signedOrder);
- });
- describe('#getUnavailableTakerAmountAsync', () => {
- it('should throw if passed an invalid orderHash', async () => {
- const invalidOrderHashHex = '0x123';
- return expect(zeroEx.exchange.getUnavailableTakerAmountAsync(invalidOrderHashHex)).to.be.rejected();
- });
- it('should return zero if passed a valid but non-existent orderHash', async () => {
- const unavailableValueT = await zeroEx.exchange.getUnavailableTakerAmountAsync(NON_EXISTENT_ORDER_HASH);
- expect(unavailableValueT).to.be.bignumber.equal(0);
- });
- it('should return the unavailableValueT for a valid and partially filled orderHash', async () => {
- const unavailableValueT = await zeroEx.exchange.getUnavailableTakerAmountAsync(orderHash);
- expect(unavailableValueT).to.be.bignumber.equal(partialFillAmount);
- });
- });
- describe('#getFilledTakerAmountAsync', () => {
- it('should throw if passed an invalid orderHash', async () => {
- const invalidOrderHashHex = '0x123';
- return expect(zeroEx.exchange.getFilledTakerAmountAsync(invalidOrderHashHex)).to.be.rejected();
- });
- it('should return zero if passed a valid but non-existent orderHash', async () => {
- const filledValueT = await zeroEx.exchange.getFilledTakerAmountAsync(NON_EXISTENT_ORDER_HASH,
- );
- expect(filledValueT).to.be.bignumber.equal(0);
- });
- it('should return the filledValueT for a valid and partially filled orderHash', async () => {
- const filledValueT = await zeroEx.exchange.getFilledTakerAmountAsync(orderHash);
- expect(filledValueT).to.be.bignumber.equal(partialFillAmount);
- });
- });
- describe('#getCanceledTakerAmountAsync', () => {
- it('should throw if passed an invalid orderHash', async () => {
- const invalidOrderHashHex = '0x123';
- return expect(zeroEx.exchange.getCanceledTakerAmountAsync(invalidOrderHashHex)).to.be.rejected();
- });
- it('should return zero if passed a valid but non-existent orderHash', async () => {
- const cancelledValueT = await zeroEx.exchange.getCanceledTakerAmountAsync(NON_EXISTENT_ORDER_HASH);
- expect(cancelledValueT).to.be.bignumber.equal(0);
- });
- it('should return the cancelledValueT for a valid and partially filled orderHash', async () => {
- const cancelledValueT = await zeroEx.exchange.getCanceledTakerAmountAsync(orderHash);
- expect(cancelledValueT).to.be.bignumber.equal(0);
- });
- it('should return the cancelledValueT for a valid and cancelled orderHash', async () => {
- const cancelAmount = fillableAmount.minus(partialFillAmount);
- await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelAmount);
- const cancelledValueT = await zeroEx.exchange.getCanceledTakerAmountAsync(orderHash);
- expect(cancelledValueT).to.be.bignumber.equal(cancelAmount);
- });
- });
- });
- describe('#subscribeAsync', () => {
- const indexFilterValues = {};
- const shouldThrowOnInsufficientBalanceOrAllowance = true;
- let makerTokenAddress: string;
- let takerTokenAddress: string;
- let coinbase: string;
- let takerAddress: string;
- let makerAddress: string;
- let fillableAmount: BigNumber;
- let signedOrder: SignedOrder;
- const takerTokenFillAmountInBaseUnits = new BigNumber(1);
- const cancelTakerAmountInBaseUnits = new BigNumber(1);
- before(() => {
- [coinbase, makerAddress, takerAddress] = userAddresses;
- const [makerToken, takerToken] = tokens;
- makerTokenAddress = makerToken.address;
- takerTokenAddress = takerToken.address;
- });
- beforeEach(async () => {
- fillableAmount = new BigNumber(5);
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- });
- afterEach(async () => {
- zeroEx.exchange.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 LogFill event when an order is filled', (done: DoneCallback) => {
- (async () => {
-
- const callback = (err: Error, logEvent: DecodedLogEvent<LogFillContractEventArgs>) => {
- expect(logEvent.event).to.be.equal(ExchangeEvents.LogFill);
- done();
- };
- await zeroEx.exchange.subscribeAsync(
- ExchangeEvents.LogFill, indexFilterValues, callback,
- );
- await zeroEx.exchange.fillOrderAsync(
- signedOrder, takerTokenFillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- );
- })().catch(done);
- });
- it('Should receive the LogCancel event when an order is cancelled', (done: DoneCallback) => {
- (async () => {
-
- const callback = (err: Error, logEvent: DecodedLogEvent<LogCancelContractEventArgs>) => {
- expect(logEvent.event).to.be.equal(ExchangeEvents.LogCancel);
- done();
- };
- await zeroEx.exchange.subscribeAsync(
- ExchangeEvents.LogCancel, indexFilterValues, callback,
- );
- await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelTakerAmountInBaseUnits);
- })().catch(done);
- });
- it('Outstanding subscriptions are cancelled when zeroEx.setProviderAsync called', (done: DoneCallback) => {
- (async () => {
-
- const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent<LogFillContractEventArgs>) => {
- done(new Error('Expected this subscription to have been cancelled'));
- };
- await zeroEx.exchange.subscribeAsync(
- ExchangeEvents.LogFill, indexFilterValues, callbackNeverToBeCalled,
- );
-
- const newProvider = web3Factory.getRpcProvider();
- await zeroEx.setProviderAsync(newProvider);
-
- const callback = (err: Error, logEvent: DecodedLogEvent<LogFillContractEventArgs>) => {
- expect(logEvent.event).to.be.equal(ExchangeEvents.LogFill);
- done();
- };
- await zeroEx.exchange.subscribeAsync(
- ExchangeEvents.LogFill, indexFilterValues, callback,
- );
- await zeroEx.exchange.fillOrderAsync(
- signedOrder, takerTokenFillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- );
- })().catch(done);
- });
- it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => {
- (async () => {
- const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent<LogFillContractEventArgs>) => {
- done(new Error('Expected this subscription to have been cancelled'));
- };
- const subscriptionToken = await zeroEx.exchange.subscribeAsync(
- ExchangeEvents.LogFill, indexFilterValues, callbackNeverToBeCalled,
- );
- zeroEx.exchange.unsubscribe(subscriptionToken);
- await zeroEx.exchange.fillOrderAsync(
- signedOrder, takerTokenFillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- );
- done();
- })().catch(done);
- });
- });
- describe('#getOrderHashHexUsingContractCallAsync', () => {
- let makerTokenAddress: string;
- let takerTokenAddress: string;
- let makerAddress: string;
- let takerAddress: string;
- const fillableAmount = new BigNumber(5);
- before(async () => {
- [, makerAddress, takerAddress] = userAddresses;
- const [makerToken, takerToken] = tokenUtils.getNonProtocolTokens();
- makerTokenAddress = makerToken.address;
- takerTokenAddress = takerToken.address;
- });
- it('get\'s the same hash as the local function', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- const orderHashFromContract = await (zeroEx.exchange as any)
- ._getOrderHashHexUsingContractCallAsync(signedOrder);
- expect(orderHash).to.equal(orderHashFromContract);
- });
- });
- describe('#getZRXTokenAddressAsync', () => {
- it('gets the same token as is in token registry', async () => {
- const zrxAddress = await zeroEx.exchange.getZRXTokenAddressAsync();
- const zrxToken = tokenUtils.getProtocolTokenOrThrow();
- expect(zrxAddress).to.equal(zrxToken.address);
- });
- });
- describe('#getLogsAsync', () => {
- let makerTokenAddress: string;
- let takerTokenAddress: string;
- let makerAddress: string;
- let takerAddress: string;
- const fillableAmount = new BigNumber(5);
- const shouldThrowOnInsufficientBalanceOrAllowance = true;
- const subscriptionOpts: SubscriptionOpts = {
- fromBlock: BlockParamLiteral.Earliest,
- toBlock: BlockParamLiteral.Latest,
- };
- let txHash: string;
- before(async () => {
- [, makerAddress, takerAddress] = userAddresses;
- const [makerToken, takerToken] = tokenUtils.getNonProtocolTokens();
- makerTokenAddress = makerToken.address;
- takerTokenAddress = takerToken.address;
- });
- it('should get logs with decoded args emitted by LogFill', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- txHash = await zeroEx.exchange.fillOrderAsync(
- signedOrder, fillableAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
- );
- await zeroEx.awaitTransactionMinedAsync(txHash);
- const eventName = ExchangeEvents.LogFill;
- const indexFilterValues = {};
- const logs = await zeroEx.exchange.getLogsAsync(eventName, subscriptionOpts, indexFilterValues);
- expect(logs).to.have.length(1);
- expect(logs[0].event).to.be.equal(eventName);
- });
- it('should only get the logs with the correct event name', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- txHash = await zeroEx.exchange.fillOrderAsync(
- signedOrder, fillableAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
- );
- await zeroEx.awaitTransactionMinedAsync(txHash);
- const differentEventName = ExchangeEvents.LogCancel;
- const indexFilterValues = {};
- const logs = await zeroEx.exchange.getLogsAsync(differentEventName, subscriptionOpts, indexFilterValues);
- expect(logs).to.have.length(0);
- });
- it('should only get the logs with the correct indexed fields', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- txHash = await zeroEx.exchange.fillOrderAsync(
- signedOrder, fillableAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
- );
- await zeroEx.awaitTransactionMinedAsync(txHash);
-
- const differentMakerAddress = userAddresses[2];
- const anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, differentMakerAddress, takerAddress, fillableAmount,
- );
- txHash = await zeroEx.exchange.fillOrderAsync(
- anotherSignedOrder, fillableAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
- );
- await zeroEx.awaitTransactionMinedAsync(txHash);
-
- const eventName = ExchangeEvents.LogFill;
- const indexFilterValues = {
- maker: differentMakerAddress,
- };
- const logs = await zeroEx.exchange.getLogsAsync<LogFillContractEventArgs>(
- eventName, subscriptionOpts, indexFilterValues,
- );
- expect(logs).to.have.length(1);
- const args = logs[0].args;
- expect(args.maker).to.be.equal(differentMakerAddress);
- });
- });
-});
diff --git a/test/order_state_watcher_test.ts b/test/order_state_watcher_test.ts
deleted file mode 100644
index c8a4a8064..000000000
--- a/test/order_state_watcher_test.ts
+++ /dev/null
@@ -1,356 +0,0 @@
-import 'mocha';
-import * as chai from 'chai';
-import * as _ from 'lodash';
-import * as Web3 from 'web3';
-import BigNumber from 'bignumber.js';
-import { chaiSetup } from './utils/chai_setup';
-import { web3Factory } from './utils/web3_factory';
-import { Web3Wrapper } from '../src/web3_wrapper';
-import { OrderStateWatcher } from '../src/order_watcher/order_state_watcher';
-import {
- Token,
- ZeroEx,
- LogEvent,
- DecodedLogEvent,
- ZeroExConfig,
- OrderState,
- SignedOrder,
- ZeroExError,
- OrderStateValid,
- OrderStateInvalid,
- ExchangeContractErrs,
-} from '../src';
-import { TokenUtils } from './utils/token_utils';
-import { FillScenarios } from './utils/fill_scenarios';
-import { DoneCallback } from '../src/types';
-import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
-import {reportCallbackErrors} from './utils/report_callback_errors';
-
-const TIMEOUT_MS = 150;
-
-chaiSetup.configure();
-const expect = chai.expect;
-const blockchainLifecycle = new BlockchainLifecycle();
-
-describe('OrderStateWatcher', () => {
- let web3: Web3;
- let zeroEx: ZeroEx;
- let tokens: Token[];
- let tokenUtils: TokenUtils;
- let fillScenarios: FillScenarios;
- let userAddresses: string[];
- let zrxTokenAddress: string;
- let exchangeContractAddress: string;
- let makerToken: Token;
- let takerToken: Token;
- let maker: string;
- let taker: string;
- let web3Wrapper: Web3Wrapper;
- let signedOrder: SignedOrder;
- const fillableAmount = new BigNumber(5);
- before(async () => {
- web3 = web3Factory.create();
- zeroEx = new ZeroEx(web3.currentProvider);
- exchangeContractAddress = await zeroEx.exchange.getContractAddressAsync();
- userAddresses = await zeroEx.getAvailableAddressesAsync();
- [, maker, taker] = userAddresses;
- tokens = await zeroEx.tokenRegistry.getTokensAsync();
- tokenUtils = new TokenUtils(tokens);
- zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address;
- fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress);
- [makerToken, takerToken] = tokenUtils.getNonProtocolTokens();
- web3Wrapper = (zeroEx as any)._web3Wrapper;
- });
- describe('#removeOrder', async () => {
- it('should successfully remove existing order', async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerToken.address, takerToken.address, maker, taker, fillableAmount,
- );
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- zeroEx.orderStateWatcher.addOrder(signedOrder);
- expect((zeroEx.orderStateWatcher as any)._orderByOrderHash).to.include({
- [orderHash]: signedOrder,
- });
- let dependentOrderHashes = (zeroEx.orderStateWatcher as any)._dependentOrderHashes;
- expect(dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress]).to.have.keys(orderHash);
- zeroEx.orderStateWatcher.removeOrder(orderHash);
- expect((zeroEx.orderStateWatcher as any)._orderByOrderHash).to.not.include({
- [orderHash]: signedOrder,
- });
- dependentOrderHashes = (zeroEx.orderStateWatcher as any)._dependentOrderHashes;
- expect(dependentOrderHashes[signedOrder.maker]).to.be.undefined();
- });
- it('should no-op when removing a non-existing order', async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerToken.address, takerToken.address, maker, taker, fillableAmount,
- );
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- const nonExistentOrderHash = `0x${orderHash.substr(2).split('').reverse().join('')}`;
- zeroEx.orderStateWatcher.removeOrder(nonExistentOrderHash);
- });
- });
- describe('#subscribe', async () => {
- afterEach(async () => {
- zeroEx.orderStateWatcher.unsubscribe();
- });
- it('should fail when trying to subscribe twice', async () => {
- zeroEx.orderStateWatcher.subscribe(_.noop);
- expect(() => zeroEx.orderStateWatcher.subscribe(_.noop))
- .to.throw(ZeroExError.SubscriptionAlreadyPresent);
- });
- });
- describe('tests with cleanup', async () => {
- afterEach(async () => {
- zeroEx.orderStateWatcher.unsubscribe();
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- zeroEx.orderStateWatcher.removeOrder(orderHash);
- });
- it('should emit orderStateInvalid when maker allowance set to 0 for watched order', (done: DoneCallback) => {
- (async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerToken.address, takerToken.address, maker, taker, fillableAmount,
- );
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- zeroEx.orderStateWatcher.addOrder(signedOrder);
- const callback = reportCallbackErrors(done)((orderState: OrderState) => {
- expect(orderState.isValid).to.be.false();
- const invalidOrderState = orderState as OrderStateInvalid;
- expect(invalidOrderState.orderHash).to.be.equal(orderHash);
- expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.InsufficientMakerAllowance);
- done();
- });
- zeroEx.orderStateWatcher.subscribe(callback);
- await zeroEx.token.setProxyAllowanceAsync(makerToken.address, maker, new BigNumber(0));
- })().catch(done);
- });
- it('should not emit an orderState event when irrelevant Transfer event received', (done: DoneCallback) => {
- (async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerToken.address, takerToken.address, maker, taker, fillableAmount,
- );
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- zeroEx.orderStateWatcher.addOrder(signedOrder);
- const callback = reportCallbackErrors(done)((orderState: OrderState) => {
- throw new Error('OrderState callback fired for irrelevant order');
- });
- zeroEx.orderStateWatcher.subscribe(callback);
- const notTheMaker = userAddresses[0];
- const anyRecipient = taker;
- const transferAmount = new BigNumber(2);
- const notTheMakerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, notTheMaker);
- await zeroEx.token.transferAsync(makerToken.address, notTheMaker, anyRecipient, transferAmount);
- setTimeout(() => {
- done();
- }, TIMEOUT_MS);
- })().catch(done);
- });
- it('should emit orderStateInvalid when maker moves balance backing watched order', (done: DoneCallback) => {
- (async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerToken.address, takerToken.address, maker, taker, fillableAmount,
- );
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- zeroEx.orderStateWatcher.addOrder(signedOrder);
- const callback = reportCallbackErrors(done)((orderState: OrderState) => {
- expect(orderState.isValid).to.be.false();
- const invalidOrderState = orderState as OrderStateInvalid;
- expect(invalidOrderState.orderHash).to.be.equal(orderHash);
- expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.InsufficientMakerBalance);
- done();
- });
- zeroEx.orderStateWatcher.subscribe(callback);
- const anyRecipient = taker;
- const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
- await zeroEx.token.transferAsync(makerToken.address, maker, anyRecipient, makerBalance);
- })().catch(done);
- });
- it('should emit orderStateInvalid when watched order fully filled', (done: DoneCallback) => {
- (async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerToken.address, takerToken.address, maker, taker, fillableAmount,
- );
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- zeroEx.orderStateWatcher.addOrder(signedOrder);
-
- let eventCount = 0;
- const callback = reportCallbackErrors(done)((orderState: OrderState) => {
- eventCount++;
- expect(orderState.isValid).to.be.false();
- const invalidOrderState = orderState as OrderStateInvalid;
- expect(invalidOrderState.orderHash).to.be.equal(orderHash);
- expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderRemainingFillAmountZero);
- if (eventCount === 2) {
- done();
- }
- });
- zeroEx.orderStateWatcher.subscribe(callback);
-
- const shouldThrowOnInsufficientBalanceOrAllowance = true;
- await zeroEx.exchange.fillOrderAsync(
- signedOrder, fillableAmount, shouldThrowOnInsufficientBalanceOrAllowance, taker,
- );
- })().catch(done);
- });
- it('should emit orderStateValid when watched order partially filled', (done: DoneCallback) => {
- (async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerToken.address, takerToken.address, maker, taker, fillableAmount,
- );
-
- const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
- const takerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, taker);
-
- const fillAmountInBaseUnits = new BigNumber(2);
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- zeroEx.orderStateWatcher.addOrder(signedOrder);
-
- let eventCount = 0;
- const callback = reportCallbackErrors(done)((orderState: OrderState) => {
- eventCount++;
- expect(orderState.isValid).to.be.true();
- const validOrderState = orderState as OrderStateValid;
- expect(validOrderState.orderHash).to.be.equal(orderHash);
- const orderRelevantState = validOrderState.orderRelevantState;
- const remainingMakerBalance = makerBalance.sub(fillAmountInBaseUnits);
- const remainingFillable = fillableAmount.minus(fillAmountInBaseUnits);
- expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
- remainingFillable);
- expect(orderRelevantState.makerBalance).to.be.bignumber.equal(remainingMakerBalance);
- if (eventCount === 2) {
- done();
- }
- });
- zeroEx.orderStateWatcher.subscribe(callback);
- const shouldThrowOnInsufficientBalanceOrAllowance = true;
- await zeroEx.exchange.fillOrderAsync(
- signedOrder, fillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance, taker,
- );
- })().catch(done);
- });
- describe('remainingFillableMakerTokenAmount', () => {
- it('should calculate correct remaining fillable', (done: DoneCallback) => {
- (async () => {
- const takerFillableAmount = new BigNumber(10);
- const makerFillableAmount = new BigNumber(20);
- signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
- makerToken.address, takerToken.address, maker, taker, makerFillableAmount, takerFillableAmount);
- const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
- const takerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, taker);
- const fillAmountInBaseUnits = new BigNumber(2);
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- zeroEx.orderStateWatcher.addOrder(signedOrder);
- let eventCount = 0;
- const callback = reportCallbackErrors(done)((orderState: OrderState) => {
- eventCount++;
- expect(orderState.isValid).to.be.true();
- const validOrderState = orderState as OrderStateValid;
- expect(validOrderState.orderHash).to.be.equal(orderHash);
- const orderRelevantState = validOrderState.orderRelevantState;
- expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
- new BigNumber(16));
- if (eventCount === 2) {
- done();
- }
- });
- zeroEx.orderStateWatcher.subscribe(callback);
- const shouldThrowOnInsufficientBalanceOrAllowance = true;
- await zeroEx.exchange.fillOrderAsync(
- signedOrder, fillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance, taker,
- );
- })().catch(done);
- });
- it('should equal approved amount when approved amount is lowest', (done: DoneCallback) => {
- (async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerToken.address, takerToken.address, maker, taker, fillableAmount,
- );
-
- const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
-
- const changedMakerApprovalAmount = new BigNumber(3);
- zeroEx.orderStateWatcher.addOrder(signedOrder);
-
- const callback = reportCallbackErrors(done)((orderState: OrderState) => {
- const validOrderState = orderState as OrderStateValid;
- const orderRelevantState = validOrderState.orderRelevantState;
- expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
- changedMakerApprovalAmount);
- done();
- });
- zeroEx.orderStateWatcher.subscribe(callback);
- await zeroEx.token.setProxyAllowanceAsync(makerToken.address, maker, changedMakerApprovalAmount);
- })().catch(done);
- });
- it('should equal balance amount when balance amount is lowest', (done: DoneCallback) => {
- (async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerToken.address, takerToken.address, maker, taker, fillableAmount,
- );
-
- const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
-
- const remainingAmount = new BigNumber(1);
- const transferAmount = makerBalance.sub(remainingAmount);
- zeroEx.orderStateWatcher.addOrder(signedOrder);
-
- const callback = reportCallbackErrors(done)((orderState: OrderState) => {
- const validOrderState = orderState as OrderStateValid;
- const orderRelevantState = validOrderState.orderRelevantState;
- expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
- remainingAmount);
- done();
- });
- zeroEx.orderStateWatcher.subscribe(callback);
- await zeroEx.token.transferAsync(
- makerToken.address, maker, ZeroEx.NULL_ADDRESS, transferAmount);
- })().catch(done);
- });
- });
- it('should emit orderStateInvalid when watched order cancelled', (done: DoneCallback) => {
- (async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerToken.address, takerToken.address, maker, taker, fillableAmount,
- );
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- zeroEx.orderStateWatcher.addOrder(signedOrder);
-
- const callback = reportCallbackErrors(done)((orderState: OrderState) => {
- expect(orderState.isValid).to.be.false();
- const invalidOrderState = orderState as OrderStateInvalid;
- expect(invalidOrderState.orderHash).to.be.equal(orderHash);
- expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderRemainingFillAmountZero);
- done();
- });
- zeroEx.orderStateWatcher.subscribe(callback);
-
- const shouldThrowOnInsufficientBalanceOrAllowance = true;
- await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
- })().catch(done);
- });
- it('should emit orderStateValid when watched order partially cancelled', (done: DoneCallback) => {
- (async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerToken.address, takerToken.address, maker, taker, fillableAmount,
- );
-
- const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
- const takerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, taker);
-
- const cancelAmountInBaseUnits = new BigNumber(2);
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- zeroEx.orderStateWatcher.addOrder(signedOrder);
-
- const callback = reportCallbackErrors(done)((orderState: OrderState) => {
- expect(orderState.isValid).to.be.true();
- const validOrderState = orderState as OrderStateValid;
- expect(validOrderState.orderHash).to.be.equal(orderHash);
- const orderRelevantState = validOrderState.orderRelevantState;
- expect(orderRelevantState.canceledTakerTokenAmount).to.be.bignumber.equal(cancelAmountInBaseUnits);
- done();
- });
- zeroEx.orderStateWatcher.subscribe(callback);
- await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelAmountInBaseUnits);
- })().catch(done);
- });
- });
-});
diff --git a/test/order_validation_test.ts b/test/order_validation_test.ts
deleted file mode 100644
index 4f18742d3..000000000
--- a/test/order_validation_test.ts
+++ /dev/null
@@ -1,327 +0,0 @@
-import * as chai from 'chai';
-import * as Web3 from 'web3';
-import BigNumber from 'bignumber.js';
-import * as Sinon from 'sinon';
-import {chaiSetup} from './utils/chai_setup';
-import {web3Factory} from './utils/web3_factory';
-import {ZeroEx, SignedOrder, Token, ExchangeContractErrs, ZeroExError} from '../src';
-import {TradeSide, TransferType} from '../src/types';
-import {TokenUtils} from './utils/token_utils';
-import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
-import {FillScenarios} from './utils/fill_scenarios';
-import {OrderValidationUtils} from '../src/utils/order_validation_utils';
-import {ExchangeTransferSimulator} from '../src/utils/exchange_transfer_simulator';
-
-chaiSetup.configure();
-const expect = chai.expect;
-const blockchainLifecycle = new BlockchainLifecycle();
-
-describe('OrderValidation', () => {
- let web3: Web3;
- let zeroEx: ZeroEx;
- let userAddresses: string[];
- let tokens: Token[];
- let tokenUtils: TokenUtils;
- let exchangeContractAddress: string;
- let zrxTokenAddress: string;
- let fillScenarios: FillScenarios;
- let makerTokenAddress: string;
- let takerTokenAddress: string;
- let coinbase: string;
- let makerAddress: string;
- let takerAddress: string;
- let feeRecipient: string;
- let orderValidationUtils: OrderValidationUtils;
- const fillableAmount = new BigNumber(5);
- const fillTakerAmount = new BigNumber(5);
- before(async () => {
- web3 = web3Factory.create();
- zeroEx = new ZeroEx(web3.currentProvider);
- exchangeContractAddress = await zeroEx.exchange.getContractAddressAsync();
- userAddresses = await zeroEx.getAvailableAddressesAsync();
- [coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses;
- tokens = await zeroEx.tokenRegistry.getTokensAsync();
- tokenUtils = new TokenUtils(tokens);
- zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address;
- fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress);
- const [makerToken, takerToken] = tokenUtils.getNonProtocolTokens();
- makerTokenAddress = makerToken.address;
- takerTokenAddress = takerToken.address;
- orderValidationUtils = new OrderValidationUtils(zeroEx.token, zeroEx.exchange);
- });
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
- describe('validateOrderFillableOrThrowAsync', () => {
- it('should succeed if the order is fillable', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- await zeroEx.exchange.validateOrderFillableOrThrowAsync(
- signedOrder,
- );
- });
- it('should succeed if the order is asymmetric and fillable', async () => {
- const makerFillableAmount = fillableAmount;
- const takerFillableAmount = fillableAmount.minus(4);
- const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
- makerFillableAmount, takerFillableAmount,
- );
- await zeroEx.exchange.validateOrderFillableOrThrowAsync(
- signedOrder,
- );
- });
- it('should throw when the order is fully filled or cancelled', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
- return expect(zeroEx.exchange.validateOrderFillableOrThrowAsync(
- signedOrder,
- )).to.be.rejectedWith(ExchangeContractErrs.OrderRemainingFillAmountZero);
- });
- it('should throw when order is expired', async () => {
- const expirationInPast = new BigNumber(1496826058); // 7th Jun 2017
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
- fillableAmount, expirationInPast,
- );
- return expect(zeroEx.exchange.validateOrderFillableOrThrowAsync(
- signedOrder,
- )).to.be.rejectedWith(ExchangeContractErrs.OrderFillExpired);
- });
- });
- describe('validateFillOrderAndThrowIfInvalidAsync', () => {
- it('should throw when the fill amount is zero', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- const zeroFillAmount = new BigNumber(0);
- return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
- signedOrder, zeroFillAmount, takerAddress,
- )).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- it('should throw when the signature is invalid', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- // 27 <--> 28
- signedOrder.ecSignature.v = 27 + (28 - signedOrder.ecSignature.v);
- return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
- signedOrder, fillableAmount, takerAddress,
- )).to.be.rejectedWith(ZeroExError.InvalidSignature);
- });
- it('should throw when the order is fully filled or cancelled', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
- return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
- signedOrder, fillableAmount, takerAddress,
- )).to.be.rejectedWith(ExchangeContractErrs.OrderRemainingFillAmountZero);
- });
- it('should throw when sender is not a taker', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- const nonTakerAddress = userAddresses[6];
- return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
- signedOrder, fillTakerAmount, nonTakerAddress,
- )).to.be.rejectedWith(ExchangeContractErrs.TransactionSenderIsNotFillOrderTaker);
- });
- it('should throw when order is expired', async () => {
- const expirationInPast = new BigNumber(1496826058); // 7th Jun 2017
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
- fillableAmount, expirationInPast,
- );
- return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
- signedOrder, fillTakerAmount, takerAddress,
- )).to.be.rejectedWith(ExchangeContractErrs.OrderFillExpired);
- });
- it('should throw when there a rounding error would have occurred', async () => {
- const makerAmount = new BigNumber(3);
- const takerAmount = new BigNumber(5);
- const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
- makerAmount, takerAmount,
- );
- const fillTakerAmountThatCausesRoundingError = new BigNumber(3);
- return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
- signedOrder, fillTakerAmountThatCausesRoundingError, takerAddress,
- )).to.be.rejectedWith(ExchangeContractErrs.OrderFillRoundingError);
- });
- });
- describe('#validateFillOrKillOrderAndThrowIfInvalidAsync', () => {
- it('should throw if remaining fillAmount is less then the desired fillAmount', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- const tooLargeFillAmount = new BigNumber(7);
- const fillAmountDifference = tooLargeFillAmount.minus(fillableAmount);
- await zeroEx.token.transferAsync(takerTokenAddress, coinbase, takerAddress, fillAmountDifference);
- await zeroEx.token.setProxyAllowanceAsync(takerTokenAddress, takerAddress, tooLargeFillAmount);
- await zeroEx.token.transferAsync(makerTokenAddress, coinbase, makerAddress, fillAmountDifference);
- await zeroEx.token.setProxyAllowanceAsync(makerTokenAddress, makerAddress, tooLargeFillAmount);
-
- return expect(zeroEx.exchange.validateFillOrKillOrderThrowIfInvalidAsync(
- signedOrder, tooLargeFillAmount, takerAddress,
- )).to.be.rejectedWith(ExchangeContractErrs.InsufficientRemainingFillAmount);
- });
- });
- describe('validateCancelOrderAndThrowIfInvalidAsync', () => {
- let signedOrder: SignedOrder;
- let orderHashHex: string;
- const cancelAmount = new BigNumber(3);
- beforeEach(async () => {
- [coinbase, makerAddress, takerAddress] = userAddresses;
- const [makerToken, takerToken] = tokenUtils.getNonProtocolTokens();
- makerTokenAddress = makerToken.address;
- takerTokenAddress = takerToken.address;
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
- );
- orderHashHex = ZeroEx.getOrderHashHex(signedOrder);
- });
- it('should throw when cancel amount is zero', async () => {
- const zeroCancelAmount = new BigNumber(0);
- return expect(zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(signedOrder, zeroCancelAmount))
- .to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
- });
- it('should throw when order is expired', async () => {
- const expirationInPast = new BigNumber(1496826058); // 7th Jun 2017
- const expiredSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
- fillableAmount, expirationInPast,
- );
- orderHashHex = ZeroEx.getOrderHashHex(expiredSignedOrder);
- return expect(zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(expiredSignedOrder, cancelAmount))
- .to.be.rejectedWith(ExchangeContractErrs.OrderCancelExpired);
- });
- it('should throw when order is already cancelled or filled', async () => {
- await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
- return expect(zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(signedOrder, fillableAmount))
- .to.be.rejectedWith(ExchangeContractErrs.OrderAlreadyCancelledOrFilled);
- });
- });
- describe('#validateFillOrderBalancesAllowancesThrowIfInvalidAsync', () => {
- let exchangeTransferSimulator: ExchangeTransferSimulator;
- let transferFromAsync: Sinon.SinonSpy;
- const bigNumberMatch = (expected: BigNumber) => {
- return Sinon.match((value: BigNumber) => value.eq(expected));
- };
- beforeEach('create exchangeTransferSimulator', async () => {
- exchangeTransferSimulator = new ExchangeTransferSimulator(zeroEx.token);
- transferFromAsync = Sinon.spy();
- exchangeTransferSimulator.transferFromAsync = transferFromAsync as any;
- });
- it('should call exchangeTransferSimulator.transferFrom in a correct order', async () => {
- const makerFee = new BigNumber(2);
- const takerFee = new BigNumber(2);
- const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
- makerTokenAddress, takerTokenAddress, makerFee, takerFee,
- makerAddress, takerAddress, fillableAmount, feeRecipient,
- );
- await orderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
- exchangeTransferSimulator, signedOrder, fillableAmount, takerAddress, zrxTokenAddress,
- );
- expect(transferFromAsync.callCount).to.be.equal(4);
- expect(
- transferFromAsync.getCall(0).calledWith(
- makerTokenAddress, makerAddress, takerAddress, bigNumberMatch(fillableAmount),
- TradeSide.Maker, TransferType.Trade,
- ),
- ).to.be.true();
- expect(
- transferFromAsync.getCall(1).calledWith(
- takerTokenAddress, takerAddress, makerAddress, bigNumberMatch(fillableAmount),
- TradeSide.Taker, TransferType.Trade,
- ),
- ).to.be.true();
- expect(
- transferFromAsync.getCall(2).calledWith(
- zrxTokenAddress, makerAddress, feeRecipient, bigNumberMatch(makerFee),
- TradeSide.Maker, TransferType.Fee,
- ),
- ).to.be.true();
- expect(
- transferFromAsync.getCall(3).calledWith(
- zrxTokenAddress, takerAddress, feeRecipient, bigNumberMatch(takerFee),
- TradeSide.Taker, TransferType.Fee,
- ),
- ).to.be.true();
- });
- it('should call exchangeTransferSimulator.transferFrom with correct values for an open order', async () => {
- const makerFee = new BigNumber(2);
- const takerFee = new BigNumber(2);
- const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
- makerTokenAddress, takerTokenAddress, makerFee, takerFee,
- makerAddress, ZeroEx.NULL_ADDRESS, fillableAmount, feeRecipient,
- );
- await orderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
- exchangeTransferSimulator, signedOrder, fillableAmount, takerAddress, zrxTokenAddress,
- );
- expect(transferFromAsync.callCount).to.be.equal(4);
- expect(
- transferFromAsync.getCall(0).calledWith(
- makerTokenAddress, makerAddress, takerAddress, bigNumberMatch(fillableAmount),
- TradeSide.Maker, TransferType.Trade,
- ),
- ).to.be.true();
- expect(
- transferFromAsync.getCall(1).calledWith(
- takerTokenAddress, takerAddress, makerAddress, bigNumberMatch(fillableAmount),
- TradeSide.Taker, TransferType.Trade,
- ),
- ).to.be.true();
- expect(
- transferFromAsync.getCall(2).calledWith(
- zrxTokenAddress, makerAddress, feeRecipient, bigNumberMatch(makerFee),
- TradeSide.Maker, TransferType.Fee,
- ),
- ).to.be.true();
- expect(
- transferFromAsync.getCall(3).calledWith(
- zrxTokenAddress, takerAddress, feeRecipient, bigNumberMatch(takerFee),
- TradeSide.Taker, TransferType.Fee,
- ),
- ).to.be.true();
- });
- it('should correctly round the fillMakerTokenAmount', async () => {
- const makerTokenAmount = new BigNumber(3);
- const takerTokenAmount = new BigNumber(1);
- const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, makerTokenAmount, takerTokenAmount,
- );
- await orderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
- exchangeTransferSimulator, signedOrder, takerTokenAmount, takerAddress, zrxTokenAddress,
- );
- expect(transferFromAsync.callCount).to.be.equal(4);
- const makerFillAmount = transferFromAsync.getCall(0).args[3];
- expect(makerFillAmount).to.be.bignumber.equal(makerTokenAmount);
- });
- it('should correctly round the makerFeeAmount', async () => {
- const makerFee = new BigNumber(2);
- const takerFee = new BigNumber(4);
- const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
- makerTokenAddress, takerTokenAddress, makerFee, takerFee, makerAddress, takerAddress,
- fillableAmount, ZeroEx.NULL_ADDRESS,
- );
- const fillTakerTokenAmount = fillableAmount.div(2).round(0);
- await orderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
- exchangeTransferSimulator, signedOrder, fillTakerTokenAmount, takerAddress, zrxTokenAddress,
- );
- const makerPartialFee = makerFee.div(2);
- const takerPartialFee = takerFee.div(2);
- expect(transferFromAsync.callCount).to.be.equal(4);
- const partialMakerFee = transferFromAsync.getCall(2).args[3];
- expect(partialMakerFee).to.be.bignumber.equal(makerPartialFee);
- const partialTakerFee = transferFromAsync.getCall(3).args[3];
- expect(partialTakerFee).to.be.bignumber.equal(takerPartialFee);
- });
- });
-});
diff --git a/test/subscription_test.ts b/test/subscription_test.ts
deleted file mode 100644
index 985fdc1d6..000000000
--- a/test/subscription_test.ts
+++ /dev/null
@@ -1,95 +0,0 @@
-import 'mocha';
-import * as _ from 'lodash';
-import * as chai from 'chai';
-import * as Sinon from 'sinon';
-import {chaiSetup} from './utils/chai_setup';
-import * as Web3 from 'web3';
-import BigNumber from 'bignumber.js';
-import promisify = require('es6-promisify');
-import {web3Factory} from './utils/web3_factory';
-import {
- ZeroEx,
- ZeroExError,
- Token,
- ApprovalContractEventArgs,
- TokenEvents,
- LogEvent,
-} from '../src';
-import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
-import {TokenUtils} from './utils/token_utils';
-import {DoneCallback, BlockParamLiteral} from '../src/types';
-
-chaiSetup.configure();
-const expect = chai.expect;
-const blockchainLifecycle = new BlockchainLifecycle();
-
-describe('SubscriptionTest', () => {
- let web3: Web3;
- let zeroEx: ZeroEx;
- let userAddresses: string[];
- let tokens: Token[];
- let tokenUtils: TokenUtils;
- let coinbase: string;
- let addressWithoutFunds: string;
- before(async () => {
- web3 = web3Factory.create();
- zeroEx = new ZeroEx(web3.currentProvider);
- userAddresses = await zeroEx.getAvailableAddressesAsync();
- tokens = await zeroEx.tokenRegistry.getTokensAsync();
- tokenUtils = new TokenUtils(tokens);
- coinbase = userAddresses[0];
- addressWithoutFunds = userAddresses[1];
- });
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
- describe('#subscribe', () => {
- const indexFilterValues = {};
- const shouldThrowOnInsufficientBalanceOrAllowance = true;
- let tokenAddress: string;
- const transferAmount = new BigNumber(42);
- const allowanceAmount = new BigNumber(42);
- let stubs: Sinon.SinonStub[] = [];
- before(() => {
- const token = tokens[0];
- tokenAddress = token.address;
- });
- afterEach(() => {
- zeroEx.token.unsubscribeAll();
- _.each(stubs, s => s.restore());
- stubs = [];
- });
- it('Should receive the Error when an error occurs', (done: DoneCallback) => {
- (async () => {
- const callback = (err: Error, logEvent: LogEvent<ApprovalContractEventArgs>) => {
- expect(err).to.not.be.null();
- expect(logEvent).to.be.undefined();
- done();
- };
- stubs = [
- Sinon.stub((zeroEx as any)._web3Wrapper, 'getBlockAsync')
- .throws("JSON RPC error")
- ]
- zeroEx.token.subscribe(
- tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
- await zeroEx.token.setAllowanceAsync(tokenAddress, coinbase, addressWithoutFunds, allowanceAmount);
- })().catch(done);
- });
- it('Should allow unsubscribeAll to be called successfully after an error', (done: DoneCallback) => {
- (async () => {
- const callback = (err: Error, logEvent: LogEvent<ApprovalContractEventArgs>) => { };
- zeroEx.token.subscribe(
- tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
- stubs = [
- Sinon.stub((zeroEx as any)._web3Wrapper, 'getBlockAsync')
- .throws("JSON RPC error")
- ]
- zeroEx.token.unsubscribeAll();
- done();
- })().catch(done);
- });
- })
- }) \ No newline at end of file
diff --git a/test/token_registry_wrapper_test.ts b/test/token_registry_wrapper_test.ts
deleted file mode 100644
index 6b5dd517e..000000000
--- a/test/token_registry_wrapper_test.ts
+++ /dev/null
@@ -1,123 +0,0 @@
-import * as _ from 'lodash';
-import 'mocha';
-import * as chai from 'chai';
-import {SchemaValidator, schemas} from '0x-json-schemas';
-import {chaiSetup} from './utils/chai_setup';
-import {web3Factory} from './utils/web3_factory';
-import {ZeroEx, Token} from '../src';
-import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
-
-chaiSetup.configure();
-const expect = chai.expect;
-const blockchainLifecycle = new BlockchainLifecycle();
-
-const TOKEN_REGISTRY_SIZE_AFTER_MIGRATION = 7;
-
-describe('TokenRegistryWrapper', () => {
- let zeroEx: ZeroEx;
- let tokens: Token[];
- const tokenAddressBySymbol: {[symbol: string]: string} = {};
- const tokenAddressByName: {[symbol: string]: string} = {};
- const tokenBySymbol: {[symbol: string]: Token} = {};
- const tokenByName: {[symbol: string]: Token} = {};
- const registeredSymbol = 'ZRX';
- const registeredName = '0x Protocol Token';
- const unregisteredSymbol = 'MAL';
- const unregisteredName = 'Malicious Token';
- before(async () => {
- const web3 = web3Factory.create();
- zeroEx = new ZeroEx(web3.currentProvider);
- tokens = await zeroEx.tokenRegistry.getTokensAsync();
- _.map(tokens, token => {
- tokenAddressBySymbol[token.symbol] = token.address;
- tokenAddressByName[token.name] = token.address;
- tokenBySymbol[token.symbol] = token;
- tokenByName[token.name] = token;
- });
- });
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
- describe('#getTokensAsync', () => {
- it('should return all the tokens added to the tokenRegistry during the migration', async () => {
- expect(tokens).to.have.lengthOf(TOKEN_REGISTRY_SIZE_AFTER_MIGRATION);
-
- const schemaValidator = new SchemaValidator();
- _.each(tokens, token => {
- const validationResult = schemaValidator.validate(token, schemas.tokenSchema);
- expect(validationResult.errors).to.have.lengthOf(0);
- });
- });
- });
- describe('#getTokenAddressesAsync', () => {
- it('should return all the token addresses added to the tokenRegistry during the migration', async () => {
- const tokenAddresses = await zeroEx.tokenRegistry.getTokenAddressesAsync();
- expect(tokenAddresses).to.have.lengthOf(TOKEN_REGISTRY_SIZE_AFTER_MIGRATION);
-
- const schemaValidator = new SchemaValidator();
- _.each(tokenAddresses, tokenAddress => {
- const validationResult = schemaValidator.validate(tokenAddress, schemas.addressSchema);
- expect(validationResult.errors).to.have.lengthOf(0);
- expect(tokenAddress).to.not.be.equal(ZeroEx.NULL_ADDRESS);
- });
- });
- });
- describe('#getTokenAddressBySymbol', () => {
- it('should return correct address for a token in the registry', async () => {
- const tokenAddress = await zeroEx.tokenRegistry.getTokenAddressBySymbolIfExistsAsync(registeredSymbol);
- expect(tokenAddress).to.be.equal(tokenAddressBySymbol[registeredSymbol]);
- });
- it('should return undefined for a token out of registry', async () => {
- const tokenAddress = await zeroEx.tokenRegistry.getTokenAddressBySymbolIfExistsAsync(unregisteredSymbol);
- expect(tokenAddress).to.be.undefined();
- });
- });
- describe('#getTokenAddressByName', () => {
- it('should return correct address for a token in the registry', async () => {
- const tokenAddress = await zeroEx.tokenRegistry.getTokenAddressByNameIfExistsAsync(registeredName);
- expect(tokenAddress).to.be.equal(tokenAddressByName[registeredName]);
- });
- it('should return undefined for a token out of registry', async () => {
- const tokenAddress = await zeroEx.tokenRegistry.getTokenAddressByNameIfExistsAsync(unregisteredName);
- expect(tokenAddress).to.be.undefined();
- });
- });
- describe('#getTokenBySymbol', () => {
- it('should return correct token for a token in the registry', async () => {
- const token = await zeroEx.tokenRegistry.getTokenBySymbolIfExistsAsync(registeredSymbol);
- expect(token).to.be.deep.equal(tokenBySymbol[registeredSymbol]);
- });
- it('should return undefined for a token out of registry', async () => {
- const token = await zeroEx.tokenRegistry.getTokenBySymbolIfExistsAsync(unregisteredSymbol);
- expect(token).to.be.undefined();
- });
- });
- describe('#getTokenByName', () => {
- it('should return correct token for a token in the registry', async () => {
- const token = await zeroEx.tokenRegistry.getTokenByNameIfExistsAsync(registeredName);
- expect(token).to.be.deep.equal(tokenByName[registeredName]);
- });
- it('should return undefined for a token out of registry', async () => {
- const token = await zeroEx.tokenRegistry.getTokenByNameIfExistsAsync(unregisteredName);
- expect(token).to.be.undefined();
- });
- });
- describe('#getTokenIfExistsAsync', () => {
- it('should return the token added to the tokenRegistry during the migration', async () => {
- const aToken = tokens[0];
-
- const token = await zeroEx.tokenRegistry.getTokenIfExistsAsync(aToken.address);
- const schemaValidator = new SchemaValidator();
- const validationResult = schemaValidator.validate(token, schemas.tokenSchema);
- expect(validationResult.errors).to.have.lengthOf(0);
- });
- it('should return return undefined when passed a token address not in the tokenRegistry', async () => {
- const unregisteredTokenAddress = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
- const tokenIfExists = await zeroEx.tokenRegistry.getTokenIfExistsAsync(unregisteredTokenAddress);
- expect(tokenIfExists).to.be.undefined();
- });
- });
-});
diff --git a/test/token_transfer_proxy_wrapper_test.ts b/test/token_transfer_proxy_wrapper_test.ts
deleted file mode 100644
index 8faef0b30..000000000
--- a/test/token_transfer_proxy_wrapper_test.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import * as chai from 'chai';
-import {chaiSetup} from './utils/chai_setup';
-import {web3Factory} from './utils/web3_factory';
-import {ZeroEx} from '../src';
-import {TokenTransferProxyWrapper} from '../src/contract_wrappers/token_transfer_proxy_wrapper';
-
-chaiSetup.configure();
-const expect = chai.expect;
-
-describe('TokenTransferProxyWrapper', () => {
- let zeroEx: ZeroEx;
- before(async () => {
- const web3 = web3Factory.create();
- zeroEx = new ZeroEx(web3.currentProvider);
- });
- describe('#isAuthorizedAsync', () => {
- it('should return false if the address is not authorized', async () => {
- const isAuthorized = await zeroEx.proxy.isAuthorizedAsync(ZeroEx.NULL_ADDRESS);
- expect(isAuthorized).to.be.false();
- });
- });
- describe('#getAuthorizedAddressesAsync', () => {
- it('should return the list of authorized addresses', async () => {
- const authorizedAddresses = await zeroEx.proxy.getAuthorizedAddressesAsync();
- for (const authorizedAddress of authorizedAddresses) {
- const isAuthorized = await zeroEx.proxy.isAuthorizedAsync(authorizedAddress);
- expect(isAuthorized).to.be.true();
- }
- });
- });
-});
diff --git a/test/token_wrapper_test.ts b/test/token_wrapper_test.ts
deleted file mode 100644
index b30762e8c..000000000
--- a/test/token_wrapper_test.ts
+++ /dev/null
@@ -1,477 +0,0 @@
-import 'mocha';
-import * as chai from 'chai';
-import {chaiSetup} from './utils/chai_setup';
-import * as Web3 from 'web3';
-import BigNumber from 'bignumber.js';
-import promisify = require('es6-promisify');
-import {web3Factory} from './utils/web3_factory';
-import {
- ZeroEx,
- ZeroExError,
- Token,
- SubscriptionOpts,
- TokenEvents,
- ContractEvent,
- TransferContractEventArgs,
- ApprovalContractEventArgs,
- TokenContractEventArgs,
- LogWithDecodedArgs,
- LogEvent,
- DecodedLogEvent,
-} from '../src';
-import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
-import {TokenUtils} from './utils/token_utils';
-import {DoneCallback, BlockParamLiteral} from '../src/types';
-
-chaiSetup.configure();
-const expect = chai.expect;
-const blockchainLifecycle = new BlockchainLifecycle();
-
-describe('TokenWrapper', () => {
- let web3: Web3;
- let zeroEx: ZeroEx;
- let userAddresses: string[];
- let tokens: Token[];
- let tokenUtils: TokenUtils;
- let coinbase: string;
- let addressWithoutFunds: string;
- before(async () => {
- web3 = web3Factory.create();
- zeroEx = new ZeroEx(web3.currentProvider);
- userAddresses = await zeroEx.getAvailableAddressesAsync();
- tokens = await zeroEx.tokenRegistry.getTokensAsync();
- tokenUtils = new TokenUtils(tokens);
- coinbase = userAddresses[0];
- addressWithoutFunds = userAddresses[1];
- });
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
- describe('#transferAsync', () => {
- let token: Token;
- let transferAmount: BigNumber;
- before(() => {
- token = tokens[0];
- transferAmount = new BigNumber(42);
- });
- it('should successfully transfer tokens', async () => {
- const fromAddress = coinbase;
- const toAddress = addressWithoutFunds;
- const preBalance = await zeroEx.token.getBalanceAsync(token.address, toAddress);
- expect(preBalance).to.be.bignumber.equal(0);
- const txHash = await zeroEx.token.transferAsync(token.address, fromAddress, toAddress, transferAmount);
- const receipt = await zeroEx.awaitTransactionMinedAsync(txHash);
- const postBalance = await zeroEx.token.getBalanceAsync(token.address, toAddress);
- return expect(postBalance).to.be.bignumber.equal(transferAmount);
- });
- it('should fail to transfer tokens if fromAddress has an insufficient balance', async () => {
- const fromAddress = addressWithoutFunds;
- const toAddress = coinbase;
- return expect(zeroEx.token.transferAsync(
- token.address, fromAddress, toAddress, transferAmount,
- )).to.be.rejectedWith(ZeroExError.InsufficientBalanceForTransfer);
- });
- it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => {
- const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065';
- const fromAddress = coinbase;
- const toAddress = coinbase;
- return expect(zeroEx.token.transferAsync(
- nonExistentTokenAddress, fromAddress, toAddress, transferAmount,
- )).to.be.rejectedWith(ZeroExError.ContractDoesNotExist);
- });
- });
- describe('#transferFromAsync', () => {
- let token: Token;
- let toAddress: string;
- let senderAddress: string;
- before(async () => {
- token = tokens[0];
- toAddress = addressWithoutFunds;
- senderAddress = userAddresses[2];
- });
- it('should fail to transfer tokens if fromAddress has insufficient allowance set', async () => {
- const fromAddress = coinbase;
- const transferAmount = new BigNumber(42);
-
- const fromAddressBalance = await zeroEx.token.getBalanceAsync(token.address, fromAddress);
- expect(fromAddressBalance).to.be.bignumber.greaterThan(transferAmount);
-
- const fromAddressAllowance = await zeroEx.token.getAllowanceAsync(token.address, fromAddress,
- toAddress);
- expect(fromAddressAllowance).to.be.bignumber.equal(0);
-
- return expect(zeroEx.token.transferFromAsync(
- token.address, fromAddress, toAddress, senderAddress, transferAmount,
- )).to.be.rejectedWith(ZeroExError.InsufficientAllowanceForTransfer);
- });
- it('[regression] should fail to transfer tokens if set allowance for toAddress instead of senderAddress',
- async () => {
- const fromAddress = coinbase;
- const transferAmount = new BigNumber(42);
-
- await zeroEx.token.setAllowanceAsync(token.address, fromAddress, toAddress, transferAmount);
-
- return expect(zeroEx.token.transferFromAsync(
- token.address, fromAddress, toAddress, senderAddress, transferAmount,
- )).to.be.rejectedWith(ZeroExError.InsufficientAllowanceForTransfer);
- });
- it('should fail to transfer tokens if fromAddress has insufficient balance', async () => {
- const fromAddress = addressWithoutFunds;
- const transferAmount = new BigNumber(42);
-
- const fromAddressBalance = await zeroEx.token.getBalanceAsync(token.address, fromAddress);
- expect(fromAddressBalance).to.be.bignumber.equal(0);
-
- await zeroEx.token.setAllowanceAsync(token.address, fromAddress, senderAddress, transferAmount);
- const fromAddressAllowance = await zeroEx.token.getAllowanceAsync(token.address, fromAddress,
- senderAddress);
- expect(fromAddressAllowance).to.be.bignumber.equal(transferAmount);
-
- return expect(zeroEx.token.transferFromAsync(
- token.address, fromAddress, toAddress, senderAddress, transferAmount,
- )).to.be.rejectedWith(ZeroExError.InsufficientBalanceForTransfer);
- });
- it('should successfully transfer tokens', async () => {
- const fromAddress = coinbase;
-
- const preBalance = await zeroEx.token.getBalanceAsync(token.address, toAddress);
- expect(preBalance).to.be.bignumber.equal(0);
-
- const transferAmount = new BigNumber(42);
- await zeroEx.token.setAllowanceAsync(token.address, fromAddress, senderAddress, transferAmount);
-
- await zeroEx.token.transferFromAsync(token.address, fromAddress, toAddress, senderAddress,
- transferAmount);
- const postBalance = await zeroEx.token.getBalanceAsync(token.address, toAddress);
- return expect(postBalance).to.be.bignumber.equal(transferAmount);
- });
- it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => {
- const fromAddress = coinbase;
- const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065';
- return expect(zeroEx.token.transferFromAsync(
- nonExistentTokenAddress, fromAddress, toAddress, senderAddress, new BigNumber(42),
- )).to.be.rejectedWith(ZeroExError.ContractDoesNotExist);
- });
- });
- describe('#getBalanceAsync', () => {
- describe('With web3 provider with accounts', () => {
- it('should return the balance for an existing ERC20 token', async () => {
- const token = tokens[0];
- const ownerAddress = coinbase;
- const balance = await zeroEx.token.getBalanceAsync(token.address, ownerAddress);
- const expectedBalance = new BigNumber('1000000000000000000000000000');
- return expect(balance).to.be.bignumber.equal(expectedBalance);
- });
- it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => {
- const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065';
- const ownerAddress = coinbase;
- return expect(zeroEx.token.getBalanceAsync(nonExistentTokenAddress, ownerAddress))
- .to.be.rejectedWith(ZeroExError.ContractDoesNotExist);
- });
- it('should return a balance of 0 for a non-existent owner address', async () => {
- const token = tokens[0];
- const nonExistentOwner = '0x198c6ad858f213fb31b6fe809e25040e6b964593';
- const balance = await zeroEx.token.getBalanceAsync(token.address, nonExistentOwner);
- const expectedBalance = new BigNumber(0);
- return expect(balance).to.be.bignumber.equal(expectedBalance);
- });
- });
- describe('With web3 provider without accounts', () => {
- let zeroExWithoutAccounts: ZeroEx;
- before(async () => {
- const hasAddresses = false;
- const web3WithoutAccounts = web3Factory.create(hasAddresses);
- zeroExWithoutAccounts = new ZeroEx(web3WithoutAccounts.currentProvider);
- });
- it('should return balance even when called with Web3 provider instance without addresses', async () => {
- const token = tokens[0];
- const ownerAddress = coinbase;
- const balance = await zeroExWithoutAccounts.token.getBalanceAsync(token.address, ownerAddress);
- const expectedBalance = new BigNumber('1000000000000000000000000000');
- return expect(balance).to.be.bignumber.equal(expectedBalance);
- });
- });
- });
- describe('#setAllowanceAsync', () => {
- it('should set the spender\'s allowance', async () => {
- const token = tokens[0];
- const ownerAddress = coinbase;
- const spenderAddress = addressWithoutFunds;
-
- const allowanceBeforeSet = await zeroEx.token.getAllowanceAsync(token.address, ownerAddress,
- spenderAddress);
- const expectedAllowanceBeforeAllowanceSet = new BigNumber(0);
- expect(allowanceBeforeSet).to.be.bignumber.equal(expectedAllowanceBeforeAllowanceSet);
-
- const amountInBaseUnits = new BigNumber(50);
- await zeroEx.token.setAllowanceAsync(token.address, ownerAddress, spenderAddress, amountInBaseUnits);
-
- const allowanceAfterSet = await zeroEx.token.getAllowanceAsync(token.address, ownerAddress, spenderAddress);
- const expectedAllowanceAfterAllowanceSet = amountInBaseUnits;
- return expect(allowanceAfterSet).to.be.bignumber.equal(expectedAllowanceAfterAllowanceSet);
- });
- });
- describe('#setUnlimitedAllowanceAsync', () => {
- it('should set the unlimited spender\'s allowance', async () => {
- const token = tokens[0];
- const ownerAddress = coinbase;
- const spenderAddress = addressWithoutFunds;
-
- await zeroEx.token.setUnlimitedAllowanceAsync(token.address, ownerAddress, spenderAddress);
- const allowance = await zeroEx.token.getAllowanceAsync(token.address, ownerAddress, spenderAddress);
- return expect(allowance).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
- });
- it('should reduce the gas cost for transfers including tokens with unlimited allowance support', async () => {
- const transferAmount = new BigNumber(5);
- const zrx = tokenUtils.getProtocolTokenOrThrow();
- const [, userWithNormalAllowance, userWithUnlimitedAllowance] = userAddresses;
- await zeroEx.token.setAllowanceAsync(zrx.address, coinbase, userWithNormalAllowance, transferAmount);
- await zeroEx.token.setUnlimitedAllowanceAsync(zrx.address, coinbase, userWithUnlimitedAllowance);
-
- const initBalanceWithNormalAllowance = await promisify(web3.eth.getBalance)(userWithNormalAllowance);
- const initBalanceWithUnlimitedAllowance = await promisify(web3.eth.getBalance)(userWithUnlimitedAllowance);
-
- await zeroEx.token.transferFromAsync(
- zrx.address, coinbase, userWithNormalAllowance, userWithNormalAllowance, transferAmount,
- );
- await zeroEx.token.transferFromAsync(
- zrx.address, coinbase, userWithUnlimitedAllowance, userWithUnlimitedAllowance, transferAmount,
- );
-
- const finalBalanceWithNormalAllowance = await promisify(web3.eth.getBalance)(userWithNormalAllowance);
- const finalBalanceWithUnlimitedAllowance = await promisify(web3.eth.getBalance)(userWithUnlimitedAllowance);
-
- const normalGasCost = initBalanceWithNormalAllowance.minus(finalBalanceWithNormalAllowance);
- const unlimitedGasCost = initBalanceWithUnlimitedAllowance.minus(finalBalanceWithUnlimitedAllowance);
-
- // In theory the gas cost with unlimited allowance should be smaller, but with testrpc it's actually bigger.
- // This needs to be investigated in ethereumjs-vm. This test is essentially a repro.
- // TODO: Make this test pass with inverted assertion.
- expect(unlimitedGasCost.toNumber()).to.be.gt(normalGasCost.toNumber());
- });
- });
- describe('#getAllowanceAsync', () => {
- describe('With web3 provider with accounts', () => {
- it('should get the proxy allowance', async () => {
- const token = tokens[0];
- const ownerAddress = coinbase;
- const spenderAddress = addressWithoutFunds;
-
- const amountInBaseUnits = new BigNumber(50);
- await zeroEx.token.setAllowanceAsync(token.address, ownerAddress, spenderAddress, amountInBaseUnits);
-
- const allowance = await zeroEx.token.getAllowanceAsync(token.address, ownerAddress, spenderAddress);
- const expectedAllowance = amountInBaseUnits;
- return expect(allowance).to.be.bignumber.equal(expectedAllowance);
- });
- it('should return 0 if no allowance set yet', async () => {
- const token = tokens[0];
- const ownerAddress = coinbase;
- const spenderAddress = addressWithoutFunds;
- const allowance = await zeroEx.token.getAllowanceAsync(token.address, ownerAddress, spenderAddress);
- const expectedAllowance = new BigNumber(0);
- return expect(allowance).to.be.bignumber.equal(expectedAllowance);
- });
- });
- describe('With web3 provider without accounts', () => {
- let zeroExWithoutAccounts: ZeroEx;
- before(async () => {
- const hasAddresses = false;
- const web3WithoutAccounts = web3Factory.create(hasAddresses);
- zeroExWithoutAccounts = new ZeroEx(web3WithoutAccounts.currentProvider);
- });
- it('should get the proxy allowance', async () => {
- const token = tokens[0];
- const ownerAddress = coinbase;
- const spenderAddress = addressWithoutFunds;
-
- const amountInBaseUnits = new BigNumber(50);
- await zeroEx.token.setAllowanceAsync(token.address, ownerAddress, spenderAddress, amountInBaseUnits);
-
- const allowance = await zeroExWithoutAccounts.token.getAllowanceAsync(
- token.address, ownerAddress, spenderAddress,
- );
- const expectedAllowance = amountInBaseUnits;
- return expect(allowance).to.be.bignumber.equal(expectedAllowance);
- });
- });
- });
- describe('#getProxyAllowanceAsync', () => {
- it('should get the proxy allowance', async () => {
- const token = tokens[0];
- const ownerAddress = coinbase;
-
- const amountInBaseUnits = new BigNumber(50);
- await zeroEx.token.setProxyAllowanceAsync(token.address, ownerAddress, amountInBaseUnits);
-
- const allowance = await zeroEx.token.getProxyAllowanceAsync(token.address, ownerAddress);
- const expectedAllowance = amountInBaseUnits;
- return expect(allowance).to.be.bignumber.equal(expectedAllowance);
- });
- });
- describe('#setProxyAllowanceAsync', () => {
- it('should set the proxy allowance', async () => {
- const token = tokens[0];
- const ownerAddress = coinbase;
-
- const allowanceBeforeSet = await zeroEx.token.getProxyAllowanceAsync(token.address, ownerAddress);
- const expectedAllowanceBeforeAllowanceSet = new BigNumber(0);
- expect(allowanceBeforeSet).to.be.bignumber.equal(expectedAllowanceBeforeAllowanceSet);
-
- const amountInBaseUnits = new BigNumber(50);
- await zeroEx.token.setProxyAllowanceAsync(token.address, ownerAddress, amountInBaseUnits);
-
- const allowanceAfterSet = await zeroEx.token.getProxyAllowanceAsync(token.address, ownerAddress);
- const expectedAllowanceAfterAllowanceSet = amountInBaseUnits;
- return expect(allowanceAfterSet).to.be.bignumber.equal(expectedAllowanceAfterAllowanceSet);
- });
- });
- describe('#setUnlimitedProxyAllowanceAsync', () => {
- it('should set the unlimited proxy allowance', async () => {
- const token = tokens[0];
- const ownerAddress = coinbase;
-
- await zeroEx.token.setUnlimitedProxyAllowanceAsync(token.address, ownerAddress);
- const allowance = await zeroEx.token.getProxyAllowanceAsync(token.address, ownerAddress);
- return expect(allowance).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
- });
- });
- describe('#subscribe', () => {
- const indexFilterValues = {};
- const shouldThrowOnInsufficientBalanceOrAllowance = true;
- let tokenAddress: string;
- const transferAmount = new BigNumber(42);
- const allowanceAmount = new BigNumber(42);
- before(() => {
- const token = tokens[0];
- tokenAddress = token.address;
- });
- afterEach(() => {
- zeroEx.token.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<TransferContractEventArgs>) => {
- expect(logEvent).to.not.be.undefined();
- const args = logEvent.args;
- expect(args._from).to.be.equal(coinbase);
- expect(args._to).to.be.equal(addressWithoutFunds);
- expect(args._value).to.be.bignumber.equal(transferAmount);
- done();
- };
- zeroEx.token.subscribe(
- tokenAddress, TokenEvents.Transfer, indexFilterValues, callback);
- await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
- })().catch(done);
- });
- it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => {
- (async () => {
- const callback = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
- expect(logEvent).to.not.be.undefined();
- const args = logEvent.args;
- expect(args._owner).to.be.equal(coinbase);
- expect(args._spender).to.be.equal(addressWithoutFunds);
- expect(args._value).to.be.bignumber.equal(allowanceAmount);
- done();
- };
- zeroEx.token.subscribe(
- tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
- await zeroEx.token.setAllowanceAsync(tokenAddress, coinbase, addressWithoutFunds, allowanceAmount);
- })().catch(done);
- });
- it('Outstanding subscriptions are cancelled when zeroEx.setProviderAsync called', (done: DoneCallback) => {
- (async () => {
- const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
- done(new Error('Expected this subscription to have been cancelled'));
- };
- zeroEx.token.subscribe(
- tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled,
- );
- const callbackToBeCalled = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
- done();
- };
- const newProvider = web3Factory.getRpcProvider();
- await zeroEx.setProviderAsync(newProvider);
- zeroEx.token.subscribe(
- tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackToBeCalled,
- );
- await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
- })().catch(done);
- });
- it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => {
- (async () => {
- const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
- done(new Error('Expected this subscription to have been cancelled'));
- };
- const subscriptionToken = zeroEx.token.subscribe(
- tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled);
- zeroEx.token.unsubscribe(subscriptionToken);
- await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
- done();
- })().catch(done);
- });
- });
- describe('#getLogsAsync', () => {
- let tokenAddress: string;
- let tokenTransferProxyAddress: string;
- const subscriptionOpts: SubscriptionOpts = {
- fromBlock: BlockParamLiteral.Earliest,
- toBlock: BlockParamLiteral.Latest,
- };
- let txHash: string;
- before(async () => {
- const token = tokens[0];
- tokenAddress = token.address;
- tokenTransferProxyAddress = await zeroEx.proxy.getContractAddressAsync();
- });
- it('should get logs with decoded args emitted by Approval', async () => {
- txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- const eventName = TokenEvents.Approval;
- const indexFilterValues = {};
- const logs = await zeroEx.token.getLogsAsync<ApprovalContractEventArgs>(
- tokenAddress, eventName, subscriptionOpts, 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(coinbase);
- 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(tokenAddress, coinbase);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- const differentEventName = TokenEvents.Transfer;
- const indexFilterValues = {};
- const logs = await zeroEx.token.getLogsAsync(
- tokenAddress, differentEventName, subscriptionOpts, indexFilterValues,
- );
- expect(logs).to.have.length(0);
- });
- it('should only get the logs with the correct indexed fields', async () => {
- txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(tokenAddress, addressWithoutFunds);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- const eventName = TokenEvents.Approval;
- const indexFilterValues = {
- _owner: coinbase,
- };
- const logs = await zeroEx.token.getLogsAsync<ApprovalContractEventArgs>(
- tokenAddress, eventName, subscriptionOpts, indexFilterValues,
- );
- expect(logs).to.have.length(1);
- const args = logs[0].args;
- expect(args._owner).to.be.equal(coinbase);
- });
- });
-});
diff --git a/test/utils/blockchain_lifecycle.ts b/test/utils/blockchain_lifecycle.ts
deleted file mode 100644
index 9a44ccd6f..000000000
--- a/test/utils/blockchain_lifecycle.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import {RPC} from './rpc';
-
-export class BlockchainLifecycle {
- private rpc: RPC;
- private snapshotIdsStack: number[];
- constructor() {
- this.rpc = new RPC();
- this.snapshotIdsStack = [];
- }
- // TODO: In order to run these tests on an actual node, we should check if we are running against
- // TestRPC, if so, use snapshots, otherwise re-deploy contracts before every test
- public async startAsync(): Promise<void> {
- const snapshotId = await this.rpc.takeSnapshotAsync();
- this.snapshotIdsStack.push(snapshotId);
- }
- public async revertAsync(): Promise<void> {
- const snapshotId = this.snapshotIdsStack.pop() as number;
- const didRevert = await this.rpc.revertSnapshotAsync(snapshotId);
- if (!didRevert) {
- throw new Error(`Snapshot with id #${snapshotId} failed to revert`);
- }
- }
- public async mineABlock(): Promise<void> {
- await this.rpc.mineBlockAsync();
- }
-}
diff --git a/test/utils/chai_setup.ts b/test/utils/chai_setup.ts
deleted file mode 100644
index c18988106..000000000
--- a/test/utils/chai_setup.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import * as chai from 'chai';
-import * as dirtyChai from 'dirty-chai';
-import ChaiBigNumber = require('chai-bignumber');
-import chaiAsPromised = require('chai-as-promised');
-
-export const chaiSetup = {
- configure() {
- chai.config.includeStack = true;
- chai.use(ChaiBigNumber());
- chai.use(dirtyChai);
- chai.use(chaiAsPromised);
- },
-};
diff --git a/test/utils/constants.ts b/test/utils/constants.ts
deleted file mode 100644
index c7d3aebca..000000000
--- a/test/utils/constants.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export const constants = {
- NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
- RPC_HOST: 'localhost',
- RPC_PORT: 8545,
- TESTRPC_NETWORK_ID: 50,
- KOVAN_RPC_URL: 'https://kovan.infura.io',
- ROPSTEN_RPC_URL: 'https://ropsten.infura.io',
-};
diff --git a/test/utils/fill_scenarios.ts b/test/utils/fill_scenarios.ts
deleted file mode 100644
index a0632b12c..000000000
--- a/test/utils/fill_scenarios.ts
+++ /dev/null
@@ -1,114 +0,0 @@
-import BigNumber from 'bignumber.js';
-import {ZeroEx, Token, SignedOrder} from '../../src';
-import {orderFactory} from '../utils/order_factory';
-import {constants} from './constants';
-
-export class FillScenarios {
- private zeroEx: ZeroEx;
- private userAddresses: string[];
- private tokens: Token[];
- private coinbase: string;
- private zrxTokenAddress: string;
- private exchangeContractAddress: string;
- constructor(zeroEx: ZeroEx, userAddresses: string[],
- tokens: Token[], zrxTokenAddress: string, exchangeContractAddress: string) {
- this.zeroEx = zeroEx;
- this.userAddresses = userAddresses;
- this.tokens = tokens;
- this.coinbase = userAddresses[0];
- this.zrxTokenAddress = zrxTokenAddress;
- this.exchangeContractAddress = exchangeContractAddress;
- }
- public async createFillableSignedOrderAsync(makerTokenAddress: string, takerTokenAddress: string,
- makerAddress: string, takerAddress: string,
- fillableAmount: BigNumber,
- expirationUnixTimestampSec?: BigNumber):
- Promise<SignedOrder> {
- return this.createAsymmetricFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
- fillableAmount, fillableAmount, expirationUnixTimestampSec,
- );
- }
- public async createFillableSignedOrderWithFeesAsync(
- makerTokenAddress: string, takerTokenAddress: string,
- makerFee: BigNumber, takerFee: BigNumber,
- makerAddress: string, takerAddress: string,
- fillableAmount: BigNumber,
- feeRecepient: string, expirationUnixTimestampSec?: BigNumber,
- ): Promise<SignedOrder> {
- return this.createAsymmetricFillableSignedOrderWithFeesAsync(
- makerTokenAddress, takerTokenAddress, makerFee, takerFee, makerAddress, takerAddress,
- fillableAmount, fillableAmount, feeRecepient, expirationUnixTimestampSec,
- );
- }
- public async createAsymmetricFillableSignedOrderAsync(
- makerTokenAddress: string, takerTokenAddress: string, makerAddress: string, takerAddress: string,
- makerFillableAmount: BigNumber, takerFillableAmount: BigNumber,
- expirationUnixTimestampSec?: BigNumber): Promise<SignedOrder> {
- const makerFee = new BigNumber(0);
- const takerFee = new BigNumber(0);
- const feeRecepient = constants.NULL_ADDRESS;
- return this.createAsymmetricFillableSignedOrderWithFeesAsync(
- makerTokenAddress, takerTokenAddress, makerFee, takerFee, makerAddress, takerAddress,
- makerFillableAmount, takerFillableAmount, feeRecepient, expirationUnixTimestampSec,
- );
- }
- public async createPartiallyFilledSignedOrderAsync(makerTokenAddress: string, takerTokenAddress: string,
- takerAddress: string, fillableAmount: BigNumber,
- partialFillAmount: BigNumber) {
- const [makerAddress] = this.userAddresses;
- const signedOrder = await this.createAsymmetricFillableSignedOrderAsync(
- makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
- fillableAmount, fillableAmount,
- );
- const shouldThrowOnInsufficientBalanceOrAllowance = false;
- await this.zeroEx.exchange.fillOrderAsync(
- signedOrder, partialFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
- );
- return signedOrder;
- }
- private async createAsymmetricFillableSignedOrderWithFeesAsync(
- makerTokenAddress: string, takerTokenAddress: string,
- makerFee: BigNumber, takerFee: BigNumber,
- makerAddress: string, takerAddress: string,
- makerFillableAmount: BigNumber, takerFillableAmount: BigNumber,
- feeRecepient: string, expirationUnixTimestampSec?: BigNumber): Promise<SignedOrder> {
-
- await Promise.all([
- this.increaseBalanceAndAllowanceAsync(makerTokenAddress, makerAddress, makerFillableAmount),
- this.increaseBalanceAndAllowanceAsync(takerTokenAddress, takerAddress, takerFillableAmount),
- ]);
- await Promise.all([
- this.increaseBalanceAndAllowanceAsync(this.zrxTokenAddress, makerAddress, makerFee),
- this.increaseBalanceAndAllowanceAsync(this.zrxTokenAddress, takerAddress, takerFee),
- ]);
-
- const signedOrder = await orderFactory.createSignedOrderAsync(this.zeroEx,
- makerAddress, takerAddress, makerFee, takerFee,
- makerFillableAmount, makerTokenAddress, takerFillableAmount, takerTokenAddress,
- this.exchangeContractAddress, feeRecepient, expirationUnixTimestampSec);
- return signedOrder;
- }
- private async increaseBalanceAndAllowanceAsync(
- tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
- if (amount.isZero() || address === ZeroEx.NULL_ADDRESS) {
- return; // noop
- }
- await Promise.all([
- this.increaseBalanceAsync(tokenAddress, address, amount),
- this.increaseAllowanceAsync(tokenAddress, address, amount),
- ]);
- }
- private async increaseBalanceAsync(
- tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
- await this.zeroEx.token.transferAsync(tokenAddress, this.coinbase, address, amount);
- }
- private async increaseAllowanceAsync(
- tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
- const oldMakerAllowance = await this.zeroEx.token.getProxyAllowanceAsync(tokenAddress, address);
- const newMakerAllowance = oldMakerAllowance.plus(amount);
- await this.zeroEx.token.setProxyAllowanceAsync(
- tokenAddress, address, newMakerAllowance,
- );
- }
-}
diff --git a/test/utils/order_factory.ts b/test/utils/order_factory.ts
deleted file mode 100644
index 6086e09f7..000000000
--- a/test/utils/order_factory.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import * as _ from 'lodash';
-import BigNumber from 'bignumber.js';
-import {ZeroEx, SignedOrder} from '../../src';
-
-export const orderFactory = {
- async createSignedOrderAsync(
- zeroEx: ZeroEx,
- maker: string,
- taker: string,
- makerFee: BigNumber,
- takerFee: BigNumber,
- makerTokenAmount: BigNumber,
- makerTokenAddress: string,
- takerTokenAmount: BigNumber,
- takerTokenAddress: string,
- exchangeContractAddress: string,
- feeRecipient: string,
- expirationUnixTimestampSec?: BigNumber): Promise<SignedOrder> {
- const defaultExpirationUnixTimestampSec = new BigNumber(2524604400); // Close to infinite
- expirationUnixTimestampSec = _.isUndefined(expirationUnixTimestampSec) ?
- defaultExpirationUnixTimestampSec :
- expirationUnixTimestampSec;
- const order = {
- maker,
- taker,
- makerFee,
- takerFee,
- makerTokenAmount,
- takerTokenAmount,
- makerTokenAddress,
- takerTokenAddress,
- salt: ZeroEx.generatePseudoRandomSalt(),
- exchangeContractAddress,
- feeRecipient,
- expirationUnixTimestampSec,
- };
- const orderHash = ZeroEx.getOrderHashHex(order);
- const ecSignature = await zeroEx.signOrderHashAsync(orderHash, maker);
- const signedOrder: SignedOrder = _.assign(order, {ecSignature});
- return signedOrder;
- },
-};
diff --git a/test/utils/report_callback_errors.ts b/test/utils/report_callback_errors.ts
deleted file mode 100644
index d471b2af2..000000000
--- a/test/utils/report_callback_errors.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { DoneCallback } from '../../src/types';
-
-export const reportCallbackErrors = (done: DoneCallback) => {
- return (f: (...args: any[]) => void) => {
- const wrapped = (...args: any[]) => {
- try {
- f(...args);
- } catch (err) {
- done(err);
- }
- };
- return wrapped;
- };
-};
diff --git a/test/utils/rpc.ts b/test/utils/rpc.ts
deleted file mode 100644
index 299e72e79..000000000
--- a/test/utils/rpc.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import * as ethUtil from 'ethereumjs-util';
-import * as request from 'request-promise-native';
-import {constants} from './constants';
-
-export class RPC {
- private host: string;
- private port: number;
- private id: number;
- constructor() {
- this.host = constants.RPC_HOST;
- this.port = constants.RPC_PORT;
- this.id = 0;
- }
- public async takeSnapshotAsync(): Promise<number> {
- const method = 'evm_snapshot';
- const params: any[] = [];
- const payload = this.toPayload(method, params);
- const snapshotIdHex = await this.sendAsync(payload);
- const snapshotId = ethUtil.bufferToInt(ethUtil.toBuffer(snapshotIdHex));
- return snapshotId;
- }
- public async revertSnapshotAsync(snapshotId: number): Promise<boolean> {
- const method = 'evm_revert';
- const params = [snapshotId];
- const payload = this.toPayload(method, params);
- const didRevert = await this.sendAsync(payload);
- return didRevert;
- }
- public async mineBlockAsync(): Promise<void> {
- const method = 'evm_mine';
- const params: any[] = [];
- const payload = this.toPayload(method, params);
- await this.sendAsync(payload);
- }
- private toPayload(method: string, params: any[] = []): string {
- const payload = JSON.stringify({
- id: this.id,
- method,
- params,
- });
- this.id += 1;
- return payload;
- }
- private async sendAsync(payload: string): Promise<any> {
- const opts = {
- method: 'POST',
- uri: `http://${this.host}:${this.port}`,
- body: payload,
- headers: {
- 'content-type': 'application/json',
- },
- };
- const bodyString = await request(opts);
- const body = JSON.parse(bodyString);
- return body.result;
- }
-}
diff --git a/test/utils/token_utils.ts b/test/utils/token_utils.ts
deleted file mode 100644
index 51cb9411c..000000000
--- a/test/utils/token_utils.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import * as _ from 'lodash';
-import {Token, InternalZeroExError} from '../../src/types';
-
-const PROTOCOL_TOKEN_SYMBOL = 'ZRX';
-
-export class TokenUtils {
- private tokens: Token[];
- constructor(tokens: Token[]) {
- this.tokens = tokens;
- }
- public getProtocolTokenOrThrow(): Token {
- const zrxToken = _.find(this.tokens, {symbol: PROTOCOL_TOKEN_SYMBOL});
- if (_.isUndefined(zrxToken)) {
- throw new Error(InternalZeroExError.ZrxNotInTokenRegistry);
- }
- return zrxToken;
- }
- public getNonProtocolTokens(): Token[] {
- const nonProtocolTokens = _.filter(this.tokens, token => {
- return token.symbol !== PROTOCOL_TOKEN_SYMBOL;
- });
- return nonProtocolTokens;
- }
-}
diff --git a/test/utils/web3_factory.ts b/test/utils/web3_factory.ts
deleted file mode 100644
index b20070c74..000000000
--- a/test/utils/web3_factory.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-// HACK: web3 injects XMLHttpRequest into the global scope and ProviderEngine checks XMLHttpRequest
-// to know whether it is running in a browser or node environment. We need it to be undefined since
-// we are not running in a browser env.
-// Filed issue: https://github.com/ethereum/web3.js/issues/844
-(global as any).XMLHttpRequest = undefined;
-import ProviderEngine = require('web3-provider-engine');
-import RpcSubprovider = require('web3-provider-engine/subproviders/rpc');
-import * as Web3 from 'web3';
-import {constants} from './constants';
-import {EmptyWalletSubProvider} from '../../src/subproviders/empty_wallet_subprovider';
-
-export const web3Factory = {
- create(hasAddresses: boolean = true): Web3 {
- const provider = this.getRpcProvider(hasAddresses);
- const web3 = new Web3();
- web3.setProvider(provider);
- return web3;
- },
- getRpcProvider(hasAddresses: boolean = true): Web3.Provider {
- const provider = new ProviderEngine();
- const rpcUrl = `http://${constants.RPC_HOST}:${constants.RPC_PORT}`;
- if (!hasAddresses) {
- provider.addProvider(new EmptyWalletSubProvider());
- }
- provider.addProvider(new RpcSubprovider({
- rpcUrl,
- }));
- provider.start();
- return provider;
- },
-};
diff --git a/test/web3_wrapper_test.ts b/test/web3_wrapper_test.ts
deleted file mode 100644
index d1c2e8e89..000000000
--- a/test/web3_wrapper_test.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import * as chai from 'chai';
-import {web3Factory} from './utils/web3_factory';
-import {ZeroEx} from '../src/';
-import {Web3Wrapper} from '../src/web3_wrapper';
-import {constants} from './utils/constants';
-
-chai.config.includeStack = true;
-const expect = chai.expect;
-
-describe('Web3Wrapper', () => {
- const web3Provider = web3Factory.create().currentProvider;
- describe('#getNetworkIdIfExistsAsync', () => {
- it('caches network id requests', async () => {
- const web3Wrapper = (new ZeroEx(web3Provider) as any)._web3Wrapper as Web3Wrapper;
- expect((web3Wrapper as any).networkIdIfExists).to.be.undefined();
- const networkIdIfExists = await web3Wrapper.getNetworkIdIfExistsAsync();
- expect((web3Wrapper as any).networkIdIfExists).to.be.equal(constants.TESTRPC_NETWORK_ID);
- });
- it('invalidates network id cache on setProvider call', async () => {
- const web3Wrapper = (new ZeroEx(web3Provider) as any)._web3Wrapper as Web3Wrapper;
- expect((web3Wrapper as any).networkIdIfExists).to.be.undefined();
- const networkIdIfExists = await web3Wrapper.getNetworkIdIfExistsAsync();
- expect((web3Wrapper as any).networkIdIfExists).to.be.equal(constants.TESTRPC_NETWORK_ID);
- const newProvider = web3Factory.create().currentProvider;
- web3Wrapper.setProvider(newProvider);
- expect((web3Wrapper as any).networkIdIfExists).to.be.undefined();
- });
- });
-});