import { marketUtils } from '@0xproject/order-utils'; import { BigNumber } from '@0xproject/utils'; import { constants } from '../constants'; import { AssetBuyerError, AssetBuyerOrdersAndFillableAmounts, BuyQuote } from '../types'; export const buyQuoteCalculator = { calculate( ordersAndFillableAmounts: AssetBuyerOrdersAndFillableAmounts, assetBuyAmount: BigNumber, feePercentage: number, slippagePercentage: number, ): BuyQuote { const { orders, feeOrders, remainingFillableMakerAssetAmounts, remainingFillableFeeAmounts, } = ordersAndFillableAmounts; const slippageBufferAmount = assetBuyAmount.mul(slippagePercentage).round(); const { resultOrders, remainingFillAmount } = 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, }, ); 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 return { assetData, orders: resultOrders, feeOrders: resultFeeOrders, minRate: constants.ZERO_AMOUNT, maxRate: constants.ZERO_AMOUNT, assetBuyAmount, feePercentage, }; }, };