aboutsummaryrefslogtreecommitdiffstats
path: root/packages/asset-buyer/src/utils/buy_quote_calculator.ts
diff options
context:
space:
mode:
authorFrancesco Agosti <francesco.agosti93@gmail.com>2018-09-24 23:47:59 +0800
committerGitHub <noreply@github.com>2018-09-24 23:47:59 +0800
commitb830c28d83a33c0170d4f150ee287ea97ccf7865 (patch)
tree34aa214865e941723a66b34fd45c59036015ae53 /packages/asset-buyer/src/utils/buy_quote_calculator.ts
parent4a316571ff9b539a540f0503b5753eb03509fea8 (diff)
parentd8d1c98a40f5cc895329f73af4d8d000c6a5195b (diff)
downloaddexon-0x-contracts-b830c28d83a33c0170d4f150ee287ea97ccf7865.tar.gz
dexon-0x-contracts-b830c28d83a33c0170d4f150ee287ea97ccf7865.tar.zst
dexon-0x-contracts-b830c28d83a33c0170d4f150ee287ea97ccf7865.zip
Merge pull request #1037 from 0xProject/feature/forwarder-helper/sra-and-rpc
[asset-buyer] Create new AssetBuyer class
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,
+ };
+ },
+};