protocol/packages/asset-swapper/test/market_utils_test.ts

375 lines
21 KiB
TypeScript

import * as chai from 'chai';
import * as _ from 'lodash';
import 'mocha';
import { constants } from '../src/constants';
import { marketUtils } from '../src/utils/market_utils';
import { chaiSetup } from './utils/chai_setup';
import { testOrders } from './utils/test_orders';
import { baseUnitAmount } from './utils/utils';
chaiSetup.configure();
const expect = chai.expect;
// tslint:disable:custom-no-magic-numbers
// tslint:disable: no-unused-expression
describe('marketUtils', () => {
describe('#findOrdersThatCoverTakerAssetFillAmount', () => {
describe('no orders', () => {
it('returns empty and unchanged remainingFillAmount', async () => {
const fillAmount = baseUnitAmount(9);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
[],
fillAmount,
);
expect(resultOrders).to.be.empty;
expect(remainingFillAmount).to.be.bignumber.equal(fillAmount);
});
});
describe('orders do not have fees', () => {
const inputOrders = testOrders.PRUNED_SIGNED_ORDERS_FEELESS;
it('returns input orders and zero remainingFillAmount when input exactly matches requested fill amount', async () => {
const fillAmount = baseUnitAmount(5);
const slippageBufferAmount = baseUnitAmount(4);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
inputOrders,
fillAmount,
slippageBufferAmount,
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
it('returns input orders and zero remainingFillAmount when input has more than requested fill amount', async () => {
const fillAmount = baseUnitAmount(6);
const slippageBufferAmount = baseUnitAmount(3);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
inputOrders,
fillAmount,
slippageBufferAmount,
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
it('returns input orders and non-zero remainingFillAmount when input has less than requested fill amount', async () => {
const fillAmount = baseUnitAmount(10);
const slippageBufferAmount = baseUnitAmount(2);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
inputOrders,
fillAmount,
slippageBufferAmount,
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(baseUnitAmount(3));
});
it('returns first order and zero remainingFillAmount when requested fill amount is exactly covered by the first order', async () => {
const fillAmount = baseUnitAmount(1);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
inputOrders,
fillAmount,
);
expect(resultOrders).to.be.deep.equal([inputOrders[0]]);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
it('returns first two orders and zero remainingFillAmount when requested fill amount is over covered by the first two order', async () => {
const fillAmount = baseUnitAmount(6);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
inputOrders,
fillAmount,
);
expect(resultOrders).to.be.deep.equal([inputOrders[0], inputOrders[1]]);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
});
describe('orders have fees in takerAsset', () => {
const inputOrders = testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET;
it('returns input orders and zero remainingFillAmount when input exactly matches requested fill amount', async () => {
const fillAmount = baseUnitAmount(10);
const slippageBufferAmount = baseUnitAmount(5);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
inputOrders,
fillAmount,
slippageBufferAmount,
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
it('returns input orders and zero remainingFillAmount when input has more than requested fill amount', async () => {
const fillAmount = baseUnitAmount(6);
const slippageBufferAmount = baseUnitAmount(6);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
inputOrders,
fillAmount,
slippageBufferAmount,
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
it('returns input orders and non-zero remainingFillAmount when input has less than requested fill amount', async () => {
const fillAmount = baseUnitAmount(10);
const slippageBufferAmount = baseUnitAmount(6);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
inputOrders,
fillAmount,
slippageBufferAmount,
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(baseUnitAmount(1));
});
it('returns first order and zero remainingFillAmount when requested fill amount is exactly covered by the first order', async () => {
const fillAmount = baseUnitAmount(4);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
inputOrders,
fillAmount,
);
expect(resultOrders).to.be.deep.equal([inputOrders[0]]);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
it('returns first two orders and zero remainingFillAmount when requested fill amount is over covered by the first two order', async () => {
const fillAmount = baseUnitAmount(9);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
inputOrders,
fillAmount,
);
expect(resultOrders).to.be.deep.equal([inputOrders[0], inputOrders[1]]);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
});
describe('orders are feeless or have fees in takerAsset', () => {
const inputOrders = _.concat(
testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET,
testOrders.PRUNED_SIGNED_ORDERS_FEELESS,
);
it('returns input orders and zero remainingFillAmount when input exactly matches requested fill amount', async () => {
const fillAmount = baseUnitAmount(20);
const slippageBufferAmount = baseUnitAmount(4);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
inputOrders,
fillAmount,
slippageBufferAmount,
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
it('returns input orders and zero remainingFillAmount when input has more than requested fill amount', async () => {
const fillAmount = baseUnitAmount(10);
const slippageBufferAmount = baseUnitAmount(12);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
inputOrders,
fillAmount,
slippageBufferAmount,
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
it('returns input orders and non-zero remainingFillAmount when input has less than requested fill amount', async () => {
const fillAmount = baseUnitAmount(20);
const slippageBufferAmount = baseUnitAmount(6);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
inputOrders,
fillAmount,
slippageBufferAmount,
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(baseUnitAmount(2));
});
it('returns first order and zero remainingFillAmount when requested fill amount is exactly covered by the first order', async () => {
const fillAmount = baseUnitAmount(4);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
inputOrders,
fillAmount,
);
expect(resultOrders).to.be.deep.equal([inputOrders[0]]);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
it('returns first four orders and zero remainingFillAmount when requested fill amount is over covered by the first two order', async () => {
const fillAmount = baseUnitAmount(16);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
inputOrders,
fillAmount,
);
expect(resultOrders).to.be.deep.equal([inputOrders[0], inputOrders[1], inputOrders[2], inputOrders[3]]);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
});
});
describe('#findOrdersThatCoverMakerAssetFillAmount', () => {
describe('no orders', () => {
it('returns empty and unchanged remainingFillAmount', async () => {
const fillAmount = baseUnitAmount(9);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
[],
fillAmount,
);
expect(resultOrders).to.be.empty;
expect(remainingFillAmount).to.be.bignumber.equal(fillAmount);
});
});
describe('orders do not have fees', () => {
const inputOrders = testOrders.PRUNED_SIGNED_ORDERS_FEELESS;
it('returns input orders and zero remainingFillAmount when input exactly matches requested fill amount', async () => {
const fillAmount = baseUnitAmount(6);
const slippageBufferAmount = baseUnitAmount(4);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
fillAmount,
slippageBufferAmount,
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
it('returns input orders and zero remainingFillAmount when input has more than requested fill amount', async () => {
const fillAmount = baseUnitAmount(6);
const slippageBufferAmount = baseUnitAmount(3);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
fillAmount,
slippageBufferAmount,
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
it('returns input orders and non-zero remainingFillAmount when input has less than requested fill amount', async () => {
const fillAmount = baseUnitAmount(10);
const slippageBufferAmount = baseUnitAmount(2);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
fillAmount,
slippageBufferAmount,
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(baseUnitAmount(2));
});
it('returns first order and zero remainingFillAmount when requested fill amount is exactly covered by the first order', async () => {
const fillAmount = baseUnitAmount(6);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
fillAmount,
);
expect(resultOrders).to.be.deep.equal([inputOrders[0]]);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
it('returns first two orders and zero remainingFillAmount when requested fill amount is over covered by the first two order', async () => {
const fillAmount = baseUnitAmount(8);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
fillAmount,
);
expect(resultOrders).to.be.deep.equal([inputOrders[0], inputOrders[1]]);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
});
describe('orders have fees in makerAsset', () => {
const inputOrders = testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET;
it('returns input orders and zero remainingFillAmount when input exactly matches requested fill amount', async () => {
const fillAmount = baseUnitAmount(2);
const slippageBufferAmount = baseUnitAmount(3);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
fillAmount,
slippageBufferAmount,
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
it('returns input orders and zero remainingFillAmount when input has more than requested fill amount', async () => {
const fillAmount = baseUnitAmount(4);
const slippageBufferAmount = baseUnitAmount(0.5);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
fillAmount,
slippageBufferAmount,
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
it('returns input orders and non-zero remainingFillAmount when input has less than requested fill amount', async () => {
const fillAmount = baseUnitAmount(3);
const slippageBufferAmount = baseUnitAmount(3);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
fillAmount,
slippageBufferAmount,
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(baseUnitAmount(1));
});
it('returns first order and zero remainingFillAmount when requested fill amount is exactly covered by the first order', async () => {
const fillAmount = baseUnitAmount(1);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
fillAmount,
);
expect(resultOrders).to.be.deep.equal([inputOrders[0]]);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
it('returns first two orders and zero remainingFillAmount when requested fill amount is over covered by the first two order', async () => {
const fillAmount = baseUnitAmount(2);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
fillAmount,
);
expect(resultOrders).to.be.deep.equal([inputOrders[0], inputOrders[1]]);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
});
describe('orders are feeless or have fees in makerAsset', () => {
const inputOrders = _.concat(
testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET,
testOrders.PRUNED_SIGNED_ORDERS_FEELESS,
);
it('returns input orders and zero remainingFillAmount when input exactly matches requested fill amount', async () => {
const fillAmount = baseUnitAmount(12);
const slippageBufferAmount = baseUnitAmount(3);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
fillAmount,
slippageBufferAmount,
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
it('returns input orders and zero remainingFillAmount when input has more than requested fill amount', async () => {
const fillAmount = baseUnitAmount(12);
const slippageBufferAmount = baseUnitAmount(2);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
fillAmount,
slippageBufferAmount,
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
it('returns input orders and non-zero remainingFillAmount when input has less than requested fill amount', async () => {
const fillAmount = baseUnitAmount(14);
const slippageBufferAmount = baseUnitAmount(4);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
fillAmount,
slippageBufferAmount,
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(baseUnitAmount(3));
});
it('returns first order and zero remainingFillAmount when requested fill amount is exactly covered by the first order', async () => {
const fillAmount = baseUnitAmount(1);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
fillAmount,
);
expect(resultOrders).to.be.deep.equal([inputOrders[0]]);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
it('returns first four orders and zero remainingFillAmount when requested fill amount is over covered by the first two order', async () => {
const fillAmount = baseUnitAmount(11);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
fillAmount,
);
expect(resultOrders).to.be.deep.equal([inputOrders[0], inputOrders[1], inputOrders[2], inputOrders[3]]);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
});
});
});