aboutsummaryrefslogtreecommitdiffstats
path: root/packages/asset-buyer/src/utils/buy_quote_calculator.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/asset-buyer/src/utils/buy_quote_calculator.ts')
-rw-r--r--packages/asset-buyer/src/utils/buy_quote_calculator.ts89
1 files changed, 89 insertions, 0 deletions
diff --git a/packages/asset-buyer/src/utils/buy_quote_calculator.ts b/packages/asset-buyer/src/utils/buy_quote_calculator.ts
new file mode 100644
index 000000000..9946924ef
--- /dev/null
+++ b/packages/asset-buyer/src/utils/buy_quote_calculator.ts
@@ -0,0 +1,89 @@
+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';
+
+import { orderUtils } from './order_utils';
+
+// Calculates a buy quote for orders that have WETH as the takerAsset
+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,
+ ordersRemainingFillableMakerAssetAmounts,
+ } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(orders, assetBuyAmount, {
+ remainingFillableMakerAssetAmounts,
+ slippageBufferAmount,
+ });
+ if (remainingFillAmount.gt(constants.ZERO_AMOUNT)) {
+ throw new Error(AssetBuyerError.InsufficientAssetLiquidity);
+ }
+ // TODO(bmillman): 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,
+ feeOrdersRemainingFillableMakerAssetAmounts,
+ } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(resultOrders, feeOrders, {
+ remainingFillableMakerAssetAmounts,
+ remainingFillableFeeAmounts,
+ });
+ if (remainingFeeAmount.gt(constants.ZERO_AMOUNT)) {
+ throw new Error(AssetBuyerError.InsufficientZrxLiquidity);
+ }
+ const assetData = orders[0].makerAssetData;
+
+ // 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 claimableTakerAssetAmount = orderUtils.calculateRemainingTakerAssetAmount(
+ order,
+ 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: feeAdjustedMinRate,
+ maxRate: feeAdjustedMaxRate,
+ assetBuyAmount,
+ feePercentage,
+ };
+ },
+};