aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Klebanoff <steve@0xproject.com>2019-01-18 08:01:36 +0800
committerGitHub <noreply@github.com>2019-01-18 08:01:36 +0800
commit2b64661c61eaedffe5debfdf1aa4210dcdb02f52 (patch)
treeafaf4bee361bff7b0b8a64bc2014f9979ee2b2b6
parent9c29eecc306ca2830495a49e5ba3ea563807b2d9 (diff)
parent25b58108bc486f09d507ee535112887c2ea813a5 (diff)
downloaddexon-sol-tools-2b64661c61eaedffe5debfdf1aa4210dcdb02f52.tar
dexon-sol-tools-2b64661c61eaedffe5debfdf1aa4210dcdb02f52.tar.gz
dexon-sol-tools-2b64661c61eaedffe5debfdf1aa4210dcdb02f52.tar.bz2
dexon-sol-tools-2b64661c61eaedffe5debfdf1aa4210dcdb02f52.tar.lz
dexon-sol-tools-2b64661c61eaedffe5debfdf1aa4210dcdb02f52.tar.xz
dexon-sol-tools-2b64661c61eaedffe5debfdf1aa4210dcdb02f52.tar.zst
dexon-sol-tools-2b64661c61eaedffe5debfdf1aa4210dcdb02f52.zip
Merge pull request #1512 from 0xProject/feature/instant/asset-buyer-check-liquidity
[instant] [asset-buyer] Helper methods for checking liquidity
-rw-r--r--packages/asset-buyer/CHANGELOG.json9
-rw-r--r--packages/asset-buyer/package.json1
-rw-r--r--packages/asset-buyer/src/asset_buyer.ts46
-rw-r--r--packages/asset-buyer/src/index.ts3
-rw-r--r--packages/asset-buyer/src/types.ts19
-rw-r--r--packages/asset-buyer/src/utils/calculate_liquidity.ts34
-rw-r--r--packages/asset-buyer/test/asset_buyer_test.ts212
-rw-r--r--packages/asset-buyer/test/utils/mocks.ts68
-rw-r--r--packages/instant/src/index.umd.ts42
-rw-r--r--yarn.lock12
10 files changed, 442 insertions, 4 deletions
diff --git a/packages/asset-buyer/CHANGELOG.json b/packages/asset-buyer/CHANGELOG.json
index 2428a33ed..3bb95fdba 100644
--- a/packages/asset-buyer/CHANGELOG.json
+++ b/packages/asset-buyer/CHANGELOG.json
@@ -1,5 +1,14 @@
[
{
+ "version": "4.1.0",
+ "changes": [
+ {
+ "note": "Adds new public method getLiquidityForAssetDataAsync, and exposes getOrdersAndFillableAmountsAsync as public method",
+ "pr": 1512
+ }
+ ]
+ },
+ {
"timestamp": 1547747677,
"version": "4.0.2",
"changes": [
diff --git a/packages/asset-buyer/package.json b/packages/asset-buyer/package.json
index 8317d1f8d..454e9cc1c 100644
--- a/packages/asset-buyer/package.json
+++ b/packages/asset-buyer/package.json
@@ -65,6 +65,7 @@
"shx": "^0.2.2",
"tslint": "5.11.0",
"typedoc": "0.13.0",
+ "typemoq": "^2.1.0",
"typescript": "3.0.1"
},
"publishConfig": {
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,
+ };
+};
diff --git a/packages/asset-buyer/test/asset_buyer_test.ts b/packages/asset-buyer/test/asset_buyer_test.ts
new file mode 100644
index 000000000..f117b4d7a
--- /dev/null
+++ b/packages/asset-buyer/test/asset_buyer_test.ts
@@ -0,0 +1,212 @@
+import { orderFactory } from '@0x/order-utils/lib/src/order_factory';
+import { Web3ProviderEngine } from '@0x/subproviders';
+import { SignedOrder } from '@0x/types';
+import { BigNumber } from '@0x/utils';
+import { Web3Wrapper } from '@0x/web3-wrapper';
+import * as chai from 'chai';
+import 'mocha';
+import * as TypeMoq from 'typemoq';
+
+import { AssetBuyer } from '../src';
+import { constants } from '../src/constants';
+import { LiquidityForAssetData, OrderProvider, OrdersAndFillableAmounts } from '../src/types';
+
+import { chaiSetup } from './utils/chai_setup';
+import {
+ mockAvailableAssetDatas,
+ mockedAssetBuyerWithOrdersAndFillableAmounts,
+ orderProviderMock,
+} from './utils/mocks';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+const FAKE_SRA_URL = 'https://fakeurl.com';
+const FAKE_ASSET_DATA = '0xf47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48';
+const TOKEN_DECIMALS = 18;
+const DAI_ASSET_DATA = '0xf47261b000000000000000000000000089d24a6b4ccb1b6faa2625fe562bdd9a23260359"';
+const WETH_ASSET_DATA = '0xf47261b0000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2';
+const WETH_DECIMALS = constants.ETHER_TOKEN_DECIMALS;
+
+const baseUnitAmount = (unitAmount: number, decimals = TOKEN_DECIMALS): BigNumber => {
+ return Web3Wrapper.toBaseUnitAmount(new BigNumber(unitAmount), decimals);
+};
+
+const expectLiquidityResult = async (
+ web3Provider: Web3ProviderEngine,
+ orderProvider: OrderProvider,
+ ordersAndFillableAmounts: OrdersAndFillableAmounts,
+ expectedLiquidityResult: LiquidityForAssetData,
+) => {
+ const mockedAssetBuyer = mockedAssetBuyerWithOrdersAndFillableAmounts(
+ web3Provider,
+ orderProvider,
+ FAKE_ASSET_DATA,
+ ordersAndFillableAmounts,
+ );
+ const liquidityResult = await mockedAssetBuyer.object.getLiquidityForAssetDataAsync(FAKE_ASSET_DATA);
+ expect(liquidityResult).to.deep.equal(expectedLiquidityResult);
+};
+
+// tslint:disable:custom-no-magic-numbers
+describe('AssetBuyer', () => {
+ describe('getLiquidityForAssetDataAsync', () => {
+ const mockWeb3Provider = TypeMoq.Mock.ofType(Web3ProviderEngine);
+ const mockOrderProvider = orderProviderMock();
+
+ beforeEach(() => {
+ mockWeb3Provider.reset();
+ mockOrderProvider.reset();
+ });
+
+ afterEach(() => {
+ mockWeb3Provider.verifyAll();
+ mockOrderProvider.verifyAll();
+ });
+
+ describe('validation', () => {
+ it('should ensure assetData is a string', async () => {
+ const assetBuyer = AssetBuyer.getAssetBuyerForStandardRelayerAPIUrl(
+ mockWeb3Provider.object,
+ FAKE_SRA_URL,
+ );
+
+ expect(assetBuyer.getLiquidityForAssetDataAsync(false as any)).to.be.rejectedWith(
+ 'Expected assetData to be of type string, encountered: false',
+ );
+ });
+ });
+
+ describe('asset pair not supported', () => {
+ it('should return 0s when no asset pair not supported', async () => {
+ mockAvailableAssetDatas(mockOrderProvider, FAKE_ASSET_DATA, []);
+
+ const assetBuyer = new AssetBuyer(mockWeb3Provider.object, mockOrderProvider.object);
+ const liquidityResult = await assetBuyer.getLiquidityForAssetDataAsync(FAKE_ASSET_DATA);
+ expect(liquidityResult).to.deep.equal({
+ tokensAvailableInBaseUnits: new BigNumber(0),
+ ethValueAvailableInWei: new BigNumber(0),
+ });
+ });
+ it('should return 0s when only other asset pair supported', async () => {
+ mockAvailableAssetDatas(mockOrderProvider, FAKE_ASSET_DATA, [DAI_ASSET_DATA]);
+
+ const assetBuyer = new AssetBuyer(mockWeb3Provider.object, mockOrderProvider.object);
+ const liquidityResult = await assetBuyer.getLiquidityForAssetDataAsync(FAKE_ASSET_DATA);
+ expect(liquidityResult).to.deep.equal({
+ tokensAvailableInBaseUnits: new BigNumber(0),
+ ethValueAvailableInWei: new BigNumber(0),
+ });
+ });
+ });
+
+ describe('assetData is supported', () => {
+ // orders
+ const sellTwoTokensFor1Weth: SignedOrder = orderFactory.createSignedOrderFromPartial({
+ makerAssetAmount: baseUnitAmount(2),
+ takerAssetAmount: baseUnitAmount(1, WETH_DECIMALS),
+ });
+ const sellTenTokensFor10Weth: SignedOrder = orderFactory.createSignedOrderFromPartial({
+ makerAssetAmount: baseUnitAmount(10),
+ takerAssetAmount: baseUnitAmount(10, WETH_DECIMALS),
+ });
+
+ beforeEach(() => {
+ mockAvailableAssetDatas(mockOrderProvider, FAKE_ASSET_DATA, [WETH_ASSET_DATA]);
+ });
+
+ it('should return 0s when no orders available', async () => {
+ const ordersAndFillableAmounts: OrdersAndFillableAmounts = {
+ orders: [],
+ remainingFillableMakerAssetAmounts: [],
+ };
+ const expectedResult = {
+ tokensAvailableInBaseUnits: new BigNumber(0),
+ ethValueAvailableInWei: new BigNumber(0),
+ };
+ await expectLiquidityResult(
+ mockWeb3Provider.object,
+ mockOrderProvider.object,
+ ordersAndFillableAmounts,
+ expectedResult,
+ );
+ });
+
+ it('should return correct computed value when orders provided with full fillableAmounts', async () => {
+ const orders: SignedOrder[] = [sellTwoTokensFor1Weth, sellTenTokensFor10Weth];
+ const ordersAndFillableAmounts = {
+ orders: [sellTwoTokensFor1Weth, sellTenTokensFor10Weth],
+ remainingFillableMakerAssetAmounts: orders.map(o => o.makerAssetAmount),
+ };
+
+ const expectedTokensAvailable = orders[0].makerAssetAmount.plus(orders[1].makerAssetAmount);
+ const expectedEthValueAvailable = orders[0].takerAssetAmount.plus(orders[1].takerAssetAmount);
+ const expectedResult = {
+ tokensAvailableInBaseUnits: expectedTokensAvailable,
+ ethValueAvailableInWei: expectedEthValueAvailable,
+ };
+
+ await expectLiquidityResult(
+ mockWeb3Provider.object,
+ mockOrderProvider.object,
+ ordersAndFillableAmounts,
+ expectedResult,
+ );
+ });
+
+ it('should return correct computed value with one partial fillableAmounts', async () => {
+ const ordersAndFillableAmounts = {
+ orders: [sellTwoTokensFor1Weth],
+ remainingFillableMakerAssetAmounts: [baseUnitAmount(1)],
+ };
+ const expectedResult = {
+ tokensAvailableInBaseUnits: baseUnitAmount(1),
+ ethValueAvailableInWei: baseUnitAmount(0.5, WETH_DECIMALS),
+ };
+
+ await expectLiquidityResult(
+ mockWeb3Provider.object,
+ mockOrderProvider.object,
+ ordersAndFillableAmounts,
+ expectedResult,
+ );
+ });
+
+ it('should return correct computed value with multiple orders and fillable amounts', async () => {
+ const ordersAndFillableAmounts = {
+ orders: [sellTwoTokensFor1Weth, sellTenTokensFor10Weth],
+ remainingFillableMakerAssetAmounts: [baseUnitAmount(1), baseUnitAmount(3)],
+ };
+ const expectedResult = {
+ tokensAvailableInBaseUnits: baseUnitAmount(4),
+ ethValueAvailableInWei: baseUnitAmount(3.5, WETH_DECIMALS),
+ };
+
+ await expectLiquidityResult(
+ mockWeb3Provider.object,
+ mockOrderProvider.object,
+ ordersAndFillableAmounts,
+ expectedResult,
+ );
+ });
+
+ it('should return 0s when no amounts fillable', async () => {
+ const ordersAndFillableAmounts = {
+ orders: [sellTwoTokensFor1Weth, sellTenTokensFor10Weth],
+ remainingFillableMakerAssetAmounts: [baseUnitAmount(0), baseUnitAmount(0)],
+ };
+ const expectedResult = {
+ tokensAvailableInBaseUnits: baseUnitAmount(0),
+ ethValueAvailableInWei: baseUnitAmount(0, WETH_DECIMALS),
+ };
+
+ await expectLiquidityResult(
+ mockWeb3Provider.object,
+ mockOrderProvider.object,
+ ordersAndFillableAmounts,
+ expectedResult,
+ );
+ });
+ });
+ });
+});
diff --git a/packages/asset-buyer/test/utils/mocks.ts b/packages/asset-buyer/test/utils/mocks.ts
new file mode 100644
index 000000000..d3e1c09c4
--- /dev/null
+++ b/packages/asset-buyer/test/utils/mocks.ts
@@ -0,0 +1,68 @@
+import { Web3ProviderEngine } from '@0x/subproviders';
+import * as TypeMoq from 'typemoq';
+
+import { AssetBuyer } from '../../src/asset_buyer';
+import { OrderProvider, OrderProviderResponse, OrdersAndFillableAmounts } from '../../src/types';
+
+// tslint:disable:promise-function-async
+
+// Implementing dummy class for using in mocks, see https://github.com/florinn/typemoq/issues/3
+class OrderProviderClass implements OrderProvider {
+ // tslint:disable-next-line:prefer-function-over-method
+ public async getOrdersAsync(): Promise<OrderProviderResponse> {
+ return Promise.resolve({ orders: [] });
+ }
+ // tslint:disable-next-line:prefer-function-over-method
+ public async getAvailableMakerAssetDatasAsync(takerAssetData: string): Promise<string[]> {
+ return Promise.resolve([]);
+ }
+}
+
+export const orderProviderMock = () => {
+ return TypeMoq.Mock.ofType(OrderProviderClass, TypeMoq.MockBehavior.Strict);
+};
+
+export const mockAvailableAssetDatas = (
+ mockOrderProvider: TypeMoq.IMock<OrderProviderClass>,
+ assetData: string,
+ availableAssetDatas: string[],
+) => {
+ mockOrderProvider
+ .setup(op => op.getAvailableMakerAssetDatasAsync(TypeMoq.It.isValue(assetData)))
+ .returns(() => {
+ return Promise.resolve(availableAssetDatas);
+ })
+ .verifiable(TypeMoq.Times.once());
+};
+
+const partiallyMockedAssetBuyer = (
+ provider: Web3ProviderEngine,
+ orderProvider: OrderProvider,
+): TypeMoq.IMock<AssetBuyer> => {
+ const rawAssetBuyer = new AssetBuyer(provider, orderProvider);
+ const mockedAssetBuyer = TypeMoq.Mock.ofInstance(rawAssetBuyer, TypeMoq.MockBehavior.Loose, false);
+ mockedAssetBuyer.callBase = true;
+ return mockedAssetBuyer;
+};
+
+const mockGetOrdersAndAvailableAmounts = (
+ mockedAssetBuyer: TypeMoq.IMock<AssetBuyer>,
+ assetData: string,
+ ordersAndFillableAmounts: OrdersAndFillableAmounts,
+): void => {
+ mockedAssetBuyer
+ .setup(a => a.getOrdersAndFillableAmountsAsync(assetData, false))
+ .returns(() => Promise.resolve(ordersAndFillableAmounts))
+ .verifiable(TypeMoq.Times.once());
+};
+
+export const mockedAssetBuyerWithOrdersAndFillableAmounts = (
+ provider: Web3ProviderEngine,
+ orderProvider: OrderProvider,
+ assetData: string,
+ ordersAndFillableAmounts: OrdersAndFillableAmounts,
+): TypeMoq.IMock<AssetBuyer> => {
+ const mockedAssetBuyer = partiallyMockedAssetBuyer(provider, orderProvider);
+ mockGetOrdersAndAvailableAmounts(mockedAssetBuyer, assetData, ordersAndFillableAmounts);
+ return mockedAssetBuyer;
+};
diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts
index d172f4145..0acf3f2ad 100644
--- a/packages/instant/src/index.umd.ts
+++ b/packages/instant/src/index.umd.ts
@@ -1,3 +1,6 @@
+import { AssetBuyer, BigNumber } from '@0x/asset-buyer';
+import { assetDataUtils } from '@0x/order-utils';
+import { Provider } from 'ethereum-types';
import * as _ from 'lodash';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
@@ -9,9 +12,12 @@ import {
INJECTED_DIV_ID,
NPM_PACKAGE_VERSION,
} from './constants';
+import { assetMetaDataMap } from './data/asset_meta_data_map';
import { ZeroExInstantOverlay, ZeroExInstantOverlayProps } from './index';
+import { Network, OrderSource } from './types';
import { analytics } from './util/analytics';
import { assert } from './util/assert';
+import { providerFactory } from './util/provider_factory';
import { util } from './util/util';
const isInstantRendered = (): boolean => !!document.getElementById(INJECTED_DIV_ID);
@@ -122,6 +128,42 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z
window.onpopstate = onPopStateHandler;
};
+export const assetDataForERC20TokenAddress = (tokenAddress: string): string => {
+ assert.isETHAddressHex('tokenAddress', tokenAddress);
+ return assetDataUtils.encodeERC20AssetData(tokenAddress);
+};
+
+export const hasMetaDataForAssetData = (assetData: string): boolean => {
+ assert.isHexString('assetData', assetData);
+ return assetMetaDataMap[assetData] !== undefined;
+};
+
+export const hasLiquidityForAssetDataAsync = async (
+ assetData: string,
+ orderSource: OrderSource,
+ networkId: Network = Network.Mainnet,
+ provider?: Provider,
+): Promise<boolean> => {
+ assert.isHexString('assetData', assetData);
+ assert.isValidOrderSource('orderSource', orderSource);
+ assert.isNumber('networkId', networkId);
+
+ if (provider !== undefined) {
+ assert.isWeb3Provider('provider', provider);
+ }
+
+ const bestProvider: Provider = provider || providerFactory.getFallbackNoSigningProvider(networkId);
+
+ const assetBuyerOptions = { networkId };
+
+ const assetBuyer = _.isString(orderSource)
+ ? AssetBuyer.getAssetBuyerForStandardRelayerAPIUrl(bestProvider, orderSource, assetBuyerOptions)
+ : AssetBuyer.getAssetBuyerForProvidedOrders(bestProvider, orderSource, assetBuyerOptions);
+
+ const liquidity = await assetBuyer.getLiquidityForAssetDataAsync(assetData);
+ return liquidity.ethValueAvailableInWei.gt(new BigNumber(0));
+};
+
// Write version info to the exported object for debugging
export const GIT_SHA = GIT_SHA_FROM_CONSTANT;
export const NPM_VERSION = NPM_PACKAGE_VERSION;
diff --git a/yarn.lock b/yarn.lock
index c7c19b4f4..7e0046213 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -12928,6 +12928,10 @@ postgres-interval@^1.1.0:
dependencies:
xtend "^4.0.0"
+postinstall-build@^5.0.1:
+ version "5.0.3"
+ resolved "https://registry.yarnpkg.com/postinstall-build/-/postinstall-build-5.0.3.tgz#238692f712a481d8f5bc8960e94786036241efc7"
+
prebuild-install@^2.2.2:
version "2.5.3"
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-2.5.3.tgz#9f65f242782d370296353710e9bc843490c19f69"
@@ -16689,6 +16693,14 @@ typedoc@0.13.0:
typedoc-default-themes "^0.5.0"
typescript "3.1.x"
+typemoq@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/typemoq/-/typemoq-2.1.0.tgz#4452ce360d92cf2a1a180f0c29de2803f87af1e8"
+ dependencies:
+ circular-json "^0.3.1"
+ lodash "^4.17.4"
+ postinstall-build "^5.0.1"
+
typeorm@^0.2.7:
version "0.2.11"
resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.2.11.tgz#d81a295ed822e05043f2920cd539f52a963896b0"