aboutsummaryrefslogblamecommitdiffstats
path: root/packages/order-utils/test/market_utils_test.ts
blob: 42ea195bb850f79dafcf5007d9e9327fb3f685db (plain) (tree)
1
2
3
4
5
6
                                      
                             

               

                                             







                                                              
                               
                                                                




                                                                                                                  





                                                                              
                                                          
                                                                                      




                                                                          
                  
              
                                                                                                                                  



                                                               

                                                                                                                  
                               
                     

                                             




                                                                                                                                



                                                               

                                                                                                                  
                               
                     

                                             




                                                                                                                                    



                                                              

                                                                                                                  
                               
                     

                                             








                                                                                                                                                 









                                                                                                                                                       







                                                                                         




                                                                          
                  
              
                                                                                                      


                                                    
                                                                                                                   
                                                                                                                                       



                                                                                                                  
                               


                                                           





                                                                                        








                                                                               

                                                                         
                                                                                                                      
                       
                                   
                  
                                                    

















                                                                                                              
                                                                                                                      
                                
                       


                                                           
                  
                                                    











                                                                                      
                                                                         
                                                                                                                      
                                
                                   
                  
                                                    














                                                                                        
                                                                                    
                                                                                                                      
                                
                                   
                  
                                                                         




















                                                                                                                   
                                                                                                                      
                                
                                   

                                                           
                      
                  
                                                                                                 














                                                                                        
                                                                                        
                                                                                                                      
                                
                                   
                  
                                                                         



                                                                                    
   
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));
            });
        });
    });
});