* development: (187 commits) Remove trailing slash Fix linter Stop nesting interfaces and add necessary type exports Remove duplicate type and remove nested interface Add support for rending the Tuple type Add missing keyu Remove excessive timestamp Improve doc commebnt Remove docs catch-all endpoint Fix comments Look for all TS mapped types Add catch and exit with non-zero Remove superfluous dep Fix CHANGELOG entry Fix double assignment Upgrade Typedoc to 0.12.0, which works with TS 3.x Fix prettier issues Enable dry run of release publishing and handle git tags existing update yarn.lock Missing/superfluous type exports from connect ...
268 lines
13 KiB
TypeScript
268 lines
13 KiB
TypeScript
import { BigNumber } from '@0xproject/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));
|
|
});
|
|
});
|
|
});
|
|
});
|