aboutsummaryrefslogblamecommitdiffstats
path: root/packages/0x.js/test/remaining_fillable_calculator_test.ts
blob: 47ba13cd796d8bff1d938c6b0cb3414199adb6a5 (plain) (tree)
1
2
3
4
5
6
7
8
9
                                     



                                   
                                                                                                 


                                                        



                           
                                               

                                                




                                                    
                                  



                                     


                                                          
                            


                                                                                                           
                                                                             

                                                                                                     






                                                      
                                          







                                                    
                                              

                                    



                                                                                     
                                                                                      




                                                                                                                       

                                                                                            



                                                                                                                       
                                             

                                                                     
                                                                                      


                                                                                                                       

                                                                                                
                                                                                              

                                                                                                   
                                                                                      


                                                                                                                       






































                                                                                                                        




                                          

                                                                                     
                                                                             

                                                                             
                                                                                      


                                                                                                                       

                                                                                             

                                                                                            


                                                                                                                       
                                                                                      

                                                 
                                                    
                                                                     
                                                                                      


                                                                                                                       







                                                                                                          
                                                                 

                                                                                                                       
                                                                                        
                                                                                                      
                                                                                                         

                                                                                                             

                                                                                           
           

       
import BigNumber from 'bignumber.js';
import * as chai from 'chai';
import 'mocha';

import { ZeroEx } from '../src/0x';
import { RemainingFillableCalculator } from '../src/order_watcher/remaining_fillable_calculator';
import { ECSignature, SignedOrder } from '../src/types';

import { chaiSetup } from './utils/chai_setup';

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