aboutsummaryrefslogtreecommitdiffstats
path: root/packages/0x.js/test
diff options
context:
space:
mode:
Diffstat (limited to 'packages/0x.js/test')
-rw-r--r--packages/0x.js/test/order_state_watcher_test.ts114
-rw-r--r--packages/0x.js/test/remaining_fillable_calculator_test.ts176
-rw-r--r--packages/0x.js/test/utils/constants.ts1
3 files changed, 276 insertions, 15 deletions
diff --git a/packages/0x.js/test/order_state_watcher_test.ts b/packages/0x.js/test/order_state_watcher_test.ts
index 00b290252..ab6174f71 100644
--- a/packages/0x.js/test/order_state_watcher_test.ts
+++ b/packages/0x.js/test/order_state_watcher_test.ts
@@ -3,10 +3,10 @@ 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 {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,
@@ -20,11 +20,12 @@ import {
OrderStateInvalid,
ExchangeContractErrs,
} from '../src';
-import { TokenUtils } from './utils/token_utils';
-import { FillScenarios } from './utils/fill_scenarios';
-import { DoneCallback } from '../src/types';
+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';
+import { constants as constants } from './utils/constants';
const TIMEOUT_MS = 150;
@@ -47,7 +48,8 @@ describe('OrderStateWatcher', () => {
let taker: string;
let web3Wrapper: Web3Wrapper;
let signedOrder: SignedOrder;
- const fillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(5), 18);
+ const decimals = constants.ZRX_DECIMALS;
+ const fillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals);
before(async () => {
web3 = web3Factory.create();
zeroEx = new ZeroEx(web3.currentProvider);
@@ -254,15 +256,15 @@ describe('OrderStateWatcher', () => {
describe('remainingFillable(M|T)akerTokenAmount', () => {
it('should calculate correct remaining fillable', (done: DoneCallback) => {
(async () => {
- const takerFillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(10), 18);
- const makerFillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(20), 18);
+ const takerFillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(10), decimals);
+ const makerFillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(20), decimals);
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 = ZeroEx.toBaseUnitAmount(new BigNumber(2), 18);
+ const fillAmountInBaseUnits = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
await zeroEx.orderStateWatcher.addOrderAsync(signedOrder);
let eventCount = 0;
@@ -273,9 +275,9 @@ describe('OrderStateWatcher', () => {
expect(validOrderState.orderHash).to.be.equal(orderHash);
const orderRelevantState = validOrderState.orderRelevantState;
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
- ZeroEx.toBaseUnitAmount(new BigNumber(16), 18));
+ ZeroEx.toBaseUnitAmount(new BigNumber(16), decimals));
expect(orderRelevantState.remainingFillableTakerTokenAmount).to.be.bignumber.equal(
- ZeroEx.toBaseUnitAmount(new BigNumber(8), 18));
+ ZeroEx.toBaseUnitAmount(new BigNumber(8), decimals));
if (eventCount === 2) {
done();
}
@@ -295,7 +297,7 @@ describe('OrderStateWatcher', () => {
const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
- const changedMakerApprovalAmount = ZeroEx.toBaseUnitAmount(new BigNumber(3), 18);
+ const changedMakerApprovalAmount = ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals);
await zeroEx.orderStateWatcher.addOrderAsync(signedOrder);
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
@@ -319,7 +321,7 @@ describe('OrderStateWatcher', () => {
const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
- const remainingAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), 18);
+ const remainingAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals);
const transferAmount = makerBalance.sub(remainingAmount);
await zeroEx.orderStateWatcher.addOrderAsync(signedOrder);
@@ -337,6 +339,88 @@ describe('OrderStateWatcher', () => {
makerToken.address, maker, ZeroEx.NULL_ADDRESS, transferAmount);
})().catch(done);
});
+ it('should equal remaining amount when partially cancelled and order has fees', (done: DoneCallback) => {
+ (async () => {
+ const takerFee = ZeroEx.toBaseUnitAmount(new BigNumber(0), decimals);
+ const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals);
+ const feeRecipient = taker;
+ signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
+ makerToken.address, takerToken.address, makerFee, takerFee, maker,
+ taker, fillableAmount, feeRecipient);
+
+ const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
+
+ const remainingTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(4), decimals);
+ const transferTokenAmount = makerFee.sub(remainingTokenAmount);
+ zeroEx.orderStateWatcher.addOrder(signedOrder);
+
+ const callback = reportCallbackErrors(done)((orderState: OrderState) => {
+ expect(orderState.isValid).to.be.true();
+ const validOrderState = orderState as OrderStateValid;
+ const orderRelevantState = validOrderState.orderRelevantState;
+ expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
+ remainingTokenAmount);
+ done();
+ });
+ zeroEx.orderStateWatcher.subscribe(callback);
+ await zeroEx.exchange.cancelOrderAsync(signedOrder, transferTokenAmount);
+ })().catch(done);
+ });
+ it('should equal ratio amount when fee balance is lowered', (done: DoneCallback) => {
+ (async () => {
+ const takerFee = ZeroEx.toBaseUnitAmount(new BigNumber(0), decimals);
+ const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals);
+ const feeRecipient = taker;
+ signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
+ makerToken.address, takerToken.address, makerFee, takerFee, maker,
+ taker, fillableAmount, feeRecipient);
+
+ const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
+
+ const remainingFeeAmount = ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals);
+ const transferFeeAmount = makerFee.sub(remainingFeeAmount);
+
+ const remainingTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(4), decimals);
+ const transferTokenAmount = makerFee.sub(remainingTokenAmount);
+ 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(
+ remainingFeeAmount);
+ done();
+ });
+ zeroEx.orderStateWatcher.subscribe(callback);
+ await zeroEx.token.setProxyAllowanceAsync(zrxTokenAddress, maker, remainingFeeAmount);
+ await zeroEx.token.transferAsync(
+ makerToken.address, maker, ZeroEx.NULL_ADDRESS, transferTokenAmount);
+ })().catch(done);
+ });
+ it('should calculate full amount when all available and non-divisible', (done: DoneCallback) => {
+ (async () => {
+ const takerFee = ZeroEx.toBaseUnitAmount(new BigNumber(0), decimals);
+ const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
+ const feeRecipient = taker;
+ signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
+ makerToken.address, takerToken.address, makerFee, takerFee, maker,
+ taker, fillableAmount, feeRecipient);
+
+ const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
+ 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(
+ fillableAmount);
+ done();
+ });
+ zeroEx.orderStateWatcher.subscribe(callback);
+ await zeroEx.token.setProxyAllowanceAsync(
+ makerToken.address, maker, ZeroEx.toBaseUnitAmount(new BigNumber(100), decimals));
+ })().catch(done);
+ });
});
it('should emit orderStateInvalid when watched order cancelled', (done: DoneCallback) => {
(async () => {
diff --git a/packages/0x.js/test/remaining_fillable_calculator_test.ts b/packages/0x.js/test/remaining_fillable_calculator_test.ts
new file mode 100644
index 000000000..65b65efd8
--- /dev/null
+++ b/packages/0x.js/test/remaining_fillable_calculator_test.ts
@@ -0,0 +1,176 @@
+import 'mocha';
+import * as chai from 'chai';
+import BigNumber from 'bignumber.js';
+import { chaiSetup } from './utils/chai_setup';
+import { RemainingFillableCalculator } from '../src/order_watcher/remaining_fillable_calculator';
+import { SignedOrder, ECSignature } from '../src/types';
+import { TokenUtils } from './utils/token_utils';
+import { ZeroEx } from '../src/0x';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+describe('RemainingFillableCalculator', () => {
+ let calculator: RemainingFillableCalculator;
+ let signedOrder: SignedOrder;
+ let transferrableMakerTokenAmount: BigNumber;
+ let transferrableMakerFeeTokenAmount: BigNumber;
+ let remainingMakerTokenAmount: BigNumber;
+ let makerAmount: BigNumber;
+ let takerAmount: BigNumber;
+ let makerFeeAmount: BigNumber;
+ let isMakerTokenZRX: boolean;
+ const makerToken: string = '0x1';
+ const takerToken: string = '0x2';
+ const decimals: number = 4;
+ const zero: BigNumber = new BigNumber(0);
+ const zeroAddress = '0x0';
+ const signature: ECSignature = { v: 27, r: '', s: ''};
+ beforeEach(async () => {
+ [makerAmount, takerAmount, makerFeeAmount] = [ZeroEx.toBaseUnitAmount(new BigNumber(50), decimals),
+ ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals),
+ ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals)];
+ [transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount] = [
+ ZeroEx.toBaseUnitAmount(new BigNumber(50), decimals),
+ ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals)];
+ });
+ function buildSignedOrder(): SignedOrder {
+ return { ecSignature: signature,
+ exchangeContractAddress: zeroAddress,
+ feeRecipient: zeroAddress,
+ maker: zeroAddress,
+ taker: zeroAddress,
+ makerFee: makerFeeAmount,
+ takerFee: zero,
+ makerTokenAmount: makerAmount,
+ takerTokenAmount: takerAmount,
+ makerTokenAddress: makerToken,
+ takerTokenAddress: takerToken,
+ salt: zero,
+ expirationUnixTimestampSec: zero };
+ }
+ describe('Maker token is NOT ZRX', () => {
+ before(async () => {
+ isMakerTokenZRX = false;
+ });
+ it('calculates the correct amount when unfilled and funds available', () => {
+ signedOrder = buildSignedOrder();
+ remainingMakerTokenAmount = signedOrder.makerTokenAmount;
+ calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
+ transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
+ expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(remainingMakerTokenAmount);
+ });
+ it('calculates the correct amount when partially filled and funds available', () => {
+ signedOrder = buildSignedOrder();
+ remainingMakerTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals);
+ calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
+ transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
+ expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(remainingMakerTokenAmount);
+ });
+ it('calculates the amount to be 0 when all fee funds are transferred', () => {
+ signedOrder = buildSignedOrder();
+ transferrableMakerFeeTokenAmount = zero;
+ remainingMakerTokenAmount = signedOrder.makerTokenAmount;
+ calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
+ transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
+ expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(zero);
+ });
+ it('calculates the correct amount when balance is less than remaining fillable', () => {
+ signedOrder = buildSignedOrder();
+ const partiallyFilledAmount = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
+ remainingMakerTokenAmount = signedOrder.makerTokenAmount.minus(partiallyFilledAmount);
+ transferrableMakerTokenAmount = remainingMakerTokenAmount.minus(partiallyFilledAmount);
+ calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
+ transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
+ expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(transferrableMakerTokenAmount);
+ });
+ describe('Order to Fee Ratio is < 1', () => {
+ beforeEach(async () => {
+ [makerAmount, takerAmount, makerFeeAmount] = [ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals),
+ ZeroEx.toBaseUnitAmount(new BigNumber(6), decimals),
+ ZeroEx.toBaseUnitAmount(new BigNumber(6), decimals)];
+ });
+ it('calculates the correct amount when funds unavailable', () => {
+ signedOrder = buildSignedOrder();
+ remainingMakerTokenAmount = signedOrder.makerTokenAmount;
+ const transferredAmount = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
+ transferrableMakerTokenAmount = remainingMakerTokenAmount.minus(transferredAmount);
+ calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
+ transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount,
+ remainingMakerTokenAmount);
+ expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(transferrableMakerTokenAmount);
+ });
+ });
+ describe('Ratio is not evenly divisble', () => {
+ beforeEach(async () => {
+ [makerAmount, takerAmount, makerFeeAmount] = [ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals),
+ ZeroEx.toBaseUnitAmount(new BigNumber(7), decimals),
+ ZeroEx.toBaseUnitAmount(new BigNumber(7), decimals)];
+ });
+ it('calculates the correct amount when funds unavailable', () => {
+ signedOrder = buildSignedOrder();
+ remainingMakerTokenAmount = signedOrder.makerTokenAmount;
+ const transferredAmount = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
+ transferrableMakerTokenAmount = remainingMakerTokenAmount.minus(transferredAmount);
+ calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
+ transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount,
+ remainingMakerTokenAmount);
+ const calculatedFillableAmount = calculator.computeRemainingMakerFillable();
+ expect(calculatedFillableAmount.lessThanOrEqualTo(transferrableMakerTokenAmount)).to.be.true();
+ expect(calculatedFillableAmount).to.be.bignumber.greaterThan(new BigNumber(0));
+ const orderToFeeRatio = signedOrder.makerTokenAmount.dividedBy(signedOrder.makerFee);
+ const calculatedFeeAmount = calculatedFillableAmount.dividedBy(orderToFeeRatio);
+ expect(calculatedFeeAmount).to.be.bignumber.lessThan(transferrableMakerFeeTokenAmount);
+ });
+ });
+ });
+ describe('Maker Token is ZRX', () => {
+ before(async () => {
+ isMakerTokenZRX = true;
+ });
+ it('calculates the correct amount when unfilled and funds available', () => {
+ signedOrder = buildSignedOrder();
+ transferrableMakerTokenAmount = makerAmount.plus(makerFeeAmount);
+ transferrableMakerFeeTokenAmount = transferrableMakerTokenAmount;
+ remainingMakerTokenAmount = signedOrder.makerTokenAmount;
+ calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
+ transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
+ expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(remainingMakerTokenAmount);
+ });
+ it('calculates the correct amount when partially filled and funds available', () => {
+ signedOrder = buildSignedOrder();
+ remainingMakerTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals);
+ calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
+ transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
+ expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(remainingMakerTokenAmount);
+ });
+ it('calculates the amount to be 0 when all fee funds are transferred', () => {
+ signedOrder = buildSignedOrder();
+ transferrableMakerTokenAmount = zero;
+ transferrableMakerFeeTokenAmount = zero;
+ remainingMakerTokenAmount = signedOrder.makerTokenAmount;
+ calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
+ transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
+ expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(zero);
+ });
+ it('calculates the correct amount when balance is less than remaining fillable', () => {
+ signedOrder = buildSignedOrder();
+ const partiallyFilledAmount = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
+ remainingMakerTokenAmount = signedOrder.makerTokenAmount.minus(partiallyFilledAmount);
+ transferrableMakerTokenAmount = remainingMakerTokenAmount.minus(partiallyFilledAmount);
+ transferrableMakerFeeTokenAmount = transferrableMakerTokenAmount;
+
+ const orderToFeeRatio = signedOrder.makerTokenAmount.dividedToIntegerBy(signedOrder.makerFee);
+ const expectedFillableAmount = new BigNumber(450980);
+ calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
+ transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
+ const calculatedFillableAmount = calculator.computeRemainingMakerFillable();
+ const numberOfFillsInRatio = calculatedFillableAmount.dividedToIntegerBy(orderToFeeRatio);
+ const calculatedFillableAmountPlusFees = calculatedFillableAmount.plus(numberOfFillsInRatio);
+ expect(calculatedFillableAmountPlusFees).to.be.bignumber.lessThan(transferrableMakerTokenAmount);
+ expect(calculatedFillableAmountPlusFees).to.be.bignumber.lessThan(remainingMakerTokenAmount);
+ expect(calculatedFillableAmount).to.be.bignumber.equal(expectedFillableAmount);
+ expect(numberOfFillsInRatio.decimalPlaces()).to.be.equal(0);
+ });
+ });
+});
diff --git a/packages/0x.js/test/utils/constants.ts b/packages/0x.js/test/utils/constants.ts
index c7d3aebca..5992c226e 100644
--- a/packages/0x.js/test/utils/constants.ts
+++ b/packages/0x.js/test/utils/constants.ts
@@ -5,4 +5,5 @@ export const constants = {
TESTRPC_NETWORK_ID: 50,
KOVAN_RPC_URL: 'https://kovan.infura.io',
ROPSTEN_RPC_URL: 'https://ropsten.infura.io',
+ ZRX_DECIMALS: 18,
};