aboutsummaryrefslogtreecommitdiffstats
path: root/packages/0x.js/src/order_watcher/remaining_fillable_calculator.ts
blob: 8141dd73cedc07d4063835cfb50c44b1b6770b2d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import {
    SignedOrder,
} from '../types';
import { BigNumber } from 'bignumber.js';
export class RemainingFillableCalculator {
    private _signedOrder: SignedOrder;
    private _isMakerTokenZRX: boolean;
    private _transferrableMakerTokenAmount: BigNumber;
    private _transferrableMakerFeeTokenAmount: BigNumber;
    private _remainingMakerTokenAmount: BigNumber;
    private _remainingMakerFeeAmount: BigNumber;
    constructor(signedOrder: SignedOrder,
                isMakerTokenZRX: boolean,
                transferrableMakerTokenAmount: BigNumber,
                transferrableMakerFeeTokenAmount: BigNumber,
                remainingMakerTokenAmount: BigNumber) {
        this._signedOrder = signedOrder;
        this._isMakerTokenZRX = isMakerTokenZRX;
        this._transferrableMakerTokenAmount = transferrableMakerTokenAmount;
        this._transferrableMakerFeeTokenAmount = transferrableMakerFeeTokenAmount;
        this._remainingMakerTokenAmount = remainingMakerTokenAmount;
        this._remainingMakerFeeAmount = remainingMakerTokenAmount.times(signedOrder.makerFee)
                                                                 .dividedToIntegerBy(signedOrder.makerTokenAmount);
    }
    public computeRemainingMakerFillable(): BigNumber {
        if (this.hasSufficientFundsForFeeAndTransferAmount()) {
            return this._remainingMakerTokenAmount;
        }
        if (this._signedOrder.makerFee.isZero()) {
            return BigNumber.min(this._remainingMakerTokenAmount, this._transferrableMakerTokenAmount);
        } else {
            return this.calculatePartiallyFillableMakerTokenAmount();
        }
    }
    public computeRemainingTakerFillable(): BigNumber {
        return this.computeRemainingMakerFillable().times(this._signedOrder.takerTokenAmount)
                                                   .dividedToIntegerBy(this._signedOrder.makerTokenAmount);
    }
    private hasSufficientFundsForFeeAndTransferAmount(): boolean {
        if (this._isMakerTokenZRX) {
            const totalZRXTransferAmountRequired = this._remainingMakerTokenAmount.plus(this._remainingMakerFeeAmount);
            return this._transferrableMakerTokenAmount.gte(totalZRXTransferAmountRequired);
        } else {
            const hasSufficientFundsForTransferAmount = this._transferrableMakerTokenAmount.gte(
                                                            this._remainingMakerTokenAmount);
            const hasSufficientFundsForFeeAmount = this._transferrableMakerFeeTokenAmount.gte(
                                                       this._remainingMakerFeeAmount);
            return (hasSufficientFundsForTransferAmount && hasSufficientFundsForFeeAmount);
        }
    }

    private calculatePartiallyFillableMakerTokenAmount(): BigNumber {
        const orderToFeeRatio = this._signedOrder.makerTokenAmount.dividedToIntegerBy(this._signedOrder.makerFee);
        // Maximum number of times the Maker can fill the order, given the fees
        const fillableTimesInFeeTokenUnits = BigNumber.min(this._transferrableMakerFeeTokenAmount,
                                                           this._remainingMakerFeeAmount);
        // Maximum number of times the Maker can fill the order, given the Maker Token Balance
        let fillableTimesInMakerTokenUnits = this._transferrableMakerTokenAmount.dividedToIntegerBy(orderToFeeRatio);
        if (this._isMakerTokenZRX) {
            const totalZRXTokenPooled = this._transferrableMakerTokenAmount;
            // The purchasing power here is less as the tokens are taken from the same Pool
            // For every one number of fills, we have to take an extra ZRX out of the pool
            fillableTimesInMakerTokenUnits = totalZRXTokenPooled.dividedToIntegerBy(
                                                                     orderToFeeRatio.plus(new BigNumber(1)));

        }
        const partiallyFillableMakerTokenAmount = fillableTimesInMakerTokenUnits.times(orderToFeeRatio);
        const partiallyFillableFeeTokenAmount = fillableTimesInFeeTokenUnits.times(orderToFeeRatio);
        return BigNumber.min(partiallyFillableMakerTokenAmount, partiallyFillableFeeTokenAmount);
    }
}