Calculate min and max rates in buy quote
This commit is contained in:
parent
93f7e33f6a
commit
60e2dfdbda
@ -1,5 +1,6 @@
|
||||
import { marketUtils } from '@0xproject/order-utils';
|
||||
import { BigNumber } from '@0xproject/utils';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { constants } from '../constants';
|
||||
import { AssetBuyerError, AssetBuyerOrdersAndFillableAmounts, BuyQuote } from '../types';
|
||||
@ -18,41 +19,64 @@ export const buyQuoteCalculator = {
|
||||
remainingFillableFeeAmounts,
|
||||
} = ordersAndFillableAmounts;
|
||||
const slippageBufferAmount = assetBuyAmount.mul(slippagePercentage).round();
|
||||
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
|
||||
orders,
|
||||
assetBuyAmount,
|
||||
{
|
||||
remainingFillableMakerAssetAmounts,
|
||||
slippageBufferAmount,
|
||||
},
|
||||
);
|
||||
const {
|
||||
resultOrders,
|
||||
remainingFillAmount,
|
||||
ordersRemainingFillableMakerAssetAmounts,
|
||||
} = marketUtils.findOrdersThatCoverMakerAssetFillAmount(orders, assetBuyAmount, {
|
||||
remainingFillableMakerAssetAmounts,
|
||||
slippageBufferAmount,
|
||||
});
|
||||
if (remainingFillAmount.gt(constants.ZERO_AMOUNT)) {
|
||||
throw new Error(AssetBuyerError.InsufficientAssetLiquidity);
|
||||
}
|
||||
// TODO: optimization
|
||||
// update this logic to find the minimum amount of feeOrders to cover the worst case as opposed to
|
||||
// finding order that cover all fees, this will help with estimating ETH and minimizing gas usage
|
||||
const { resultFeeOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
|
||||
resultOrders,
|
||||
feeOrders,
|
||||
{
|
||||
remainingFillableMakerAssetAmounts,
|
||||
remainingFillableFeeAmounts,
|
||||
},
|
||||
);
|
||||
const {
|
||||
resultFeeOrders,
|
||||
remainingFeeAmount,
|
||||
feeOrdersRemainingFillableMakerAssetAmounts,
|
||||
} = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(resultOrders, feeOrders, {
|
||||
remainingFillableMakerAssetAmounts,
|
||||
remainingFillableFeeAmounts,
|
||||
});
|
||||
if (remainingFeeAmount.gt(constants.ZERO_AMOUNT)) {
|
||||
throw new Error(AssetBuyerError.InsufficientZrxLiquidity);
|
||||
}
|
||||
const assetData = orders[0].makerAssetData;
|
||||
// TODO: critical
|
||||
|
||||
// calculate minRate and maxRate by calculating min and max eth usage and then dividing into
|
||||
// assetBuyAmount to get assetData / WETH, needs to take into account feePercentage as well
|
||||
// minEthAmount = (sum(takerAssetAmount[i]) until sum(makerAssetAmount[i]) >= assetBuyAmount ) * (1 + feePercentage)
|
||||
// maxEthAmount = (sum(takerAssetAmount[i]) until i == orders.length) * (1 + feePercentage)
|
||||
const allOrders = _.concat(resultOrders, resultFeeOrders);
|
||||
const allRemainingAmounts = _.concat(
|
||||
ordersRemainingFillableMakerAssetAmounts,
|
||||
feeOrdersRemainingFillableMakerAssetAmounts,
|
||||
);
|
||||
let minEthAmount = constants.ZERO_AMOUNT;
|
||||
let maxEthAmount = constants.ZERO_AMOUNT;
|
||||
let cumulativeMakerAmount = constants.ZERO_AMOUNT;
|
||||
_.forEach(allOrders, (order, index) => {
|
||||
const remainingFillableMakerAssetAmount = allRemainingAmounts[index];
|
||||
const orderRate = order.takerAssetAmount.div(order.makerAssetAmount);
|
||||
const claimableTakerAssetAmount = orderRate.mul(remainingFillableMakerAssetAmount);
|
||||
// taker asset is always assumed to be WETH
|
||||
maxEthAmount = maxEthAmount.plus(claimableTakerAssetAmount);
|
||||
if (cumulativeMakerAmount.lessThan(assetBuyAmount)) {
|
||||
minEthAmount = minEthAmount.plus(claimableTakerAssetAmount);
|
||||
}
|
||||
cumulativeMakerAmount = cumulativeMakerAmount.plus(remainingFillableMakerAssetAmount);
|
||||
});
|
||||
const feeAdjustedMinRate = minEthAmount.mul(feePercentage + 1).div(assetBuyAmount);
|
||||
const feeAdjustedMaxRate = minEthAmount.mul(feePercentage + 1).div(assetBuyAmount);
|
||||
return {
|
||||
assetData,
|
||||
orders: resultOrders,
|
||||
feeOrders: resultFeeOrders,
|
||||
minRate: constants.ZERO_AMOUNT,
|
||||
maxRate: constants.ZERO_AMOUNT,
|
||||
minRate: feeAdjustedMinRate,
|
||||
maxRate: feeAdjustedMaxRate,
|
||||
assetBuyAmount,
|
||||
feePercentage,
|
||||
};
|
||||
|
@ -51,17 +51,23 @@ export const marketUtils = {
|
||||
// iterate through the orders input from left to right until we have enough makerAsset to fill totalFillAmount
|
||||
const result = _.reduce(
|
||||
orders,
|
||||
({ resultOrders, remainingFillAmount }, order, index) => {
|
||||
({ resultOrders, remainingFillAmount, ordersRemainingFillableMakerAssetAmounts }, order, index) => {
|
||||
if (remainingFillAmount.lessThanOrEqualTo(constants.ZERO_AMOUNT)) {
|
||||
return { resultOrders, remainingFillAmount: 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: makerAssetAmountAvailable.gt(constants.ZERO_AMOUNT)
|
||||
? _.concat(resultOrders, order)
|
||||
: resultOrders,
|
||||
resultOrders: shouldIncludeOrder ? _.concat(resultOrders, order) : resultOrders,
|
||||
ordersRemainingFillableMakerAssetAmounts: shouldIncludeOrder
|
||||
? _.concat(ordersRemainingFillableMakerAssetAmounts, makerAssetAmountAvailable)
|
||||
: ordersRemainingFillableMakerAssetAmounts,
|
||||
remainingFillAmount: BigNumber.max(
|
||||
constants.ZERO_AMOUNT,
|
||||
remainingFillAmount.minus(makerAssetAmountAvailable),
|
||||
@ -69,7 +75,11 @@ export const marketUtils = {
|
||||
};
|
||||
}
|
||||
},
|
||||
{ resultOrders: [] as T[], remainingFillAmount: totalFillAmount },
|
||||
{
|
||||
resultOrders: [] as T[],
|
||||
remainingFillAmount: totalFillAmount,
|
||||
ordersRemainingFillableMakerAssetAmounts: [] as BigNumber[],
|
||||
},
|
||||
);
|
||||
return result;
|
||||
},
|
||||
@ -133,17 +143,18 @@ export const marketUtils = {
|
||||
},
|
||||
constants.ZERO_AMOUNT,
|
||||
);
|
||||
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
|
||||
feeOrders,
|
||||
totalFeeAmount,
|
||||
{
|
||||
remainingFillableMakerAssetAmounts: remainingFillableFeeAmounts,
|
||||
slippageBufferAmount,
|
||||
},
|
||||
);
|
||||
const {
|
||||
resultOrders,
|
||||
remainingFillAmount,
|
||||
ordersRemainingFillableMakerAssetAmounts,
|
||||
} = marketUtils.findOrdersThatCoverMakerAssetFillAmount(feeOrders, totalFeeAmount, {
|
||||
remainingFillableMakerAssetAmounts: remainingFillableFeeAmounts,
|
||||
slippageBufferAmount,
|
||||
});
|
||||
return {
|
||||
resultFeeOrders: resultOrders,
|
||||
remainingFeeAmount: remainingFillAmount,
|
||||
feeOrdersRemainingFillableMakerAssetAmounts: ordersRemainingFillableMakerAssetAmounts,
|
||||
};
|
||||
// TODO: add more orders here to cover rounding
|
||||
// https://github.com/0xProject/0x-protocol-specification/blob/master/v2/forwarding-contract-specification.md#over-buying-zrx
|
||||
|
@ -72,10 +72,12 @@ export interface FindFeeOrdersThatCoverFeesForTargetOrdersOpts {
|
||||
|
||||
export interface FeeOrdersAndRemainingFeeAmount<T> {
|
||||
resultFeeOrders: T[];
|
||||
feeOrdersRemainingFillableMakerAssetAmounts: BigNumber[];
|
||||
remainingFeeAmount: BigNumber;
|
||||
}
|
||||
|
||||
export interface OrdersAndRemainingFillAmount<T> {
|
||||
resultOrders: T[];
|
||||
ordersRemainingFillableMakerAssetAmounts: BigNumber[];
|
||||
remainingFillAmount: BigNumber;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user