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.ts221
1 files changed, 0 insertions, 221 deletions
diff --git a/packages/asset-buyer/src/utils/buy_quote_calculator.ts b/packages/asset-buyer/src/utils/buy_quote_calculator.ts
deleted file mode 100644
index 125841094..000000000
--- a/packages/asset-buyer/src/utils/buy_quote_calculator.ts
+++ /dev/null
@@ -1,221 +0,0 @@
-import { marketUtils, SignedOrder } from '@0x/order-utils';
-import { BigNumber } from '@0x/utils';
-import * as _ from 'lodash';
-
-import { constants } from '../constants';
-import { InsufficientAssetLiquidityError } from '../errors';
-import { AssetBuyerError, BuyQuote, BuyQuoteInfo, OrdersAndFillableAmounts } from '../types';
-
-import { orderUtils } from './order_utils';
-
-// Calculates a buy quote for orders that have WETH as the takerAsset
-export const buyQuoteCalculator = {
- calculate(
- ordersAndFillableAmounts: OrdersAndFillableAmounts,
- feeOrdersAndFillableAmounts: OrdersAndFillableAmounts,
- assetBuyAmount: BigNumber,
- feePercentage: number,
- slippagePercentage: number,
- isMakerAssetZrxToken: boolean,
- ): BuyQuote {
- const orders = ordersAndFillableAmounts.orders;
- const remainingFillableMakerAssetAmounts = ordersAndFillableAmounts.remainingFillableMakerAssetAmounts;
- const feeOrders = feeOrdersAndFillableAmounts.orders;
- const remainingFillableFeeAmounts = feeOrdersAndFillableAmounts.remainingFillableMakerAssetAmounts;
- const slippageBufferAmount = assetBuyAmount.multipliedBy(slippagePercentage).integerValue();
- // find the orders that cover the desired assetBuyAmount (with slippage)
- const {
- resultOrders,
- remainingFillAmount,
- ordersRemainingFillableMakerAssetAmounts,
- } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(orders, assetBuyAmount, {
- remainingFillableMakerAssetAmounts,
- slippageBufferAmount,
- });
- // if we do not have enough orders to cover the desired assetBuyAmount, throw
- if (remainingFillAmount.gt(constants.ZERO_AMOUNT)) {
- // We needed the amount they requested to buy, plus the amount for slippage
- const totalAmountRequested = assetBuyAmount.plus(slippageBufferAmount);
- const amountAbleToFill = totalAmountRequested.minus(remainingFillAmount);
- // multiplierNeededWithSlippage represents what we need to multiply the assetBuyAmount by
- // in order to get the total amount needed considering slippage
- // i.e. if slippagePercent was 0.2 (20%), multiplierNeededWithSlippage would be 1.2
- const multiplierNeededWithSlippage = new BigNumber(1).plus(slippagePercentage);
- // Given amountAvailableToFillConsideringSlippage * multiplierNeededWithSlippage = amountAbleToFill
- // We divide amountUnableToFill by multiplierNeededWithSlippage to determine amountAvailableToFillConsideringSlippage
- const amountAvailableToFillConsideringSlippage = amountAbleToFill
- .div(multiplierNeededWithSlippage)
- .integerValue(BigNumber.ROUND_FLOOR);
-
- throw new InsufficientAssetLiquidityError(amountAvailableToFillConsideringSlippage);
- }
- // if we are not buying ZRX:
- // given the orders calculated above, find the fee-orders that cover the desired assetBuyAmount (with slippage)
- // 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
- let resultFeeOrders = [] as SignedOrder[];
- let feeOrdersRemainingFillableMakerAssetAmounts = [] as BigNumber[];
- if (!isMakerAssetZrxToken) {
- const feeOrdersAndRemainingFeeAmount = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
- resultOrders,
- feeOrders,
- {
- remainingFillableMakerAssetAmounts: ordersRemainingFillableMakerAssetAmounts,
- remainingFillableFeeAmounts,
- },
- );
- // if we do not have enough feeOrders to cover the fees, throw
- if (feeOrdersAndRemainingFeeAmount.remainingFeeAmount.gt(constants.ZERO_AMOUNT)) {
- throw new Error(AssetBuyerError.InsufficientZrxLiquidity);
- }
- resultFeeOrders = feeOrdersAndRemainingFeeAmount.resultFeeOrders;
- feeOrdersRemainingFillableMakerAssetAmounts =
- feeOrdersAndRemainingFeeAmount.feeOrdersRemainingFillableMakerAssetAmounts;
- }
-
- // assetData information for the result
- const assetData = orders[0].makerAssetData;
- // compile the resulting trimmed set of orders for makerAsset and feeOrders that are needed for assetBuyAmount
- const trimmedOrdersAndFillableAmounts: OrdersAndFillableAmounts = {
- orders: resultOrders,
- remainingFillableMakerAssetAmounts: ordersRemainingFillableMakerAssetAmounts,
- };
- const trimmedFeeOrdersAndFillableAmounts: OrdersAndFillableAmounts = {
- orders: resultFeeOrders,
- remainingFillableMakerAssetAmounts: feeOrdersRemainingFillableMakerAssetAmounts,
- };
- const bestCaseQuoteInfo = calculateQuoteInfo(
- trimmedOrdersAndFillableAmounts,
- trimmedFeeOrdersAndFillableAmounts,
- assetBuyAmount,
- feePercentage,
- isMakerAssetZrxToken,
- );
- // in order to calculate the maxRate, reverse the ordersAndFillableAmounts such that they are sorted from worst rate to best rate
- const worstCaseQuoteInfo = calculateQuoteInfo(
- reverseOrdersAndFillableAmounts(trimmedOrdersAndFillableAmounts),
- reverseOrdersAndFillableAmounts(trimmedFeeOrdersAndFillableAmounts),
- assetBuyAmount,
- feePercentage,
- isMakerAssetZrxToken,
- );
- return {
- assetData,
- orders: resultOrders,
- feeOrders: resultFeeOrders,
- bestCaseQuoteInfo,
- worstCaseQuoteInfo,
- assetBuyAmount,
- feePercentage,
- };
- },
-};
-
-function calculateQuoteInfo(
- ordersAndFillableAmounts: OrdersAndFillableAmounts,
- feeOrdersAndFillableAmounts: OrdersAndFillableAmounts,
- assetBuyAmount: BigNumber,
- feePercentage: number,
- isMakerAssetZrxToken: boolean,
-): BuyQuoteInfo {
- // find the total eth and zrx needed to buy assetAmount from the resultOrders from left to right
- let assetEthAmount = constants.ZERO_AMOUNT;
- let zrxEthAmount = constants.ZERO_AMOUNT;
- if (isMakerAssetZrxToken) {
- assetEthAmount = findEthAmountNeededToBuyZrx(ordersAndFillableAmounts, assetBuyAmount);
- } else {
- // find eth and zrx amounts needed to buy
- const ethAndZrxAmountToBuyAsset = findEthAndZrxAmountNeededToBuyAsset(ordersAndFillableAmounts, assetBuyAmount);
- assetEthAmount = ethAndZrxAmountToBuyAsset[0];
- const zrxAmountToBuyAsset = ethAndZrxAmountToBuyAsset[1];
- // find eth amount needed to buy zrx
- zrxEthAmount = findEthAmountNeededToBuyZrx(feeOrdersAndFillableAmounts, zrxAmountToBuyAsset);
- }
- // eth amount needed to buy the affiliate fee
- const affiliateFeeEthAmount = assetEthAmount.multipliedBy(feePercentage).integerValue(BigNumber.ROUND_CEIL);
- // eth amount needed for fees is the sum of affiliate fee and zrx fee
- const feeEthAmount = affiliateFeeEthAmount.plus(zrxEthAmount);
- // eth amount needed in total is the sum of the amount needed for the asset and the amount needed for fees
- const totalEthAmount = assetEthAmount.plus(feeEthAmount);
- return {
- assetEthAmount,
- feeEthAmount,
- totalEthAmount,
- };
-}
-
-// given an OrdersAndFillableAmounts, reverse the orders and remainingFillableMakerAssetAmounts properties
-function reverseOrdersAndFillableAmounts(ordersAndFillableAmounts: OrdersAndFillableAmounts): OrdersAndFillableAmounts {
- const ordersCopy = _.clone(ordersAndFillableAmounts.orders);
- const remainingFillableMakerAssetAmountsCopy = _.clone(ordersAndFillableAmounts.remainingFillableMakerAssetAmounts);
- return {
- orders: ordersCopy.reverse(),
- remainingFillableMakerAssetAmounts: remainingFillableMakerAssetAmountsCopy.reverse(),
- };
-}
-
-function findEthAmountNeededToBuyZrx(
- feeOrdersAndFillableAmounts: OrdersAndFillableAmounts,
- zrxBuyAmount: BigNumber,
-): BigNumber {
- const { orders, remainingFillableMakerAssetAmounts } = feeOrdersAndFillableAmounts;
- const result = _.reduce(
- orders,
- (acc, order, index) => {
- const { totalEthAmount, remainingZrxBuyAmount } = acc;
- const remainingFillableMakerAssetAmount = remainingFillableMakerAssetAmounts[index];
- const makerFillAmount = BigNumber.min(remainingZrxBuyAmount, remainingFillableMakerAssetAmount);
- const [takerFillAmount, adjustedMakerFillAmount] = orderUtils.getTakerFillAmountForFeeOrder(
- order,
- makerFillAmount,
- );
- const extraFeeAmount = remainingFillableMakerAssetAmount.isGreaterThanOrEqualTo(adjustedMakerFillAmount)
- ? constants.ZERO_AMOUNT
- : adjustedMakerFillAmount.minus(makerFillAmount);
- return {
- totalEthAmount: totalEthAmount.plus(takerFillAmount),
- remainingZrxBuyAmount: BigNumber.max(
- constants.ZERO_AMOUNT,
- remainingZrxBuyAmount.minus(makerFillAmount).plus(extraFeeAmount),
- ),
- };
- },
- {
- totalEthAmount: constants.ZERO_AMOUNT,
- remainingZrxBuyAmount: zrxBuyAmount,
- },
- );
- return result.totalEthAmount;
-}
-
-function findEthAndZrxAmountNeededToBuyAsset(
- ordersAndFillableAmounts: OrdersAndFillableAmounts,
- assetBuyAmount: BigNumber,
-): [BigNumber, BigNumber] {
- const { orders, remainingFillableMakerAssetAmounts } = ordersAndFillableAmounts;
- const result = _.reduce(
- orders,
- (acc, order, index) => {
- const { totalEthAmount, totalZrxAmount, remainingAssetBuyAmount } = acc;
- const remainingFillableMakerAssetAmount = remainingFillableMakerAssetAmounts[index];
- const makerFillAmount = BigNumber.min(acc.remainingAssetBuyAmount, remainingFillableMakerAssetAmount);
- const takerFillAmount = orderUtils.getTakerFillAmount(order, makerFillAmount);
- const takerFeeAmount = orderUtils.getTakerFeeAmount(order, takerFillAmount);
- return {
- totalEthAmount: totalEthAmount.plus(takerFillAmount),
- totalZrxAmount: totalZrxAmount.plus(takerFeeAmount),
- remainingAssetBuyAmount: BigNumber.max(
- constants.ZERO_AMOUNT,
- remainingAssetBuyAmount.minus(makerFillAmount),
- ),
- };
- },
- {
- totalEthAmount: constants.ZERO_AMOUNT,
- totalZrxAmount: constants.ZERO_AMOUNT,
- remainingAssetBuyAmount: assetBuyAmount,
- },
- );
- return [result.totalEthAmount, result.totalZrxAmount];
-}