268 lines
13 KiB
TypeScript
268 lines
13 KiB
TypeScript
import { BigNumber } from '@0x/utils';
|
|
import * as chai from 'chai';
|
|
import 'mocha';
|
|
|
|
import { marketUtils } from '../src';
|
|
import { constants } from '../src/constants';
|
|
|
|
import { chaiSetup } from './utils/chai_setup';
|
|
import { testOrderFactory } from './utils/test_order_factory';
|
|
|
|
chaiSetup.configure();
|
|
const expect = chai.expect;
|
|
|
|
// tslint:disable: no-unused-expression
|
|
describe('marketUtils', () => {
|
|
describe('#findOrdersThatCoverMakerAssetFillAmount', () => {
|
|
describe('no orders', () => {
|
|
it('returns empty and unchanged remainingFillAmount', async () => {
|
|
const fillAmount = new BigNumber(10);
|
|
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
|
|
[],
|
|
fillAmount,
|
|
);
|
|
expect(resultOrders).to.be.empty;
|
|
expect(remainingFillAmount).to.be.bignumber.equal(fillAmount);
|
|
});
|
|
});
|
|
describe('orders are completely fillable', () => {
|
|
// generate three signed orders each with 10 units of makerAsset, 30 total
|
|
const makerAssetAmount = new BigNumber(10);
|
|
const inputOrders = testOrderFactory.generateTestSignedOrders(
|
|
{
|
|
makerAssetAmount,
|
|
},
|
|
3,
|
|
);
|
|
it('returns input orders and zero remainingFillAmount when input exactly matches requested fill amount', async () => {
|
|
// try to fill 20 units of makerAsset
|
|
// include 10 units of slippageBufferAmount
|
|
const fillAmount = new BigNumber(20);
|
|
const slippageBufferAmount = new BigNumber(10);
|
|
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 () => {
|
|
// try to fill 15 units of makerAsset
|
|
// include 10 units of slippageBufferAmount
|
|
const fillAmount = new BigNumber(15);
|
|
const slippageBufferAmount = new BigNumber(10);
|
|
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 () => {
|
|
// try to fill 30 units of makerAsset
|
|
// include 5 units of slippageBufferAmount
|
|
const fillAmount = new BigNumber(30);
|
|
const slippageBufferAmount = new BigNumber(5);
|
|
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
|
|
inputOrders,
|
|
fillAmount,
|
|
{
|
|
slippageBufferAmount,
|
|
},
|
|
);
|
|
expect(resultOrders).to.be.deep.equal(inputOrders);
|
|
expect(remainingFillAmount).to.be.bignumber.equal(new BigNumber(5));
|
|
});
|
|
it('returns first order and zero remainingFillAmount when requested fill amount is exactly covered by the first order', async () => {
|
|
// try to fill 10 units of makerAsset
|
|
const fillAmount = new BigNumber(10);
|
|
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 () => {
|
|
// try to fill 15 units of makerAsset
|
|
const fillAmount = new BigNumber(15);
|
|
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 partially fillable', () => {
|
|
// generate three signed orders each with 10 units of makerAsset, 30 total
|
|
const makerAssetAmount = new BigNumber(10);
|
|
const inputOrders = testOrderFactory.generateTestSignedOrders(
|
|
{
|
|
makerAssetAmount,
|
|
},
|
|
3,
|
|
);
|
|
// generate remainingFillableMakerAssetAmounts that cover different partial fill scenarios
|
|
// 1. order is completely filled already
|
|
// 2. order is partially fillable
|
|
// 3. order is completely fillable
|
|
const remainingFillableMakerAssetAmounts = [constants.ZERO_AMOUNT, new BigNumber(5), makerAssetAmount];
|
|
it('returns last two orders and non-zero remainingFillAmount when trying to fill original makerAssetAmounts', async () => {
|
|
// try to fill 30 units of makerAsset
|
|
const fillAmount = new BigNumber(30);
|
|
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
|
|
inputOrders,
|
|
fillAmount,
|
|
{
|
|
remainingFillableMakerAssetAmounts,
|
|
},
|
|
);
|
|
expect(resultOrders).to.be.deep.equal([inputOrders[1], inputOrders[2]]);
|
|
expect(remainingFillAmount).to.be.bignumber.equal(new BigNumber(15));
|
|
});
|
|
});
|
|
});
|
|
describe('#findFeeOrdersThatCoverFeesForTargetOrders', () => {
|
|
// generate three signed fee orders each with 10 units of ZRX, 30 total
|
|
const zrxAmount = new BigNumber(10);
|
|
const inputFeeOrders = testOrderFactory.generateTestSignedOrders(
|
|
{
|
|
makerAssetAmount: zrxAmount,
|
|
},
|
|
3,
|
|
);
|
|
describe('no target orders', () => {
|
|
it('returns empty and zero remainingFeeAmount', async () => {
|
|
const { resultFeeOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
|
|
[],
|
|
inputFeeOrders,
|
|
);
|
|
expect(resultFeeOrders).to.be.empty;
|
|
expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
|
});
|
|
});
|
|
describe('no fee orders', () => {
|
|
// generate three signed orders each with 10 units of makerAsset, 30 total
|
|
// each signed order requires 10 units of takerFee
|
|
const makerAssetAmount = new BigNumber(10);
|
|
const takerFee = new BigNumber(10);
|
|
const inputOrders = testOrderFactory.generateTestSignedOrders(
|
|
{
|
|
makerAssetAmount,
|
|
takerFee,
|
|
},
|
|
3,
|
|
);
|
|
// generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount
|
|
const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount];
|
|
it('returns empty and non-zero remainingFeeAmount', async () => {
|
|
const { resultFeeOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
|
|
inputOrders,
|
|
[],
|
|
{
|
|
remainingFillableMakerAssetAmounts,
|
|
},
|
|
);
|
|
expect(resultFeeOrders).to.be.empty;
|
|
expect(remainingFeeAmount).to.be.bignumber.equal(new BigNumber(30));
|
|
});
|
|
});
|
|
describe('target orders have no fees', () => {
|
|
// generate three signed orders each with 10 units of makerAsset, 30 total
|
|
const makerAssetAmount = new BigNumber(10);
|
|
const inputOrders = testOrderFactory.generateTestSignedOrders(
|
|
{
|
|
makerAssetAmount,
|
|
},
|
|
3,
|
|
);
|
|
it('returns empty and zero remainingFeeAmount', async () => {
|
|
const { resultFeeOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
|
|
inputOrders,
|
|
inputFeeOrders,
|
|
);
|
|
expect(resultFeeOrders).to.be.empty;
|
|
expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
|
});
|
|
});
|
|
describe('target orders require fees and are completely fillable', () => {
|
|
// generate three signed orders each with 10 units of makerAsset, 30 total
|
|
// each signed order requires 10 units of takerFee
|
|
const makerAssetAmount = new BigNumber(10);
|
|
const takerFee = new BigNumber(10);
|
|
const inputOrders = testOrderFactory.generateTestSignedOrders(
|
|
{
|
|
makerAssetAmount,
|
|
takerFee,
|
|
},
|
|
3,
|
|
);
|
|
it('returns input fee orders and zero remainingFeeAmount', async () => {
|
|
const { resultFeeOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
|
|
inputOrders,
|
|
inputFeeOrders,
|
|
);
|
|
expect(resultFeeOrders).to.be.deep.equal(inputFeeOrders);
|
|
expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
|
});
|
|
});
|
|
describe('target orders require fees and are partially fillable', () => {
|
|
// generate three signed orders each with 10 units of makerAsset, 30 total
|
|
// each signed order requires 10 units of takerFee
|
|
const makerAssetAmount = new BigNumber(10);
|
|
const takerFee = new BigNumber(10);
|
|
const inputOrders = testOrderFactory.generateTestSignedOrders(
|
|
{
|
|
makerAssetAmount,
|
|
takerFee,
|
|
},
|
|
3,
|
|
);
|
|
// generate remainingFillableMakerAssetAmounts that cover different partial fill scenarios
|
|
// 1. order is completely filled already
|
|
// 2. order is partially fillable
|
|
// 3. order is completely fillable
|
|
const remainingFillableMakerAssetAmounts = [constants.ZERO_AMOUNT, new BigNumber(5), makerAssetAmount];
|
|
it('returns first two input fee orders and zero remainingFeeAmount', async () => {
|
|
const { resultFeeOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
|
|
inputOrders,
|
|
inputFeeOrders,
|
|
{
|
|
remainingFillableMakerAssetAmounts,
|
|
},
|
|
);
|
|
expect(resultFeeOrders).to.be.deep.equal([inputFeeOrders[0], inputFeeOrders[1]]);
|
|
expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
|
});
|
|
});
|
|
describe('target orders require more fees than available', () => {
|
|
// generate three signed orders each with 10 units of makerAsset, 30 total
|
|
// each signed order requires 20 units of takerFee
|
|
const makerAssetAmount = new BigNumber(10);
|
|
const takerFee = new BigNumber(20);
|
|
const inputOrders = testOrderFactory.generateTestSignedOrders(
|
|
{
|
|
makerAssetAmount,
|
|
takerFee,
|
|
},
|
|
3,
|
|
);
|
|
it('returns input fee orders and non-zero remainingFeeAmount', async () => {
|
|
const { resultFeeOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
|
|
inputOrders,
|
|
inputFeeOrders,
|
|
);
|
|
expect(resultFeeOrders).to.be.deep.equal(inputFeeOrders);
|
|
expect(remainingFeeAmount).to.be.bignumber.equal(new BigNumber(30));
|
|
});
|
|
});
|
|
});
|
|
});
|