diff options
Diffstat (limited to 'packages/asset-buyer/src')
-rw-r--r-- | packages/asset-buyer/src/asset_buyer.ts | 46 | ||||
-rw-r--r-- | packages/asset-buyer/src/index.ts | 3 | ||||
-rw-r--r-- | packages/asset-buyer/src/types.ts | 19 | ||||
-rw-r--r-- | packages/asset-buyer/src/utils/calculate_liquidity.ts | 34 |
4 files changed, 98 insertions, 4 deletions
diff --git a/packages/asset-buyer/src/asset_buyer.ts b/packages/asset-buyer/src/asset_buyer.ts index 934410c55..ad4b3bb60 100644 --- a/packages/asset-buyer/src/asset_buyer.ts +++ b/packages/asset-buyer/src/asset_buyer.ts @@ -16,14 +16,16 @@ import { BuyQuote, BuyQuoteExecutionOpts, BuyQuoteRequestOpts, + LiquidityForAssetData, + LiquidityRequestOpts, OrderProvider, - OrderProviderResponse, OrdersAndFillableAmounts, } from './types'; import { assert } from './utils/assert'; import { assetDataUtils } from './utils/asset_data_utils'; import { buyQuoteCalculator } from './utils/buy_quote_calculator'; +import { calculateLiquidity } from './utils/calculate_liquidity'; import { orderProviderResponseProcessor } from './utils/order_provider_response_processor'; interface OrdersEntry { @@ -138,10 +140,10 @@ export class AssetBuyer { // get the relevant orders for the makerAsset and fees // if the requested assetData is ZRX, don't get the fee info const [ordersAndFillableAmounts, feeOrdersAndFillableAmounts] = await Promise.all([ - this._getOrdersAndFillableAmountsAsync(assetData, shouldForceOrderRefresh), + this.getOrdersAndFillableAmountsAsync(assetData, shouldForceOrderRefresh), isMakerAssetZrxToken ? Promise.resolve(constants.EMPTY_ORDERS_AND_FILLABLE_AMOUNTS) - : this._getOrdersAndFillableAmountsAsync(zrxTokenAssetData, shouldForceOrderRefresh), + : this.getOrdersAndFillableAmountsAsync(zrxTokenAssetData, shouldForceOrderRefresh), shouldForceOrderRefresh, ]); if (ordersAndFillableAmounts.orders.length === 0) { @@ -178,6 +180,40 @@ export class AssetBuyer { return buyQuote; } /** + * Returns information about available liquidity for an asset + * Does not factor in slippage or fees + * @param assetData The assetData of the desired asset to buy (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md). + * @param options Options for the request. See type definition for more information. + * + * @return An object that conforms to LiquidityForAssetData that satisfies the request. See type definition for more information. + */ + public async getLiquidityForAssetDataAsync( + assetData: string, + options: Partial<LiquidityRequestOpts> = {}, + ): Promise<LiquidityForAssetData> { + const shouldForceOrderRefresh = + options.shouldForceOrderRefresh !== undefined ? options.shouldForceOrderRefresh : false; + assetDataUtils.decodeAssetDataOrThrow(assetData); + assert.isBoolean('options.shouldForceOrderRefresh', shouldForceOrderRefresh); + + const assetPairs = await this.orderProvider.getAvailableMakerAssetDatasAsync(assetData); + const etherTokenAssetData = this._getEtherTokenAssetDataOrThrow(); + if (!assetPairs.includes(etherTokenAssetData)) { + return { + tokensAvailableInBaseUnits: new BigNumber(0), + ethValueAvailableInWei: new BigNumber(0), + }; + } + + const ordersAndFillableAmounts = await this.getOrdersAndFillableAmountsAsync( + assetData, + shouldForceOrderRefresh, + ); + + return calculateLiquidity(ordersAndFillableAmounts); + } + + /** * Given a BuyQuote and desired rate, attempt to execute the buy. * @param buyQuote An object that conforms to BuyQuote. See type definition for more information. * @param options Options for the execution of the BuyQuote. See type definition for more information. @@ -260,8 +296,10 @@ export class AssetBuyer { } /** * Grab orders from the map, if there is a miss or it is time to refresh, fetch and process the orders + * @param assetData The assetData of the desired asset to buy (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md). + * @param shouldForceOrderRefresh If set to true, new orders and state will be fetched instead of waiting for the next orderRefreshIntervalMs. */ - private async _getOrdersAndFillableAmountsAsync( + public async getOrdersAndFillableAmountsAsync( assetData: string, shouldForceOrderRefresh: boolean, ): Promise<OrdersAndFillableAmounts> { diff --git a/packages/asset-buyer/src/index.ts b/packages/asset-buyer/src/index.ts index a42d7e272..f69cfad69 100644 --- a/packages/asset-buyer/src/index.ts +++ b/packages/asset-buyer/src/index.ts @@ -19,6 +19,9 @@ export { BuyQuoteExecutionOpts, BuyQuoteInfo, BuyQuoteRequestOpts, + LiquidityForAssetData, + LiquidityRequestOpts, + OrdersAndFillableAmounts, OrderProvider, OrderProviderRequest, OrderProviderResponse, diff --git a/packages/asset-buyer/src/types.ts b/packages/asset-buyer/src/types.ts index d5d6be695..46a2338ce 100644 --- a/packages/asset-buyer/src/types.ts +++ b/packages/asset-buyer/src/types.ts @@ -75,6 +75,13 @@ export interface BuyQuoteRequestOpts { slippagePercentage: number; } +/* + * Options for checking liquidity + * + * shouldForceOrderRefresh: If set to true, new orders and state will be fetched instead of waiting for the next orderRefreshIntervalMs. Defaults to false. + */ +export type LiquidityRequestOpts = Pick<BuyQuoteRequestOpts, 'shouldForceOrderRefresh'>; + /** * ethAmount: The desired amount of eth to spend. Defaults to buyQuote.worstCaseQuoteInfo.totalEthAmount. * takerAddress: The address to perform the buy. Defaults to the first available address from the provider. @@ -117,7 +124,19 @@ export enum AssetBuyerError { TransactionValueTooLow = 'TRANSACTION_VALUE_TOO_LOW', } +/** + * orders: An array of signed orders + * remainingFillableMakerAssetAmounts: A list of fillable amounts for the signed orders. The index of an item in the array associates the amount with the corresponding order. + */ export interface OrdersAndFillableAmounts { orders: SignedOrder[]; remainingFillableMakerAssetAmounts: BigNumber[]; } + +/** + * Represents available liquidity for a given assetData + */ +export interface LiquidityForAssetData { + tokensAvailableInBaseUnits: BigNumber; + ethValueAvailableInWei: BigNumber; +} diff --git a/packages/asset-buyer/src/utils/calculate_liquidity.ts b/packages/asset-buyer/src/utils/calculate_liquidity.ts new file mode 100644 index 000000000..a8d165b4b --- /dev/null +++ b/packages/asset-buyer/src/utils/calculate_liquidity.ts @@ -0,0 +1,34 @@ +import { BigNumber } from '@0x/utils'; + +import { LiquidityForAssetData, OrdersAndFillableAmounts } from '../types'; + +import { orderUtils } from './order_utils'; + +export const calculateLiquidity = (ordersAndFillableAmounts: OrdersAndFillableAmounts): LiquidityForAssetData => { + const { orders, remainingFillableMakerAssetAmounts } = ordersAndFillableAmounts; + const liquidityInBigNumbers = orders.reduce( + (acc, order, curIndex) => { + const availableMakerAssetAmount = remainingFillableMakerAssetAmounts[curIndex]; + if (availableMakerAssetAmount === undefined) { + throw new Error(`No corresponding fillableMakerAssetAmounts at index ${curIndex}`); + } + + const tokensAvailableForCurrentOrder = availableMakerAssetAmount; + const ethValueAvailableForCurrentOrder = orderUtils.getTakerFillAmount(order, availableMakerAssetAmount); + return { + tokensAvailableInBaseUnits: acc.tokensAvailableInBaseUnits.plus(tokensAvailableForCurrentOrder), + ethValueAvailableInWei: acc.ethValueAvailableInWei.plus(ethValueAvailableForCurrentOrder), + }; + }, + { + tokensAvailableInBaseUnits: new BigNumber(0), + ethValueAvailableInWei: new BigNumber(0), + }, + ); + + // Turn into regular numbers + return { + tokensAvailableInBaseUnits: liquidityInBigNumbers.tokensAvailableInBaseUnits, + ethValueAvailableInWei: liquidityInBigNumbers.ethValueAvailableInWei, + }; +}; |