aboutsummaryrefslogblamecommitdiffstats
path: root/packages/forwarder-helper/src/utils/forwarder_helper_impl_config_utils.ts
blob: 253384f6551a7545f4d78ac2635bf3e8520976a0 (plain) (tree)



























































































                                                                                                                             
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,
    };
}