aboutsummaryrefslogtreecommitdiffstats
path: root/packages/forwarder-helper/src/utils/forwarder_helper_impl_config_utils.ts
blob: 253384f6551a7545f4d78ac2635bf3e8520976a0 (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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import { sortingUtils } from '@0xproject/order-utils';
import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';

import { ForwarderHelperImplConfig } from '../forwarder_helper_impl';

interface SignedOrderWithAmount extends SignedOrder {
    remainingFillAmount: BigNumber;
}

export const forwarderHelperImplConfigUtils = {
    sortedConfig(config: ForwarderHelperImplConfig): ForwarderHelperImplConfig {
        const { orders, feeOrders, remainingFillableMakerAssetAmounts, remainingFillableFeeAmounts } = config;
        // TODO: provide a feeRate to the sorting function to more accurately sort based on the current market for ZRX tokens
        const orderSorter = (ordersToSort: SignedOrder[]) => {
            return sortingUtils.sortOrdersByFeeAdjustedRate(ordersToSort);
        };
        const sortOrdersResult = sortOrdersAndRemainingFillAmounts(
            orderSorter,
            orders,
            remainingFillableMakerAssetAmounts,
        );
        const feeOrderSorter = (ordersToSort: SignedOrder[]) => {
            return sortingUtils.sortFeeOrdersByFeeAdjustedRate(ordersToSort);
        };
        const sortFeeOrdersResult = sortOrdersAndRemainingFillAmounts(
            feeOrderSorter,
            feeOrders,
            remainingFillableFeeAmounts,
        );
        return {
            orders: sortOrdersResult.orders,
            feeOrders: sortFeeOrdersResult.orders,
            remainingFillableMakerAssetAmounts: sortOrdersResult.remainingFillAmounts,
            remainingFillableFeeAmounts: sortFeeOrdersResult.remainingFillAmounts,
        };
    },
};

type OrderSorter = (orders: SignedOrder[]) => SignedOrder[];

function sortOrdersAndRemainingFillAmounts(
    orderSorter: OrderSorter,
    orders: SignedOrder[],
    remainingFillAmounts?: BigNumber[],
): { orders: SignedOrder[]; remainingFillAmounts?: BigNumber[] } {
    if (!_.isUndefined(remainingFillAmounts)) {
        // Bundle orders together with their remainingFillAmounts so that we can sort them together
        const orderWithAmounts = bundleSignedOrderWithAmounts(orders, remainingFillAmounts);
        // Sort
        const sortedOrderWithAmounts = orderSorter(orderWithAmounts) as SignedOrderWithAmount[];
        // Unbundle after sorting
        const unbundledSortedOrderWithAmounts = unbundleSignedOrderWithAmounts(sortedOrderWithAmounts);
        return {
            orders: unbundledSortedOrderWithAmounts.orders,
            remainingFillAmounts: unbundledSortedOrderWithAmounts.amounts,
        };
    } else {
        const sortedOrders = orderSorter(orders);
        return {
            orders: sortedOrders,
        };
    }
}

function bundleSignedOrderWithAmounts(orders: SignedOrder[], amounts: BigNumber[]): SignedOrderWithAmount[] {
    const ordersAndAmounts = _.map(orders, (order, index) => {
        return {
            ...order,
            remainingFillAmount: amounts[index],
        };
    });
    return ordersAndAmounts;
}

function unbundleSignedOrderWithAmounts(
    signedOrderWithAmounts: SignedOrderWithAmount[],
): { orders: SignedOrder[]; amounts: BigNumber[] } {
    const orders = _.map(signedOrderWithAmounts, order => {
        const { remainingFillAmount, ...rest } = order;
        return rest;
    });
    const amounts = _.map(signedOrderWithAmounts, order => {
        const { remainingFillAmount } = order;
        return remainingFillAmount;
    });
    return {
        orders,
        amounts,
    };
}