235 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			235 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import { ECSignature, SignedOrder } from '@0xproject/types';
 | 
						|
import { BigNumber } from '@0xproject/utils';
 | 
						|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
 | 
						|
import * as chai from 'chai';
 | 
						|
import 'mocha';
 | 
						|
 | 
						|
import { RemainingFillableCalculator } from '@0xproject/order-utils';
 | 
						|
 | 
						|
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] = [
 | 
						|
            Web3Wrapper.toBaseUnitAmount(new BigNumber(50), decimals),
 | 
						|
            Web3Wrapper.toBaseUnitAmount(new BigNumber(5), decimals),
 | 
						|
            Web3Wrapper.toBaseUnitAmount(new BigNumber(1), decimals),
 | 
						|
        ];
 | 
						|
        [transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount] = [
 | 
						|
            Web3Wrapper.toBaseUnitAmount(new BigNumber(50), decimals),
 | 
						|
            Web3Wrapper.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 = Web3Wrapper.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 = Web3Wrapper.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] = [
 | 
						|
                    Web3Wrapper.toBaseUnitAmount(new BigNumber(3), decimals),
 | 
						|
                    Web3Wrapper.toBaseUnitAmount(new BigNumber(6), decimals),
 | 
						|
                    Web3Wrapper.toBaseUnitAmount(new BigNumber(6), decimals),
 | 
						|
                ];
 | 
						|
            });
 | 
						|
            it('calculates the correct amount when funds unavailable', () => {
 | 
						|
                signedOrder = buildSignedOrder();
 | 
						|
                remainingMakerTokenAmount = signedOrder.makerTokenAmount;
 | 
						|
                const transferredAmount = Web3Wrapper.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] = [
 | 
						|
                    Web3Wrapper.toBaseUnitAmount(new BigNumber(3), decimals),
 | 
						|
                    Web3Wrapper.toBaseUnitAmount(new BigNumber(7), decimals),
 | 
						|
                    Web3Wrapper.toBaseUnitAmount(new BigNumber(7), decimals),
 | 
						|
                ];
 | 
						|
            });
 | 
						|
            it('calculates the correct amount when funds unavailable', () => {
 | 
						|
                signedOrder = buildSignedOrder();
 | 
						|
                remainingMakerTokenAmount = signedOrder.makerTokenAmount;
 | 
						|
                const transferredAmount = Web3Wrapper.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 = Web3Wrapper.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 = Web3Wrapper.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);
 | 
						|
        });
 | 
						|
    });
 | 
						|
});
 |