aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/0x.js_test.ts6
-rw-r--r--test/exchange_wrapper_test.ts160
-rw-r--r--test/utils/fill_scenarios.ts20
3 files changed, 178 insertions, 8 deletions
diff --git a/test/0x.js_test.ts b/test/0x.js_test.ts
index efc703ea1..52580171b 100644
--- a/test/0x.js_test.ts
+++ b/test/0x.js_test.ts
@@ -8,7 +8,7 @@ import * as Sinon from 'sinon';
import {ZeroEx} from '../src/0x.js';
import {constants} from './utils/constants';
import {web3Factory} from './utils/web3_factory';
-import {Order} from '../src/types';
+import {Order, DoneCallback} from '../src/types';
chai.use(ChaiBigNumber());
chai.use(dirtyChai);
@@ -16,7 +16,7 @@ const expect = chai.expect;
describe('ZeroEx library', () => {
describe('#setProvider', () => {
- it('overrides the provider in the nested web3 instance and invalidates contractInstances', async () => {
+ it('overrides provider in nested web3s and invalidates contractInstances', async () => {
const web3 = web3Factory.create();
const zeroEx = new ZeroEx(web3);
// Instantiate the contract instances with the current provider
@@ -28,7 +28,7 @@ describe('ZeroEx library', () => {
const newProvider = web3Factory.getRpcProvider();
// Add property to newProvider so that we can differentiate it from old provider
(newProvider as any).zeroExTestId = 1;
- zeroEx.setProvider(newProvider);
+ await zeroEx.setProviderAsync(newProvider);
// Check that contractInstances with old provider are removed after provider update
expect((zeroEx.exchange as any).exchangeContractIfExists).to.be.undefined();
diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts
index 66ba167cc..cfb75789c 100644
--- a/test/exchange_wrapper_test.ts
+++ b/test/exchange_wrapper_test.ts
@@ -10,7 +10,15 @@ import {web3Factory} from './utils/web3_factory';
import {ZeroEx} from '../src/0x.js';
import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
import {orderFactory} from './utils/order_factory';
-import {FillOrderValidationErrs, Token} from '../src/types';
+import {
+ FillOrderValidationErrs,
+ Token,
+ SignedOrder,
+ SubscriptionOpts,
+ ExchangeEvents,
+ ContractEvent,
+ DoneCallback,
+} from '../src/types';
import {FillScenarios} from './utils/fill_scenarios';
chai.use(dirtyChai);
@@ -18,14 +26,20 @@ chai.use(ChaiBigNumber());
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle();
+const NON_EXISTENT_ORDER_HASH = '0x79370342234e7acd6bbeac335bd3bb1d368383294b64b8160a00f4060e4d3777';
+
describe('ExchangeWrapper', () => {
let zeroEx: ZeroEx;
let userAddresses: string[];
let web3: Web3;
+ let tokens: Token[];
+ let fillScenarios: FillScenarios;
before(async () => {
web3 = web3Factory.create();
zeroEx = new ZeroEx(web3);
userAddresses = await promisify(web3.eth.getAccounts)();
+ tokens = await zeroEx.tokenRegistry.getTokensAsync();
+ fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens);
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
@@ -104,10 +118,8 @@ describe('ExchangeWrapper', () => {
});
});
describe('#fillOrderAsync', () => {
- let tokens: Token[];
let makerTokenAddress: string;
let takerTokenAddress: string;
- let fillScenarios: FillScenarios;
let coinBase: string;
let makerAddress: string;
let takerAddress: string;
@@ -115,11 +127,9 @@ describe('ExchangeWrapper', () => {
const shouldCheckTransfer = false;
before('fetch tokens', async () => {
[coinBase, makerAddress, takerAddress] = userAddresses;
- tokens = await zeroEx.tokenRegistry.getTokensAsync();
const [makerToken, takerToken] = tokens;
makerTokenAddress = makerToken.address;
takerTokenAddress = takerToken.address;
- fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens);
});
afterEach('reset default account', () => {
zeroEx.setTransactionSenderAccount(userAddresses[0]);
@@ -251,4 +261,144 @@ describe('ExchangeWrapper', () => {
});
});
});
+ describe('tests that require partially filled order', () => {
+ let makerTokenAddress: string;
+ let takerTokenAddress: string;
+ let takerAddress: string;
+ let fillableAmount: BigNumber.BigNumber;
+ let partialFillAmount: BigNumber.BigNumber;
+ let signedOrder: SignedOrder;
+ 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,
+ );
+ });
+ describe('#getUnavailableTakerAmountAsync', () => {
+ it ('should throw if passed an invalid orderHash', async () => {
+ const invalidOrderHashHex = '0x123';
+ 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 orderHash = await zeroEx.getOrderHashHexAsync(signedOrder);
+ 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';
+ 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 orderHash = await zeroEx.getOrderHashHexAsync(signedOrder);
+ 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';
+ 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 orderHash = await zeroEx.getOrderHashHexAsync(signedOrder);
+ const cancelledValueT = await zeroEx.exchange.getCanceledTakerAmountAsync(orderHash);
+ expect(cancelledValueT).to.be.bignumber.equal(0);
+ });
+ });
+ });
+ describe('#subscribeAsync', () => {
+ const indexFilterValues = {};
+ const shouldCheckTransfer = false;
+ let makerTokenAddress: string;
+ let takerTokenAddress: string;
+ let coinBase: string;
+ let takerAddress: string;
+ let makerAddress: string;
+ let fillableAmount: BigNumber.BigNumber;
+ let signedOrder: SignedOrder;
+ before(() => {
+ [coinBase, makerAddress, takerAddress] = userAddresses;
+ const [makerToken, takerToken] = tokens;
+ makerTokenAddress = makerToken.address;
+ takerTokenAddress = takerToken.address;
+ });
+ beforeEach(async () => {
+ fillableAmount = new BigNumber(5);
+ signedOrder = await fillScenarios.createAFillableSignedOrderAsync(
+ makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
+ );
+ });
+ afterEach(async () => {
+ (zeroEx.exchange as any).stopWatchingExchangeLogEventsAsync();
+ });
+ // 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 `subscribeAsync` 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 subscriptionOpts: SubscriptionOpts = {
+ fromBlock: 0,
+ toBlock: 'latest',
+ };
+ await zeroEx.exchange.subscribeAsync(ExchangeEvents.LogFill, subscriptionOpts,
+ indexFilterValues, (err: Error, event: ContractEvent) => {
+ expect(err).to.be.null();
+ expect(event).to.not.be.undefined();
+ done();
+ });
+ const fillTakerAmountInBaseUnits = new BigNumber(1);
+ zeroEx.setTransactionSenderAccount(takerAddress);
+ await zeroEx.exchange.fillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer);
+ })();
+ });
+ it('Outstanding subscriptions are cancelled when zeroEx.setProviderAsync called', (done: DoneCallback) => {
+ (async () => {
+ const subscriptionOpts: SubscriptionOpts = {
+ fromBlock: 0,
+ toBlock: 'latest',
+ };
+ await zeroEx.exchange.subscribeAsync(ExchangeEvents.LogFill, subscriptionOpts,
+ indexFilterValues, (err: Error, event: ContractEvent) => {
+ done(new Error('Expected this subscription to have been cancelled'));
+ });
+
+ const newProvider = web3Factory.getRpcProvider();
+ await zeroEx.setProviderAsync(newProvider);
+
+ await zeroEx.exchange.subscribeAsync(ExchangeEvents.LogFill, subscriptionOpts,
+ indexFilterValues, (err: Error, event: ContractEvent) => {
+ expect(err).to.be.null();
+ expect(event).to.not.be.undefined();
+ done();
+ });
+
+ const fillTakerAmountInBaseUnits = new BigNumber(1);
+ zeroEx.setTransactionSenderAccount(takerAddress);
+ await zeroEx.exchange.fillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer);
+ })();
+ });
+ });
});
diff --git a/test/utils/fill_scenarios.ts b/test/utils/fill_scenarios.ts
index 3b66937e6..17c2dbeba 100644
--- a/test/utils/fill_scenarios.ts
+++ b/test/utils/fill_scenarios.ts
@@ -32,4 +32,24 @@ export class FillScenarios {
this.zeroEx.setTransactionSenderAccount(transactionSenderAccount as string);
return signedOrder;
}
+ public async createPartiallyFilledSignedOrderAsync(makerTokenAddress: string, takerTokenAddress: string,
+ takerAddress: string, fillableAmount: BigNumber.BigNumber,
+ partialFillAmount: BigNumber.BigNumber) {
+ const prevSenderAccount = await this.zeroEx.getTransactionSenderAccountIfExistsAsync();
+ const [makerAddress] = this.userAddresses;
+ await this.zeroEx.token.setProxyAllowanceAsync(makerTokenAddress, makerAddress, fillableAmount);
+ await this.zeroEx.token.transferAsync(takerTokenAddress, makerAddress, takerAddress, fillableAmount);
+ await this.zeroEx.token.setProxyAllowanceAsync(takerTokenAddress, takerAddress, fillableAmount);
+
+ const signedOrder = await orderFactory.createSignedOrderAsync(this.zeroEx, makerAddress,
+ takerAddress, fillableAmount, makerTokenAddress, fillableAmount, takerTokenAddress);
+
+ this.zeroEx.setTransactionSenderAccount(takerAddress);
+ const shouldCheckTransfer = false;
+ await this.zeroEx.exchange.fillOrderAsync(signedOrder, partialFillAmount, shouldCheckTransfer);
+
+ // Re-set sender account so as to avoid introducing side-effects
+ this.zeroEx.setTransactionSenderAccount(prevSenderAccount as string);
+ return signedOrder;
+ }
}