refactored types and market sell operation
This commit is contained in:
		@@ -10,6 +10,7 @@ import {
 | 
			
		||||
    FindFeeOrdersThatCoverFeesForTargetOrdersOpts,
 | 
			
		||||
    FindOrdersThatCoverMakerAssetFillAmountOpts,
 | 
			
		||||
    FindOrdersThatCoverTakerAssetFillAmountOpts,
 | 
			
		||||
    MarketOperation,
 | 
			
		||||
    OrdersAndRemainingMakerFillAmount,
 | 
			
		||||
    OrdersAndRemainingTakerFillAmount,
 | 
			
		||||
} from './types';
 | 
			
		||||
@@ -20,60 +21,12 @@ export const marketUtils = {
 | 
			
		||||
        takerAssetFillAmount: BigNumber,
 | 
			
		||||
        opts?: FindOrdersThatCoverTakerAssetFillAmountOpts,
 | 
			
		||||
    ): OrdersAndRemainingTakerFillAmount<T> {
 | 
			
		||||
        assert.doesConformToSchema('orders', orders, schemas.ordersSchema);
 | 
			
		||||
        assert.isValidBaseUnitAmount('takerAssetFillAmount', takerAssetFillAmount);
 | 
			
		||||
        // try to get remainingFillableTakerAssetAmounts from opts, if it's not there, use takerAssetAmount values from orders
 | 
			
		||||
        const remainingFillableTakerAssetAmounts = _.get(
 | 
			
		||||
            opts,
 | 
			
		||||
            'remainingFillableTakerAssetAmounts',
 | 
			
		||||
            _.map(orders, order => order.takerAssetAmount),
 | 
			
		||||
        ) as BigNumber[];
 | 
			
		||||
        _.forEach(remainingFillableTakerAssetAmounts, (amount, index) =>
 | 
			
		||||
            assert.isValidBaseUnitAmount(`remainingFillableTakerAssetAmount[${index}]`, amount),
 | 
			
		||||
        );
 | 
			
		||||
        assert.assert(
 | 
			
		||||
            orders.length === remainingFillableTakerAssetAmounts.length,
 | 
			
		||||
            'Expected orders.length to equal opts.remainingFillableMakerAssetAmounts.length',
 | 
			
		||||
        );
 | 
			
		||||
        // try to get slippageBufferAmount from opts, if it's not there, default to 0
 | 
			
		||||
        const slippageBufferAmount = _.get(opts, 'slippageBufferAmount', constants.ZERO_AMOUNT) as BigNumber;
 | 
			
		||||
        assert.isValidBaseUnitAmount('opts.slippageBufferAmount', slippageBufferAmount);
 | 
			
		||||
        // calculate total amount of makerAsset needed to be filled
 | 
			
		||||
        const totalFillAmount = takerAssetFillAmount.plus(slippageBufferAmount);
 | 
			
		||||
        // iterate through the orders input from left to right until we have enough makerAsset to fill totalFillAmount
 | 
			
		||||
        const result = _.reduce(
 | 
			
		||||
        return findOrdersThatCoverAssetFillAmount(
 | 
			
		||||
            orders,
 | 
			
		||||
            ({ resultOrders, remainingFillAmount, ordersRemainingFillableTakerAssetAmounts }, order, index) => {
 | 
			
		||||
                if (remainingFillAmount.isLessThanOrEqualTo(constants.ZERO_AMOUNT)) {
 | 
			
		||||
                    return {
 | 
			
		||||
                        resultOrders,
 | 
			
		||||
                        remainingFillAmount: constants.ZERO_AMOUNT,
 | 
			
		||||
                        ordersRemainingFillableTakerAssetAmounts,
 | 
			
		||||
                    };
 | 
			
		||||
                } else {
 | 
			
		||||
                    const takerAssetAmountAvailable = remainingFillableTakerAssetAmounts[index];
 | 
			
		||||
                    const shouldIncludeOrder = takerAssetAmountAvailable.gt(constants.ZERO_AMOUNT);
 | 
			
		||||
                    // if there is no makerAssetAmountAvailable do not append order to resultOrders
 | 
			
		||||
                    // if we have exceeded the total amount we want to fill set remainingFillAmount to 0
 | 
			
		||||
                    return {
 | 
			
		||||
                        resultOrders: shouldIncludeOrder ? _.concat(resultOrders, order) : resultOrders,
 | 
			
		||||
                        ordersRemainingFillableTakerAssetAmounts: shouldIncludeOrder
 | 
			
		||||
                            ? _.concat(ordersRemainingFillableTakerAssetAmounts, takerAssetAmountAvailable)
 | 
			
		||||
                            : ordersRemainingFillableTakerAssetAmounts,
 | 
			
		||||
                        remainingFillAmount: BigNumber.max(
 | 
			
		||||
                            constants.ZERO_AMOUNT,
 | 
			
		||||
                            remainingFillAmount.minus(takerAssetAmountAvailable),
 | 
			
		||||
                        ),
 | 
			
		||||
                    };
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                resultOrders: [] as T[],
 | 
			
		||||
                remainingFillAmount: totalFillAmount,
 | 
			
		||||
                ordersRemainingFillableTakerAssetAmounts: [] as BigNumber[],
 | 
			
		||||
            },
 | 
			
		||||
        );
 | 
			
		||||
        return result;
 | 
			
		||||
            takerAssetFillAmount,
 | 
			
		||||
            'marketSell',
 | 
			
		||||
            opts,
 | 
			
		||||
        ) as OrdersAndRemainingTakerFillAmount<T>;
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * Takes an array of orders and returns a subset of those orders that has enough makerAssetAmount
 | 
			
		||||
@@ -90,60 +43,12 @@ export const marketUtils = {
 | 
			
		||||
        makerAssetFillAmount: BigNumber,
 | 
			
		||||
        opts?: FindOrdersThatCoverMakerAssetFillAmountOpts,
 | 
			
		||||
    ): OrdersAndRemainingMakerFillAmount<T> {
 | 
			
		||||
        assert.doesConformToSchema('orders', orders, schemas.ordersSchema);
 | 
			
		||||
        assert.isValidBaseUnitAmount('makerAssetFillAmount', makerAssetFillAmount);
 | 
			
		||||
        // try to get remainingFillableMakerAssetAmounts from opts, if it's not there, use makerAssetAmount values from orders
 | 
			
		||||
        const remainingFillableMakerAssetAmounts = _.get(
 | 
			
		||||
            opts,
 | 
			
		||||
            'remainingFillableMakerAssetAmounts',
 | 
			
		||||
            _.map(orders, order => order.makerAssetAmount),
 | 
			
		||||
        ) as BigNumber[];
 | 
			
		||||
        _.forEach(remainingFillableMakerAssetAmounts, (amount, index) =>
 | 
			
		||||
            assert.isValidBaseUnitAmount(`remainingFillableMakerAssetAmount[${index}]`, amount),
 | 
			
		||||
        );
 | 
			
		||||
        assert.assert(
 | 
			
		||||
            orders.length === remainingFillableMakerAssetAmounts.length,
 | 
			
		||||
            'Expected orders.length to equal opts.remainingFillableMakerAssetAmounts.length',
 | 
			
		||||
        );
 | 
			
		||||
        // try to get slippageBufferAmount from opts, if it's not there, default to 0
 | 
			
		||||
        const slippageBufferAmount = _.get(opts, 'slippageBufferAmount', constants.ZERO_AMOUNT) as BigNumber;
 | 
			
		||||
        assert.isValidBaseUnitAmount('opts.slippageBufferAmount', slippageBufferAmount);
 | 
			
		||||
        // calculate total amount of makerAsset needed to be filled
 | 
			
		||||
        const totalFillAmount = makerAssetFillAmount.plus(slippageBufferAmount);
 | 
			
		||||
        // iterate through the orders input from left to right until we have enough makerAsset to fill totalFillAmount
 | 
			
		||||
        const result = _.reduce(
 | 
			
		||||
        return findOrdersThatCoverAssetFillAmount(
 | 
			
		||||
            orders,
 | 
			
		||||
            ({ resultOrders, remainingFillAmount, ordersRemainingFillableMakerAssetAmounts }, order, index) => {
 | 
			
		||||
                if (remainingFillAmount.isLessThanOrEqualTo(constants.ZERO_AMOUNT)) {
 | 
			
		||||
                    return {
 | 
			
		||||
                        resultOrders,
 | 
			
		||||
                        remainingFillAmount: constants.ZERO_AMOUNT,
 | 
			
		||||
                        ordersRemainingFillableMakerAssetAmounts,
 | 
			
		||||
                    };
 | 
			
		||||
                } else {
 | 
			
		||||
                    const makerAssetAmountAvailable = remainingFillableMakerAssetAmounts[index];
 | 
			
		||||
                    const shouldIncludeOrder = makerAssetAmountAvailable.gt(constants.ZERO_AMOUNT);
 | 
			
		||||
                    // if there is no makerAssetAmountAvailable do not append order to resultOrders
 | 
			
		||||
                    // if we have exceeded the total amount we want to fill set remainingFillAmount to 0
 | 
			
		||||
                    return {
 | 
			
		||||
                        resultOrders: shouldIncludeOrder ? _.concat(resultOrders, order) : resultOrders,
 | 
			
		||||
                        ordersRemainingFillableMakerAssetAmounts: shouldIncludeOrder
 | 
			
		||||
                            ? _.concat(ordersRemainingFillableMakerAssetAmounts, makerAssetAmountAvailable)
 | 
			
		||||
                            : ordersRemainingFillableMakerAssetAmounts,
 | 
			
		||||
                        remainingFillAmount: BigNumber.max(
 | 
			
		||||
                            constants.ZERO_AMOUNT,
 | 
			
		||||
                            remainingFillAmount.minus(makerAssetAmountAvailable),
 | 
			
		||||
                        ),
 | 
			
		||||
                    };
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                resultOrders: [] as T[],
 | 
			
		||||
                remainingFillAmount: totalFillAmount,
 | 
			
		||||
                ordersRemainingFillableMakerAssetAmounts: [] as BigNumber[],
 | 
			
		||||
            },
 | 
			
		||||
        );
 | 
			
		||||
        return result;
 | 
			
		||||
            makerAssetFillAmount,
 | 
			
		||||
            'marketBuy',
 | 
			
		||||
            opts,
 | 
			
		||||
        ) as OrdersAndRemainingMakerFillAmount<T>;
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * Takes an array of orders and an array of feeOrders. Returns a subset of the feeOrders that has enough ZRX
 | 
			
		||||
@@ -222,3 +127,82 @@ export const marketUtils = {
 | 
			
		||||
        // https://github.com/0xProject/0x-protocol-specification/blob/master/v2/forwarding-contract-specification.md#over-buying-zrx
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function findOrdersThatCoverAssetFillAmount<T extends Order>(
 | 
			
		||||
    orders: T[],
 | 
			
		||||
    assetFillAmount: BigNumber,
 | 
			
		||||
    operation: MarketOperation,
 | 
			
		||||
    opts?: FindOrdersThatCoverTakerAssetFillAmountOpts,
 | 
			
		||||
): OrdersAndRemainingTakerFillAmount<T> | OrdersAndRemainingMakerFillAmount<T> {
 | 
			
		||||
    const variablePrefix = operation === 'marketBuy' ? 'maker' : 'taker';
 | 
			
		||||
    assert.doesConformToSchema('orders', orders, schemas.ordersSchema);
 | 
			
		||||
    assert.isValidBaseUnitAmount(`${variablePrefix}AssetFillAmount}`, assetFillAmount);
 | 
			
		||||
    // try to get remainingFillableTakerAssetAmounts from opts, if it's not there, use takerAssetAmount values from orders
 | 
			
		||||
    const remainingFillableAssetAmounts = _.get(
 | 
			
		||||
        opts,
 | 
			
		||||
        `remainingFillable${variablePrefix}AssetAmounts`,
 | 
			
		||||
        _.map(orders, order => (operation === 'marketBuy' ? order.makerAssetAmount : order.takerAssetAmount)),
 | 
			
		||||
    ) as BigNumber[];
 | 
			
		||||
    _.forEach(remainingFillableAssetAmounts, (amount, index) =>
 | 
			
		||||
        assert.isValidBaseUnitAmount(`remainingFillable${variablePrefix}AssetAmount[${index}]`, amount),
 | 
			
		||||
    );
 | 
			
		||||
    assert.assert(
 | 
			
		||||
        orders.length === remainingFillableAssetAmounts.length,
 | 
			
		||||
        `Expected orders.length to equal opts.remainingFillable${variablePrefix}AssetAmounts.length`,
 | 
			
		||||
    );
 | 
			
		||||
    // try to get slippageBufferAmount from opts, if it's not there, default to 0
 | 
			
		||||
    const slippageBufferAmount = _.get(opts, 'slippageBufferAmount', constants.ZERO_AMOUNT) as BigNumber;
 | 
			
		||||
    assert.isValidBaseUnitAmount('opts.slippageBufferAmount', slippageBufferAmount);
 | 
			
		||||
    // calculate total amount of asset needed to be filled
 | 
			
		||||
    const totalFillAmount = assetFillAmount.plus(slippageBufferAmount);
 | 
			
		||||
    // iterate through the orders input from left to right until we have enough makerAsset to fill totalFillAmount
 | 
			
		||||
    const result = _.reduce(
 | 
			
		||||
        orders,
 | 
			
		||||
        ({ resultOrders, remainingFillAmount, ordersRemainingFillableAssetAmounts }, order, index) => {
 | 
			
		||||
            if (remainingFillAmount.isLessThanOrEqualTo(constants.ZERO_AMOUNT)) {
 | 
			
		||||
                return {
 | 
			
		||||
                    resultOrders,
 | 
			
		||||
                    remainingFillAmount: constants.ZERO_AMOUNT,
 | 
			
		||||
                    ordersRemainingFillableAssetAmounts,
 | 
			
		||||
                };
 | 
			
		||||
            } else {
 | 
			
		||||
                const assetAmountAvailable = remainingFillableAssetAmounts[index];
 | 
			
		||||
                const shouldIncludeOrder = assetAmountAvailable.gt(constants.ZERO_AMOUNT);
 | 
			
		||||
                // if there is no assetAmountAvailable do not append order to resultOrders
 | 
			
		||||
                // if we have exceeded the total amount we want to fill set remainingFillAmount to 0
 | 
			
		||||
                return {
 | 
			
		||||
                    resultOrders: shouldIncludeOrder ? _.concat(resultOrders, order) : resultOrders,
 | 
			
		||||
                    ordersRemainingFillableAssetAmounts: shouldIncludeOrder
 | 
			
		||||
                        ? _.concat(ordersRemainingFillableAssetAmounts, assetAmountAvailable)
 | 
			
		||||
                        : ordersRemainingFillableAssetAmounts,
 | 
			
		||||
                    remainingFillAmount: BigNumber.max(
 | 
			
		||||
                        constants.ZERO_AMOUNT,
 | 
			
		||||
                        remainingFillAmount.minus(assetAmountAvailable),
 | 
			
		||||
                    ),
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            resultOrders: [] as T[],
 | 
			
		||||
            remainingFillAmount: totalFillAmount,
 | 
			
		||||
            ordersRemainingFillableAssetAmounts: [] as BigNumber[],
 | 
			
		||||
        },
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    const {
 | 
			
		||||
        ordersRemainingFillableAssetAmounts: resultOrdersRemainingFillableAssetAmounts,
 | 
			
		||||
        ...ordersAndRemainingFillAmount
 | 
			
		||||
    } = result;
 | 
			
		||||
 | 
			
		||||
    if (operation === 'marketBuy') {
 | 
			
		||||
        return {
 | 
			
		||||
            ...ordersAndRemainingFillAmount,
 | 
			
		||||
            ordersRemainingFillableMakerAssetAmounts: resultOrdersRemainingFillableAssetAmounts,
 | 
			
		||||
        };
 | 
			
		||||
    } else {
 | 
			
		||||
        return {
 | 
			
		||||
            ...ordersAndRemainingFillAmount,
 | 
			
		||||
            ordersRemainingFillableMakerAssetAmounts: resultOrdersRemainingFillableAssetAmounts,
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -49,6 +49,8 @@ export interface FindOrdersThatCoverTakerAssetFillAmountOpts {
 | 
			
		||||
    slippageBufferAmount?: BigNumber;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type MarketOperation = 'marketSell' | 'marketBuy';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * remainingFillableMakerAssetAmount: An array of BigNumbers corresponding to the `orders` parameter.
 | 
			
		||||
 * You can use `OrderStateUtils` `@0x/order-utils` to perform blockchain lookups for these values.
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user