aboutsummaryrefslogtreecommitdiffstats
path: root/packages/0x.js/src/order_watcher/remaining_fillable_calculator.ts
blob: fe373eae47158019bc0a141195fdd9eb21070ce2 (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
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,
                zrxAddress: string,
                transferrableMakerTokenAmount: BigNumber,
                transferrableMakerFeeTokenAmount: BigNumber,
                remainingMakerTokenAmount: BigNumber) {
        this._signedOrder = signedOrder;
        this._isMakerTokenZRX = signedOrder.makerTokenAddress === zrxAddress;
        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 totalZRXTransferAmount = this._remainingMakerTokenAmount.plus(this._remainingMakerFeeAmount);
            return this._transferrableMakerTokenAmount.gte(totalZRXTransferAmount);
        } 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);
        const fillableTimesInFeeToken = BigNumber.min(this._transferrableMakerFeeTokenAmount,
                                                      this._remainingMakerFeeAmount);
        let fillableTimesInMakerToken = this._transferrableMakerTokenAmount.dividedToIntegerBy(orderToFeeRatio);
        if (this._isMakerTokenZRX) {
            // when zrx == maker token transferrable maker == transfer
            const totalZRXTokenPooled = this._transferrableMakerTokenAmount;
            fillableTimesInMakerToken = totalZRXTokenPooled.dividedToIntegerBy(
                                                             orderToFeeRatio.plus(new BigNumber(1)));

        }
        const partiallyFillableMakerTokenAmount = fillableTimesInMakerToken.times(orderToFeeRatio);
        const partiallyFillableFeeTokenAmount = fillableTimesInFeeToken.times(orderToFeeRatio);
        return BigNumber.min(partiallyFillableMakerTokenAmount, partiallyFillableFeeTokenAmount);
    }
}