Make marketUtils interface compatible with Order and SignedOrder

This commit is contained in:
Brandon Millman 2018-08-13 21:29:35 -07:00
parent a2192e62df
commit 6a2634d362
2 changed files with 42 additions and 42 deletions

View File

@ -1,5 +1,5 @@
import { schemas } from '@0xproject/json-schemas'; import { schemas } from '@0xproject/json-schemas';
import { SignedOrder } from '@0xproject/types'; import { Order } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash'; import * as _ from 'lodash';
@ -12,40 +12,40 @@ export const marketUtils = {
* Takes an array of orders and returns a subset of those orders that has enough makerAssetAmount * Takes an array of orders and returns a subset of those orders that has enough makerAssetAmount
* in order to fill the input makerAssetFillAmount plus slippageBufferAmount. Iterates from first order to last order. * in order to fill the input makerAssetFillAmount plus slippageBufferAmount. Iterates from first order to last order.
* Sort the input by ascending rate in order to get the subset of orders that will cost the least ETH. * Sort the input by ascending rate in order to get the subset of orders that will cost the least ETH.
* @param signedOrders An array of objects that conform to the SignedOrder interface. All orders should specify the same makerAsset. * @param orders An array of objects that extend the Order interface. All orders should specify the same makerAsset.
* All orders should specify WETH as the takerAsset. * All orders should specify WETH as the takerAsset.
* @param makerAssetFillAmount The amount of makerAsset desired to be filled. * @param makerAssetFillAmount The amount of makerAsset desired to be filled.
* @param opts Optional arguments this function accepts. * @param opts Optional arguments this function accepts.
* @return Resulting orders and remaining fill amount that could not be covered by the input. * @return Resulting orders and remaining fill amount that could not be covered by the input.
*/ */
findOrdersThatCoverMakerAssetFillAmount( findOrdersThatCoverMakerAssetFillAmount<T extends Order>(
signedOrders: SignedOrder[], orders: T[],
makerAssetFillAmount: BigNumber, makerAssetFillAmount: BigNumber,
opts?: FindOrdersThatCoverMakerAssetFillAmountOpts, opts?: FindOrdersThatCoverMakerAssetFillAmountOpts,
): { resultOrders: SignedOrder[]; remainingFillAmount: BigNumber } { ): { resultOrders: T[]; remainingFillAmount: BigNumber } {
assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); assert.doesConformToSchema('orders', orders, schemas.ordersSchema);
assert.isValidBaseUnitAmount('makerAssetFillAmount', makerAssetFillAmount); assert.isValidBaseUnitAmount('makerAssetFillAmount', makerAssetFillAmount);
// try to get remainingFillableMakerAssetAmounts from opts, if it's not there, use makerAssetAmount values from signedOrders // try to get remainingFillableMakerAssetAmounts from opts, if it's not there, use makerAssetAmount values from orders
const remainingFillableMakerAssetAmounts = _.get( const remainingFillableMakerAssetAmounts = _.get(
opts, opts,
'remainingFillableMakerAssetAmounts', 'remainingFillableMakerAssetAmounts',
_.map(signedOrders, order => order.makerAssetAmount), _.map(orders, order => order.makerAssetAmount),
) as BigNumber[]; ) as BigNumber[];
_.forEach(remainingFillableMakerAssetAmounts, (amount, index) => _.forEach(remainingFillableMakerAssetAmounts, (amount, index) =>
assert.isValidBaseUnitAmount(`remainingFillableMakerAssetAmount[${index}]`, amount), assert.isValidBaseUnitAmount(`remainingFillableMakerAssetAmount[${index}]`, amount),
); );
assert.assert( assert.assert(
signedOrders.length === remainingFillableMakerAssetAmounts.length, orders.length === remainingFillableMakerAssetAmounts.length,
'Expected signedOrders.length to equal opts.remainingFillableMakerAssetAmounts.length', 'Expected orders.length to equal opts.remainingFillableMakerAssetAmounts.length',
); );
// try to get slippageBufferAmount from opts, if it's not there, default to 0 // try to get slippageBufferAmount from opts, if it's not there, default to 0
const slippageBufferAmount = _.get(opts, 'slippageBufferAmount', constants.ZERO_AMOUNT) as BigNumber; const slippageBufferAmount = _.get(opts, 'slippageBufferAmount', constants.ZERO_AMOUNT) as BigNumber;
assert.isValidBaseUnitAmount('opts.slippageBufferAmount', slippageBufferAmount); assert.isValidBaseUnitAmount('opts.slippageBufferAmount', slippageBufferAmount);
// calculate total amount of makerAsset needed to be filled // calculate total amount of makerAsset needed to be filled
const totalFillAmount = makerAssetFillAmount.plus(slippageBufferAmount); const totalFillAmount = makerAssetFillAmount.plus(slippageBufferAmount);
// iterate through the signedOrders input from left to right until we have enough makerAsset to fill totalFillAmount // iterate through the orders input from left to right until we have enough makerAsset to fill totalFillAmount
const result = _.reduce( const result = _.reduce(
signedOrders, orders,
({ resultOrders, remainingFillAmount }, order, index) => { ({ resultOrders, remainingFillAmount }, order, index) => {
if (remainingFillAmount.lessThanOrEqualTo(constants.ZERO_AMOUNT)) { if (remainingFillAmount.lessThanOrEqualTo(constants.ZERO_AMOUNT)) {
return { resultOrders, remainingFillAmount: constants.ZERO_AMOUNT }; return { resultOrders, remainingFillAmount: constants.ZERO_AMOUNT };
@ -64,61 +64,61 @@ export const marketUtils = {
}; };
} }
}, },
{ resultOrders: [] as SignedOrder[], remainingFillAmount: totalFillAmount }, { resultOrders: [] as T[], remainingFillAmount: totalFillAmount },
); );
return result; return result;
}, },
/** /**
* Takes an array of orders and an array of feeOrders. Returns a subset of the feeOrders that has enough ZRX * Takes an array of orders and an array of feeOrders. Returns a subset of the feeOrders that has enough ZRX
* in order to fill the takerFees required by signedOrders plus a slippageBufferAmount. * in order to fill the takerFees required by orders plus a slippageBufferAmount.
* Iterates from first feeOrder to last. Sort the feeOrders by ascending rate in order to get the subset of * Iterates from first feeOrder to last. Sort the feeOrders by ascending rate in order to get the subset of
* feeOrders that will cost the least ETH. * feeOrders that will cost the least ETH.
* @param signedOrders An array of objects that conform to the SignedOrder interface. All orders should specify ZRX as * @param orders An array of objects that extend the Order interface. All orders should specify ZRX as
* the makerAsset and WETH as the takerAsset. * the makerAsset and WETH as the takerAsset.
* @param signedFeeOrders An array of objects that conform to the SignedOrder interface. All orders should specify ZRX as * @param feeOrders An array of objects that extend the Order interface. All orders should specify ZRX as
* the makerAsset and WETH as the takerAsset. * the makerAsset and WETH as the takerAsset.
* @param opts Optional arguments this function accepts. * @param opts Optional arguments this function accepts.
* @return Resulting orders and remaining fee amount that could not be covered by the input. * @return Resulting orders and remaining fee amount that could not be covered by the input.
*/ */
findFeeOrdersThatCoverFeesForTargetOrders( findFeeOrdersThatCoverFeesForTargetOrders<T extends Order>(
signedOrders: SignedOrder[], orders: T[],
signedFeeOrders: SignedOrder[], feeOrders: T[],
opts?: FindFeeOrdersThatCoverFeesForTargetOrdersOpts, opts?: FindFeeOrdersThatCoverFeesForTargetOrdersOpts,
): { resultOrders: SignedOrder[]; remainingFeeAmount: BigNumber } { ): { resultOrders: T[]; remainingFeeAmount: BigNumber } {
assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); assert.doesConformToSchema('orders', orders, schemas.ordersSchema);
assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema); assert.doesConformToSchema('feeOrders', feeOrders, schemas.ordersSchema);
// try to get remainingFillableMakerAssetAmounts from opts, if it's not there, use makerAssetAmount values from signedOrders // try to get remainingFillableMakerAssetAmounts from opts, if it's not there, use makerAssetAmount values from orders
const remainingFillableMakerAssetAmounts = _.get( const remainingFillableMakerAssetAmounts = _.get(
opts, opts,
'remainingFillableMakerAssetAmounts', 'remainingFillableMakerAssetAmounts',
_.map(signedOrders, order => order.makerAssetAmount), _.map(orders, order => order.makerAssetAmount),
) as BigNumber[]; ) as BigNumber[];
_.forEach(remainingFillableMakerAssetAmounts, (amount, index) => _.forEach(remainingFillableMakerAssetAmounts, (amount, index) =>
assert.isValidBaseUnitAmount(`remainingFillableMakerAssetAmount[${index}]`, amount), assert.isValidBaseUnitAmount(`remainingFillableMakerAssetAmount[${index}]`, amount),
); );
assert.assert( assert.assert(
signedOrders.length === remainingFillableMakerAssetAmounts.length, orders.length === remainingFillableMakerAssetAmounts.length,
'Expected signedOrders.length to equal opts.remainingFillableMakerAssetAmounts.length', 'Expected orders.length to equal opts.remainingFillableMakerAssetAmounts.length',
); );
// try to get remainingFillableFeeAmounts from opts, if it's not there, use makerAssetAmount values from signedFeeOrders // try to get remainingFillableFeeAmounts from opts, if it's not there, use makerAssetAmount values from feeOrders
const remainingFillableFeeAmounts = _.get( const remainingFillableFeeAmounts = _.get(
opts, opts,
'remainingFillableFeeAmounts', 'remainingFillableFeeAmounts',
_.map(signedFeeOrders, order => order.makerAssetAmount), _.map(feeOrders, order => order.makerAssetAmount),
) as BigNumber[]; ) as BigNumber[];
_.forEach(remainingFillableFeeAmounts, (amount, index) => _.forEach(remainingFillableFeeAmounts, (amount, index) =>
assert.isValidBaseUnitAmount(`remainingFillableFeeAmounts[${index}]`, amount), assert.isValidBaseUnitAmount(`remainingFillableFeeAmounts[${index}]`, amount),
); );
assert.assert( assert.assert(
signedOrders.length === remainingFillableMakerAssetAmounts.length, feeOrders.length === remainingFillableFeeAmounts.length,
'Expected signedFeeOrders.length to equal opts.remainingFillableFeeAmounts.length', 'Expected feeOrders.length to equal opts.remainingFillableFeeAmounts.length',
); );
// try to get slippageBufferAmount from opts, if it's not there, default to 0 // try to get slippageBufferAmount from opts, if it's not there, default to 0
const slippageBufferAmount = _.get(opts, 'slippageBufferAmount', constants.ZERO_AMOUNT) as BigNumber; const slippageBufferAmount = _.get(opts, 'slippageBufferAmount', constants.ZERO_AMOUNT) as BigNumber;
assert.isValidBaseUnitAmount('opts.slippageBufferAmount', slippageBufferAmount); assert.isValidBaseUnitAmount('opts.slippageBufferAmount', slippageBufferAmount);
// calculate total amount of ZRX needed to fill signedOrders // calculate total amount of ZRX needed to fill orders
const totalFeeAmount = _.reduce( const totalFeeAmount = _.reduce(
signedOrders, orders,
(accFees, order, index) => { (accFees, order, index) => {
const makerAssetAmountAvailable = remainingFillableMakerAssetAmounts[index]; const makerAssetAmountAvailable = remainingFillableMakerAssetAmounts[index];
const feeToFillMakerAssetAmountAvailable = makerAssetAmountAvailable const feeToFillMakerAssetAmountAvailable = makerAssetAmountAvailable
@ -129,7 +129,7 @@ export const marketUtils = {
constants.ZERO_AMOUNT, constants.ZERO_AMOUNT,
); );
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
signedFeeOrders, feeOrders,
totalFeeAmount, totalFeeAmount,
{ {
remainingFillableMakerAssetAmounts: remainingFillableFeeAmounts, remainingFillableMakerAssetAmounts: remainingFillableFeeAmounts,

View File

@ -43,9 +43,9 @@ export interface CreateOrderOpts {
} }
/** /**
* remainingFillableMakerAssetAmount: An array of BigNumbers corresponding to the `signedOrders` parameter. * remainingFillableMakerAssetAmount: An array of BigNumbers corresponding to the `orders` parameter.
* You can use `OrderStateUtils` `@0xproject/order-utils` to perform blockchain lookups for these values. * You can use `OrderStateUtils` `@0xproject/order-utils` to perform blockchain lookups for these values.
* Defaults to `makerAssetAmount` values from the signedOrders param. * Defaults to `makerAssetAmount` values from the orders param.
* slippageBufferAmount: An additional amount of makerAsset to be covered by the result in case of trade collisions or partial fills. * slippageBufferAmount: An additional amount of makerAsset to be covered by the result in case of trade collisions or partial fills.
* Defaults to 0 * Defaults to 0
*/ */
@ -55,12 +55,12 @@ export interface FindOrdersThatCoverMakerAssetFillAmountOpts {
} }
/** /**
* remainingFillableMakerAssetAmount: An array of BigNumbers corresponding to the `signedOrders` parameter. * remainingFillableMakerAssetAmount: An array of BigNumbers corresponding to the `orders` parameter.
* You can use `OrderStateUtils` `@0xproject/order-utils` to perform blockchain lookups for these values. * You can use `OrderStateUtils` `@0xproject/order-utils` to perform blockchain lookups for these values.
* Defaults to `makerAssetAmount` values from the signedOrders param. * Defaults to `makerAssetAmount` values from the orders param.
* remainingFillableFeeAmounts: An array of BigNumbers corresponding to the signedFeeOrders parameter. * remainingFillableFeeAmounts: An array of BigNumbers corresponding to the feeOrders parameter.
* You can use OrderStateUtils @0xproject/order-utils to perform blockchain lookups for these values. * You can use OrderStateUtils @0xproject/order-utils to perform blockchain lookups for these values.
* Defaults to `makerAssetAmount` values from the signedFeeOrders param. * Defaults to `makerAssetAmount` values from the feeOrders param.
* slippageBufferAmount: An additional amount of fee to be covered by the result in case of trade collisions or partial fills. * slippageBufferAmount: An additional amount of fee to be covered by the result in case of trade collisions or partial fills.
* Defaults to 0 * Defaults to 0
*/ */