235 lines
12 KiB
TypeScript
235 lines
12 KiB
TypeScript
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);
|
|
});
|
|
});
|
|
});
|