From a9fad77eb4375439767f9aa1fcbfa12716f41ed3 Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Tue, 8 Jan 2019 08:57:36 -0800 Subject: Implement liquidity checking w/ testing --- packages/asset-buyer/package.json | 1 + packages/asset-buyer/src/asset_buyer.ts | 67 +++++++++- packages/asset-buyer/src/types.ts | 8 ++ packages/asset-buyer/test/asset_buyer_test.ts | 168 ++++++++++++++++++++++++++ packages/asset-buyer/test/utils/mocks.ts | 66 ++++++++++ 5 files changed, 307 insertions(+), 3 deletions(-) create mode 100644 packages/asset-buyer/test/asset_buyer_test.ts create mode 100644 packages/asset-buyer/test/utils/mocks.ts (limited to 'packages/asset-buyer') diff --git a/packages/asset-buyer/package.json b/packages/asset-buyer/package.json index 401aec120..9ddeb2c60 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..511c99fb1 100644 --- a/packages/asset-buyer/src/asset_buyer.ts +++ b/packages/asset-buyer/src/asset_buyer.ts @@ -16,6 +16,7 @@ import { BuyQuote, BuyQuoteExecutionOpts, BuyQuoteRequestOpts, + LiquidityForAssetData, OrderProvider, OrderProviderResponse, OrdersAndFillableAmounts, @@ -25,12 +26,42 @@ import { assert } from './utils/assert'; import { assetDataUtils } from './utils/asset_data_utils'; import { buyQuoteCalculator } from './utils/buy_quote_calculator'; import { orderProviderResponseProcessor } from './utils/order_provider_response_processor'; +import { orderUtils } from './utils/order_utils'; interface OrdersEntry { ordersAndFillableAmounts: OrdersAndFillableAmounts; lastRefreshTime: number; } +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 { + tokensAvailableInUnitAmount: acc.tokensAvailableInUnitAmount.plus(tokensAvailableForCurrentOrder), + ethValueAvailableInWei: acc.ethValueAvailableInWei.plus(ethValueAvailableForCurrentOrder), + }; + }, + { + tokensAvailableInUnitAmount: new BigNumber(0), + ethValueAvailableInWei: new BigNumber(0), + }, + ); + + // Turn into regular numbers + return { + tokensAvailableInUnitAmount: liquidityInBigNumbers.tokensAvailableInUnitAmount.toNumber(), + ethValueAvailableInWei: liquidityInBigNumbers.ethValueAvailableInWei.toNumber(), + }; +}; + export class AssetBuyer { public readonly provider: Provider; public readonly orderProvider: OrderProvider; @@ -138,10 +169,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) { @@ -177,6 +208,36 @@ export class AssetBuyer { const buyQuote = this.getBuyQuoteAsync(assetData, assetBuyAmount, options); return buyQuote; } + public async getLiquidityForAssetDataAsync( + assetData: string, + options: Partial = {}, + ): Promise { + const { feePercentage, shouldForceOrderRefresh, slippagePercentage } = _.merge( + {}, + constants.DEFAULT_BUY_QUOTE_REQUEST_OPTS, + options, + ); + assert.isString('assetData', assetData); + assert.isValidPercentage('feePercentage', feePercentage); + assert.isBoolean('shouldForceOrderRefresh', shouldForceOrderRefresh); + assert.isNumber('slippagePercentage', slippagePercentage); + + const assetPairs = await this.orderProvider.getAvailableMakerAssetDatasAsync(assetData); + if (!assetPairs.includes(assetData)) { + return { + tokensAvailableInUnitAmount: 0, + ethValueAvailableInWei: 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. @@ -261,7 +322,7 @@ export class AssetBuyer { /** * Grab orders from the map, if there is a miss or it is time to refresh, fetch and process the orders */ - private async _getOrdersAndFillableAmountsAsync( + public async getOrdersAndFillableAmountsAsync( assetData: string, shouldForceOrderRefresh: boolean, ): Promise { diff --git a/packages/asset-buyer/src/types.ts b/packages/asset-buyer/src/types.ts index 3b573edca..84434aa7f 100644 --- a/packages/asset-buyer/src/types.ts +++ b/packages/asset-buyer/src/types.ts @@ -121,3 +121,11 @@ export interface OrdersAndFillableAmounts { orders: SignedOrder[]; remainingFillableMakerAssetAmounts: BigNumber[]; } + +/** + * Represents available liquidity for a given assetData + */ +export interface LiquidityForAssetData { + tokensAvailableInUnitAmount: number; + ethValueAvailableInWei: number; +} 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..a109d1ae8 --- /dev/null +++ b/packages/asset-buyer/test/asset_buyer_test.ts @@ -0,0 +1,168 @@ +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 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); +}; + +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', + ); + }); + }); + + it('should return 0s when 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({ + tokensAvailableInUnitAmount: 0, + ethValueAvailableInWei: 0, + }); + }); + + describe('assetData is supported', () => { + // orders + const sellTwoTokensFor1Weth: SignedOrder = orderFactory.createSignedOrderFromPartial({ + makerAssetAmount: baseUnitAmount(2), + takerAssetAmount: baseUnitAmount(1, WETH_DECIMALS), + }); + const sellTenTokensFor10Weth: SignedOrder = orderFactory.createSignedOrderFromPartial({ + // tslint:disable-next-line:custom-no-magic-numbers + makerAssetAmount: baseUnitAmount(10), + // tslint:disable-next-line:custom-no-magic-numbers + takerAssetAmount: baseUnitAmount(10, WETH_DECIMALS), + }); + + beforeEach(() => { + mockAvailableAssetDatas(mockOrderProvider, FAKE_ASSET_DATA, [FAKE_ASSET_DATA]); + }); + + it('should return 0s when no orders available', async () => { + const ordersAndFillableAmounts: OrdersAndFillableAmounts = { + orders: [], + remainingFillableMakerAssetAmounts: [], + }; + const mockedAssetBuyer = mockedAssetBuyerWithOrdersAndFillableAmounts( + mockWeb3Provider.object, + mockOrderProvider.object, + FAKE_ASSET_DATA, + ordersAndFillableAmounts, + ); + + const liquidityResult = await mockedAssetBuyer.object.getLiquidityForAssetDataAsync(FAKE_ASSET_DATA); + expect(liquidityResult).to.deep.equal({ + tokensAvailableInUnitAmount: 0, + ethValueAvailableInWei: 0, + }); + }); + + it('should return correct computed value when orders provided with full fillableAmounts', async () => { + const orders: SignedOrder[] = [sellTwoTokensFor1Weth, sellTenTokensFor10Weth]; + const remainingFillableMakerAssetAmounts: BigNumber[] = orders.map(o => o.makerAssetAmount); + const mockedAssetBuyer = mockedAssetBuyerWithOrdersAndFillableAmounts( + mockWeb3Provider.object, + mockOrderProvider.object, + FAKE_ASSET_DATA, + { + orders, + remainingFillableMakerAssetAmounts, + }, + ); + + const expectedTokensAvailable = orders[0].makerAssetAmount.plus(orders[1].makerAssetAmount); + const expectedEthValueAvailable = orders[0].takerAssetAmount.plus(orders[1].takerAssetAmount); + + const liquidityResult = await mockedAssetBuyer.object.getLiquidityForAssetDataAsync(FAKE_ASSET_DATA); + expect(liquidityResult).to.deep.equal({ + tokensAvailableInUnitAmount: expectedTokensAvailable.toNumber(), + ethValueAvailableInWei: expectedEthValueAvailable.toNumber(), + }); + }); + + it('should return correct computed value with one partial fillableAmounts', async () => { + const ordersAndFillableAmounts = { + orders: [sellTwoTokensFor1Weth], + remainingFillableMakerAssetAmounts: [baseUnitAmount(1)], + }; + + const expectedResult = { + tokensAvailableInUnitAmount: baseUnitAmount(1).toNumber(), + // tslint:disable-next-line:custom-no-magic-numbers + ethValueAvailableInWei: baseUnitAmount(0.5, WETH_DECIMALS).toNumber(), + }; + + 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..fe0d0cbf4 --- /dev/null +++ b/packages/asset-buyer/test/utils/mocks.ts @@ -0,0 +1,66 @@ +import { Web3ProviderEngine } from '@0x/subproviders'; +import * as TypeMoq from 'typemoq'; + +import { AssetBuyer } from '../../src/asset_buyer'; +import { OrderProvider, OrderProviderResponse, OrdersAndFillableAmounts } from '../../src/types'; + +// 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 { + return Promise.resolve({ orders: [] }); + } + // tslint:disable-next-line:prefer-function-over-method + public async getAvailableMakerAssetDatasAsync(takerAssetData: string): Promise { + return Promise.resolve([]); + } +} + +export const orderProviderMock = () => { + return TypeMoq.Mock.ofType(OrderProviderClass, TypeMoq.MockBehavior.Strict); +}; + +export const mockAvailableAssetDatas = ( + mockOrderProvider: TypeMoq.IMock, + 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 => { + 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, + 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 => { + const mockedAssetBuyer = partiallyMockedAssetBuyer(provider, orderProvider); + mockGetOrdersAndAvailableAmounts(mockedAssetBuyer, assetData, ordersAndFillableAmounts); + return mockedAssetBuyer; +}; -- cgit v1.2.3 From 0dade8624c0935a26bed9b9c53a94a8211dabdee Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Thu, 10 Jan 2019 13:51:02 -0800 Subject: Adding more test coverage --- packages/asset-buyer/test/asset_buyer_test.ts | 41 ++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 4 deletions(-) (limited to 'packages/asset-buyer') diff --git a/packages/asset-buyer/test/asset_buyer_test.ts b/packages/asset-buyer/test/asset_buyer_test.ts index a109d1ae8..fd31b9843 100644 --- a/packages/asset-buyer/test/asset_buyer_test.ts +++ b/packages/asset-buyer/test/asset_buyer_test.ts @@ -46,6 +46,7 @@ const expectLiquidityResult = async ( expect(liquidityResult).to.deep.equal(expectedLiquidityResult); }; +// tslint:disable:custom-no-magic-numbers describe('AssetBuyer', () => { describe('getLiquidityForAssetDataAsync', () => { const mockWeb3Provider = TypeMoq.Mock.ofType(Web3ProviderEngine); @@ -92,9 +93,7 @@ describe('AssetBuyer', () => { takerAssetAmount: baseUnitAmount(1, WETH_DECIMALS), }); const sellTenTokensFor10Weth: SignedOrder = orderFactory.createSignedOrderFromPartial({ - // tslint:disable-next-line:custom-no-magic-numbers makerAssetAmount: baseUnitAmount(10), - // tslint:disable-next-line:custom-no-magic-numbers takerAssetAmount: baseUnitAmount(10, WETH_DECIMALS), }); @@ -149,10 +148,8 @@ describe('AssetBuyer', () => { orders: [sellTwoTokensFor1Weth], remainingFillableMakerAssetAmounts: [baseUnitAmount(1)], }; - const expectedResult = { tokensAvailableInUnitAmount: baseUnitAmount(1).toNumber(), - // tslint:disable-next-line:custom-no-magic-numbers ethValueAvailableInWei: baseUnitAmount(0.5, WETH_DECIMALS).toNumber(), }; @@ -163,6 +160,42 @@ describe('AssetBuyer', () => { 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 = { + tokensAvailableInUnitAmount: baseUnitAmount(4).toNumber(), + ethValueAvailableInWei: baseUnitAmount(3.5, WETH_DECIMALS).toNumber(), + }; + + 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 = { + tokensAvailableInUnitAmount: baseUnitAmount(0).toNumber(), + ethValueAvailableInWei: baseUnitAmount(0, WETH_DECIMALS).toNumber(), + }; + + await expectLiquidityResult( + mockWeb3Provider.object, + mockOrderProvider.object, + ordersAndFillableAmounts, + expectedResult, + ); + }); }); }); }); -- cgit v1.2.3 From 2360b8282fe40e1c1b1336b17872b5699bde610e Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Thu, 10 Jan 2019 14:00:16 -0800 Subject: rename tokensAvailableInUnitAmount to tokensAvailableInBaseUnits and use test helpers --- packages/asset-buyer/src/asset_buyer.ts | 8 ++--- packages/asset-buyer/src/types.ts | 2 +- packages/asset-buyer/test/asset_buyer_test.ts | 51 +++++++++++++-------------- 3 files changed, 29 insertions(+), 32 deletions(-) (limited to 'packages/asset-buyer') diff --git a/packages/asset-buyer/src/asset_buyer.ts b/packages/asset-buyer/src/asset_buyer.ts index 511c99fb1..92a99c28c 100644 --- a/packages/asset-buyer/src/asset_buyer.ts +++ b/packages/asset-buyer/src/asset_buyer.ts @@ -45,19 +45,19 @@ const calculateLiquidity = (ordersAndFillableAmounts: OrdersAndFillableAmounts): const tokensAvailableForCurrentOrder = availableMakerAssetAmount; const ethValueAvailableForCurrentOrder = orderUtils.getTakerFillAmount(order, availableMakerAssetAmount); return { - tokensAvailableInUnitAmount: acc.tokensAvailableInUnitAmount.plus(tokensAvailableForCurrentOrder), + tokensAvailableInBaseUnits: acc.tokensAvailableInBaseUnits.plus(tokensAvailableForCurrentOrder), ethValueAvailableInWei: acc.ethValueAvailableInWei.plus(ethValueAvailableForCurrentOrder), }; }, { - tokensAvailableInUnitAmount: new BigNumber(0), + tokensAvailableInBaseUnits: new BigNumber(0), ethValueAvailableInWei: new BigNumber(0), }, ); // Turn into regular numbers return { - tokensAvailableInUnitAmount: liquidityInBigNumbers.tokensAvailableInUnitAmount.toNumber(), + tokensAvailableInBaseUnits: liquidityInBigNumbers.tokensAvailableInBaseUnits.toNumber(), ethValueAvailableInWei: liquidityInBigNumbers.ethValueAvailableInWei.toNumber(), }; }; @@ -225,7 +225,7 @@ export class AssetBuyer { const assetPairs = await this.orderProvider.getAvailableMakerAssetDatasAsync(assetData); if (!assetPairs.includes(assetData)) { return { - tokensAvailableInUnitAmount: 0, + tokensAvailableInBaseUnits: 0, ethValueAvailableInWei: 0, }; } diff --git a/packages/asset-buyer/src/types.ts b/packages/asset-buyer/src/types.ts index 84434aa7f..71822c4d7 100644 --- a/packages/asset-buyer/src/types.ts +++ b/packages/asset-buyer/src/types.ts @@ -126,6 +126,6 @@ export interface OrdersAndFillableAmounts { * Represents available liquidity for a given assetData */ export interface LiquidityForAssetData { - tokensAvailableInUnitAmount: number; + tokensAvailableInBaseUnits: number; ethValueAvailableInWei: number; } diff --git a/packages/asset-buyer/test/asset_buyer_test.ts b/packages/asset-buyer/test/asset_buyer_test.ts index fd31b9843..5e05d5564 100644 --- a/packages/asset-buyer/test/asset_buyer_test.ts +++ b/packages/asset-buyer/test/asset_buyer_test.ts @@ -81,7 +81,7 @@ describe('AssetBuyer', () => { const assetBuyer = new AssetBuyer(mockWeb3Provider.object, mockOrderProvider.object); const liquidityResult = await assetBuyer.getLiquidityForAssetDataAsync(FAKE_ASSET_DATA); expect(liquidityResult).to.deep.equal({ - tokensAvailableInUnitAmount: 0, + tokensAvailableInBaseUnits: 0, ethValueAvailableInWei: 0, }); }); @@ -106,41 +106,38 @@ describe('AssetBuyer', () => { orders: [], remainingFillableMakerAssetAmounts: [], }; - const mockedAssetBuyer = mockedAssetBuyerWithOrdersAndFillableAmounts( + const expectedResult = { + tokensAvailableInBaseUnits: 0, + ethValueAvailableInWei: 0, + }; + await expectLiquidityResult( mockWeb3Provider.object, mockOrderProvider.object, - FAKE_ASSET_DATA, ordersAndFillableAmounts, + expectedResult, ); - - const liquidityResult = await mockedAssetBuyer.object.getLiquidityForAssetDataAsync(FAKE_ASSET_DATA); - expect(liquidityResult).to.deep.equal({ - tokensAvailableInUnitAmount: 0, - ethValueAvailableInWei: 0, - }); }); it('should return correct computed value when orders provided with full fillableAmounts', async () => { const orders: SignedOrder[] = [sellTwoTokensFor1Weth, sellTenTokensFor10Weth]; - const remainingFillableMakerAssetAmounts: BigNumber[] = orders.map(o => o.makerAssetAmount); - const mockedAssetBuyer = mockedAssetBuyerWithOrdersAndFillableAmounts( - mockWeb3Provider.object, - mockOrderProvider.object, - FAKE_ASSET_DATA, - { - orders, - remainingFillableMakerAssetAmounts, - }, - ); + 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 liquidityResult = await mockedAssetBuyer.object.getLiquidityForAssetDataAsync(FAKE_ASSET_DATA); - expect(liquidityResult).to.deep.equal({ - tokensAvailableInUnitAmount: expectedTokensAvailable.toNumber(), + const expectedResult = { + tokensAvailableInBaseUnits: expectedTokensAvailable.toNumber(), ethValueAvailableInWei: expectedEthValueAvailable.toNumber(), - }); + }; + + await expectLiquidityResult( + mockWeb3Provider.object, + mockOrderProvider.object, + ordersAndFillableAmounts, + expectedResult, + ); }); it('should return correct computed value with one partial fillableAmounts', async () => { @@ -149,7 +146,7 @@ describe('AssetBuyer', () => { remainingFillableMakerAssetAmounts: [baseUnitAmount(1)], }; const expectedResult = { - tokensAvailableInUnitAmount: baseUnitAmount(1).toNumber(), + tokensAvailableInBaseUnits: baseUnitAmount(1).toNumber(), ethValueAvailableInWei: baseUnitAmount(0.5, WETH_DECIMALS).toNumber(), }; @@ -167,7 +164,7 @@ describe('AssetBuyer', () => { remainingFillableMakerAssetAmounts: [baseUnitAmount(1), baseUnitAmount(3)], }; const expectedResult = { - tokensAvailableInUnitAmount: baseUnitAmount(4).toNumber(), + tokensAvailableInBaseUnits: baseUnitAmount(4).toNumber(), ethValueAvailableInWei: baseUnitAmount(3.5, WETH_DECIMALS).toNumber(), }; @@ -185,7 +182,7 @@ describe('AssetBuyer', () => { remainingFillableMakerAssetAmounts: [baseUnitAmount(0), baseUnitAmount(0)], }; const expectedResult = { - tokensAvailableInUnitAmount: baseUnitAmount(0).toNumber(), + tokensAvailableInBaseUnits: baseUnitAmount(0).toNumber(), ethValueAvailableInWei: baseUnitAmount(0, WETH_DECIMALS).toNumber(), }; -- cgit v1.2.3 From 127bd4bf9dd99c0520dcc4fbd5413d98e1dac65a Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Thu, 10 Jan 2019 15:38:41 -0800 Subject: Getting rid of unused params and adding documentation --- packages/asset-buyer/src/asset_buyer.ts | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'packages/asset-buyer') diff --git a/packages/asset-buyer/src/asset_buyer.ts b/packages/asset-buyer/src/asset_buyer.ts index 92a99c28c..77cf403d7 100644 --- a/packages/asset-buyer/src/asset_buyer.ts +++ b/packages/asset-buyer/src/asset_buyer.ts @@ -17,6 +17,7 @@ import { BuyQuoteExecutionOpts, BuyQuoteRequestOpts, LiquidityForAssetData, + LiquidityRequestOpts, OrderProvider, OrderProviderResponse, OrdersAndFillableAmounts, @@ -208,19 +209,22 @@ export class AssetBuyer { const buyQuote = this.getBuyQuoteAsync(assetData, assetBuyAmount, options); 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 = {}, + options: Partial = {}, ): Promise { - const { feePercentage, shouldForceOrderRefresh, slippagePercentage } = _.merge( - {}, - constants.DEFAULT_BUY_QUOTE_REQUEST_OPTS, - options, - ); + const shouldForceOrderRefresh = + options.shouldForceOrderRefresh !== undefined ? options.shouldForceOrderRefresh : false; assert.isString('assetData', assetData); - assert.isValidPercentage('feePercentage', feePercentage); assert.isBoolean('shouldForceOrderRefresh', shouldForceOrderRefresh); - assert.isNumber('slippagePercentage', slippagePercentage); const assetPairs = await this.orderProvider.getAvailableMakerAssetDatasAsync(assetData); if (!assetPairs.includes(assetData)) { @@ -321,6 +325,8 @@ 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. */ public async getOrdersAndFillableAmountsAsync( assetData: string, -- cgit v1.2.3 From 841ad8757cc9ba165f9ae303877da0d4b6ffe8b0 Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Thu, 10 Jan 2019 15:40:55 -0800 Subject: Add LiquidityRequestOpts type --- packages/asset-buyer/src/types.ts | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'packages/asset-buyer') diff --git a/packages/asset-buyer/src/types.ts b/packages/asset-buyer/src/types.ts index 71822c4d7..ef63aacfe 100644 --- a/packages/asset-buyer/src/types.ts +++ b/packages/asset-buyer/src/types.ts @@ -75,6 +75,11 @@ export interface BuyQuoteRequestOpts { slippagePercentage: number; } +/* + * shouldForceOrderRefresh: If set to true, new orders and state will be fetched instead of waiting for the next orderRefreshIntervalMs. Defaults to false. + */ +export interface LiquidityRequestOpts extends Pick {} + /** * 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. -- cgit v1.2.3 From 742e5e039dd4e821209b5511fb6a194d11c6291c Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Fri, 11 Jan 2019 08:14:57 -0800 Subject: getLiquidityForAssetDataAsync helper method, and fix to assetBuyer to check for eth token in asset pairs --- packages/asset-buyer/src/asset_buyer.ts | 3 ++- packages/asset-buyer/test/asset_buyer_test.ts | 30 ++++++++++++++++++++------- 2 files changed, 24 insertions(+), 9 deletions(-) (limited to 'packages/asset-buyer') diff --git a/packages/asset-buyer/src/asset_buyer.ts b/packages/asset-buyer/src/asset_buyer.ts index 77cf403d7..43b60f928 100644 --- a/packages/asset-buyer/src/asset_buyer.ts +++ b/packages/asset-buyer/src/asset_buyer.ts @@ -227,7 +227,8 @@ export class AssetBuyer { assert.isBoolean('shouldForceOrderRefresh', shouldForceOrderRefresh); const assetPairs = await this.orderProvider.getAvailableMakerAssetDatasAsync(assetData); - if (!assetPairs.includes(assetData)) { + const etherTokenAssetData = this._getEtherTokenAssetDataOrThrow(); + if (!assetPairs.includes(etherTokenAssetData)) { return { tokensAvailableInBaseUnits: 0, ethValueAvailableInWei: 0, diff --git a/packages/asset-buyer/test/asset_buyer_test.ts b/packages/asset-buyer/test/asset_buyer_test.ts index 5e05d5564..9ed51f5e5 100644 --- a/packages/asset-buyer/test/asset_buyer_test.ts +++ b/packages/asset-buyer/test/asset_buyer_test.ts @@ -24,6 +24,8 @@ 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 => { @@ -75,14 +77,26 @@ describe('AssetBuyer', () => { }); }); - it('should return 0s when asset pair not supported', async () => { - mockAvailableAssetDatas(mockOrderProvider, FAKE_ASSET_DATA, []); + 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: 0, - ethValueAvailableInWei: 0, + const assetBuyer = new AssetBuyer(mockWeb3Provider.object, mockOrderProvider.object); + const liquidityResult = await assetBuyer.getLiquidityForAssetDataAsync(FAKE_ASSET_DATA); + expect(liquidityResult).to.deep.equal({ + tokensAvailableInBaseUnits: 0, + ethValueAvailableInWei: 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: 0, + ethValueAvailableInWei: 0, + }); }); }); @@ -98,7 +112,7 @@ describe('AssetBuyer', () => { }); beforeEach(() => { - mockAvailableAssetDatas(mockOrderProvider, FAKE_ASSET_DATA, [FAKE_ASSET_DATA]); + mockAvailableAssetDatas(mockOrderProvider, FAKE_ASSET_DATA, [WETH_ASSET_DATA]); }); it('should return 0s when no orders available', async () => { -- cgit v1.2.3 From dbaed69d778e610c74930748816e3ba63752334c Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Fri, 11 Jan 2019 08:59:07 -0800 Subject: Add new version to CHANGELOG --- packages/asset-buyer/CHANGELOG.json | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'packages/asset-buyer') diff --git a/packages/asset-buyer/CHANGELOG.json b/packages/asset-buyer/CHANGELOG.json index 19bee94fd..f4767bd9c 100644 --- a/packages/asset-buyer/CHANGELOG.json +++ b/packages/asset-buyer/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "version": "4.1.0", + "changes": [ + { + "note": + "Adds new public method getOrdersAndFillableAmountsAsync, and exposes getOrdersAndFillableAmountsAsync as public method" + } + ] + }, { "version": "4.0.0", "changes": [ -- cgit v1.2.3 From a5e7ce9e1acb2f8fdfcef629789dd315e3adcbdc Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Fri, 11 Jan 2019 09:28:51 -0800 Subject: Move calculateLiquidity to helper function --- packages/asset-buyer/src/asset_buyer.ts | 32 +------------------- .../asset-buyer/src/utils/calculate_liquidity.ts | 34 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 31 deletions(-) create mode 100644 packages/asset-buyer/src/utils/calculate_liquidity.ts (limited to 'packages/asset-buyer') diff --git a/packages/asset-buyer/src/asset_buyer.ts b/packages/asset-buyer/src/asset_buyer.ts index 43b60f928..cd60f0eff 100644 --- a/packages/asset-buyer/src/asset_buyer.ts +++ b/packages/asset-buyer/src/asset_buyer.ts @@ -19,50 +19,20 @@ import { 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'; -import { orderUtils } from './utils/order_utils'; interface OrdersEntry { ordersAndFillableAmounts: OrdersAndFillableAmounts; lastRefreshTime: number; } -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.toNumber(), - ethValueAvailableInWei: liquidityInBigNumbers.ethValueAvailableInWei.toNumber(), - }; -}; - export class AssetBuyer { public readonly provider: Provider; public readonly orderProvider: OrderProvider; 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..910c756ac --- /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.toNumber(), + ethValueAvailableInWei: liquidityInBigNumbers.ethValueAvailableInWei.toNumber(), + }; +}; -- cgit v1.2.3 From 8d3bbb8213eb2972ace2cf488ef1d901bef8f725 Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Fri, 11 Jan 2019 09:32:28 -0800 Subject: Disable promise-function-async for mocking async functions --- packages/asset-buyer/test/utils/mocks.ts | 2 ++ 1 file changed, 2 insertions(+) (limited to 'packages/asset-buyer') diff --git a/packages/asset-buyer/test/utils/mocks.ts b/packages/asset-buyer/test/utils/mocks.ts index fe0d0cbf4..d3e1c09c4 100644 --- a/packages/asset-buyer/test/utils/mocks.ts +++ b/packages/asset-buyer/test/utils/mocks.ts @@ -4,6 +4,8 @@ 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 -- cgit v1.2.3 From 8a8a5332d76ae8429d1c6449e0ea693a2e8c8a8a Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Fri, 11 Jan 2019 10:38:52 -0800 Subject: prettier changelog --- packages/asset-buyer/CHANGELOG.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'packages/asset-buyer') diff --git a/packages/asset-buyer/CHANGELOG.json b/packages/asset-buyer/CHANGELOG.json index f4767bd9c..484ad1625 100644 --- a/packages/asset-buyer/CHANGELOG.json +++ b/packages/asset-buyer/CHANGELOG.json @@ -3,8 +3,7 @@ "version": "4.1.0", "changes": [ { - "note": - "Adds new public method getOrdersAndFillableAmountsAsync, and exposes getOrdersAndFillableAmountsAsync as public method" + "note": "Adds new public method getOrdersAndFillableAmountsAsync, and exposes getOrdersAndFillableAmountsAsync as public method" } ] }, -- cgit v1.2.3 From af63934d2ca0d2830a8609c16bd685a02241e257 Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Tue, 15 Jan 2019 13:57:31 -0800 Subject: Export types and add additional documentation --- packages/asset-buyer/src/index.ts | 4 ++++ packages/asset-buyer/src/types.ts | 6 ++++++ 2 files changed, 10 insertions(+) (limited to 'packages/asset-buyer') diff --git a/packages/asset-buyer/src/index.ts b/packages/asset-buyer/src/index.ts index a42d7e272..339d64616 100644 --- a/packages/asset-buyer/src/index.ts +++ b/packages/asset-buyer/src/index.ts @@ -1,3 +1,4 @@ +import { LiquidityRequestOpts } from './../lib/src/types.d'; export { JSONRPCRequestPayload, JSONRPCResponsePayload, @@ -19,6 +20,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 da8b75c8f..0bf2323bd 100644 --- a/packages/asset-buyer/src/types.ts +++ b/packages/asset-buyer/src/types.ts @@ -76,6 +76,8 @@ export interface BuyQuoteRequestOpts { } /* + * 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 interface LiquidityRequestOpts extends Pick {} @@ -122,6 +124,10 @@ 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[]; -- cgit v1.2.3 From f269bc28cf49a0c6d319ff6e30465eb209efe9df Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Tue, 15 Jan 2019 14:00:00 -0800 Subject: Add PR number and fix description --- packages/asset-buyer/CHANGELOG.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'packages/asset-buyer') diff --git a/packages/asset-buyer/CHANGELOG.json b/packages/asset-buyer/CHANGELOG.json index 909236772..8a9dc333a 100644 --- a/packages/asset-buyer/CHANGELOG.json +++ b/packages/asset-buyer/CHANGELOG.json @@ -3,7 +3,8 @@ "version": "4.1.0", "changes": [ { - "note": "Adds new public method getOrdersAndFillableAmountsAsync, and exposes getOrdersAndFillableAmountsAsync as public method" + "note": "Adds new public method getLiquidityForAssetDataAsync, and exposes getOrdersAndFillableAmountsAsync as public method", + "pr": 1512 } ] }, -- cgit v1.2.3 From ce1c2eeab78cfe1ce79a856f3f3f03b9f2bd67e4 Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Wed, 16 Jan 2019 09:37:10 -0800 Subject: Remove accidental import --- packages/asset-buyer/src/index.ts | 1 - 1 file changed, 1 deletion(-) (limited to 'packages/asset-buyer') diff --git a/packages/asset-buyer/src/index.ts b/packages/asset-buyer/src/index.ts index 339d64616..f69cfad69 100644 --- a/packages/asset-buyer/src/index.ts +++ b/packages/asset-buyer/src/index.ts @@ -1,4 +1,3 @@ -import { LiquidityRequestOpts } from './../lib/src/types.d'; export { JSONRPCRequestPayload, JSONRPCResponsePayload, -- cgit v1.2.3 From 444250520a73ea4e147d501a9df54614689570e5 Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Wed, 16 Jan 2019 09:40:36 -0800 Subject: Clarify boolean variable name --- packages/asset-buyer/src/asset_buyer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/asset-buyer') diff --git a/packages/asset-buyer/src/asset_buyer.ts b/packages/asset-buyer/src/asset_buyer.ts index cd60f0eff..b4b024d62 100644 --- a/packages/asset-buyer/src/asset_buyer.ts +++ b/packages/asset-buyer/src/asset_buyer.ts @@ -194,7 +194,7 @@ export class AssetBuyer { const shouldForceOrderRefresh = options.shouldForceOrderRefresh !== undefined ? options.shouldForceOrderRefresh : false; assert.isString('assetData', assetData); - assert.isBoolean('shouldForceOrderRefresh', shouldForceOrderRefresh); + assert.isBoolean('options.shouldForceOrderRefresh', shouldForceOrderRefresh); const assetPairs = await this.orderProvider.getAvailableMakerAssetDatasAsync(assetData); const etherTokenAssetData = this._getEtherTokenAssetDataOrThrow(); -- cgit v1.2.3 From a58771844366d5fd331e6b46a8de596d17fa6632 Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Wed, 16 Jan 2019 09:41:12 -0800 Subject: export type instead of interface for more succinct syntax --- packages/asset-buyer/src/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/asset-buyer') diff --git a/packages/asset-buyer/src/types.ts b/packages/asset-buyer/src/types.ts index 0bf2323bd..9208a3217 100644 --- a/packages/asset-buyer/src/types.ts +++ b/packages/asset-buyer/src/types.ts @@ -80,7 +80,7 @@ export interface BuyQuoteRequestOpts { * * shouldForceOrderRefresh: If set to true, new orders and state will be fetched instead of waiting for the next orderRefreshIntervalMs. Defaults to false. */ -export interface LiquidityRequestOpts extends Pick {} +export type LiquidityRequestOpts = Pick; /** * ethAmount: The desired amount of eth to spend. Defaults to buyQuote.worstCaseQuoteInfo.totalEthAmount. -- cgit v1.2.3 From 466ec6b22a51f0a9d618f6091ce6f9f533118280 Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Wed, 16 Jan 2019 14:16:49 -0800 Subject: Change LiquidityForAssetData to return a BigNumber instead of a number to avoid losing precision --- packages/asset-buyer/src/asset_buyer.ts | 4 ++-- packages/asset-buyer/src/types.ts | 4 ++-- .../asset-buyer/src/utils/calculate_liquidity.ts | 4 ++-- packages/asset-buyer/test/asset_buyer_test.ts | 28 +++++++++++----------- 4 files changed, 20 insertions(+), 20 deletions(-) (limited to 'packages/asset-buyer') diff --git a/packages/asset-buyer/src/asset_buyer.ts b/packages/asset-buyer/src/asset_buyer.ts index b4b024d62..4344f070c 100644 --- a/packages/asset-buyer/src/asset_buyer.ts +++ b/packages/asset-buyer/src/asset_buyer.ts @@ -200,8 +200,8 @@ export class AssetBuyer { const etherTokenAssetData = this._getEtherTokenAssetDataOrThrow(); if (!assetPairs.includes(etherTokenAssetData)) { return { - tokensAvailableInBaseUnits: 0, - ethValueAvailableInWei: 0, + tokensAvailableInBaseUnits: new BigNumber(0), + ethValueAvailableInWei: new BigNumber(0), }; } diff --git a/packages/asset-buyer/src/types.ts b/packages/asset-buyer/src/types.ts index 9208a3217..46a2338ce 100644 --- a/packages/asset-buyer/src/types.ts +++ b/packages/asset-buyer/src/types.ts @@ -137,6 +137,6 @@ export interface OrdersAndFillableAmounts { * Represents available liquidity for a given assetData */ export interface LiquidityForAssetData { - tokensAvailableInBaseUnits: number; - ethValueAvailableInWei: number; + tokensAvailableInBaseUnits: BigNumber; + ethValueAvailableInWei: BigNumber; } diff --git a/packages/asset-buyer/src/utils/calculate_liquidity.ts b/packages/asset-buyer/src/utils/calculate_liquidity.ts index 910c756ac..a8d165b4b 100644 --- a/packages/asset-buyer/src/utils/calculate_liquidity.ts +++ b/packages/asset-buyer/src/utils/calculate_liquidity.ts @@ -28,7 +28,7 @@ export const calculateLiquidity = (ordersAndFillableAmounts: OrdersAndFillableAm // Turn into regular numbers return { - tokensAvailableInBaseUnits: liquidityInBigNumbers.tokensAvailableInBaseUnits.toNumber(), - ethValueAvailableInWei: liquidityInBigNumbers.ethValueAvailableInWei.toNumber(), + 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 index 9ed51f5e5..f117b4d7a 100644 --- a/packages/asset-buyer/test/asset_buyer_test.ts +++ b/packages/asset-buyer/test/asset_buyer_test.ts @@ -84,8 +84,8 @@ describe('AssetBuyer', () => { const assetBuyer = new AssetBuyer(mockWeb3Provider.object, mockOrderProvider.object); const liquidityResult = await assetBuyer.getLiquidityForAssetDataAsync(FAKE_ASSET_DATA); expect(liquidityResult).to.deep.equal({ - tokensAvailableInBaseUnits: 0, - ethValueAvailableInWei: 0, + tokensAvailableInBaseUnits: new BigNumber(0), + ethValueAvailableInWei: new BigNumber(0), }); }); it('should return 0s when only other asset pair supported', async () => { @@ -94,8 +94,8 @@ describe('AssetBuyer', () => { const assetBuyer = new AssetBuyer(mockWeb3Provider.object, mockOrderProvider.object); const liquidityResult = await assetBuyer.getLiquidityForAssetDataAsync(FAKE_ASSET_DATA); expect(liquidityResult).to.deep.equal({ - tokensAvailableInBaseUnits: 0, - ethValueAvailableInWei: 0, + tokensAvailableInBaseUnits: new BigNumber(0), + ethValueAvailableInWei: new BigNumber(0), }); }); }); @@ -121,8 +121,8 @@ describe('AssetBuyer', () => { remainingFillableMakerAssetAmounts: [], }; const expectedResult = { - tokensAvailableInBaseUnits: 0, - ethValueAvailableInWei: 0, + tokensAvailableInBaseUnits: new BigNumber(0), + ethValueAvailableInWei: new BigNumber(0), }; await expectLiquidityResult( mockWeb3Provider.object, @@ -142,8 +142,8 @@ describe('AssetBuyer', () => { const expectedTokensAvailable = orders[0].makerAssetAmount.plus(orders[1].makerAssetAmount); const expectedEthValueAvailable = orders[0].takerAssetAmount.plus(orders[1].takerAssetAmount); const expectedResult = { - tokensAvailableInBaseUnits: expectedTokensAvailable.toNumber(), - ethValueAvailableInWei: expectedEthValueAvailable.toNumber(), + tokensAvailableInBaseUnits: expectedTokensAvailable, + ethValueAvailableInWei: expectedEthValueAvailable, }; await expectLiquidityResult( @@ -160,8 +160,8 @@ describe('AssetBuyer', () => { remainingFillableMakerAssetAmounts: [baseUnitAmount(1)], }; const expectedResult = { - tokensAvailableInBaseUnits: baseUnitAmount(1).toNumber(), - ethValueAvailableInWei: baseUnitAmount(0.5, WETH_DECIMALS).toNumber(), + tokensAvailableInBaseUnits: baseUnitAmount(1), + ethValueAvailableInWei: baseUnitAmount(0.5, WETH_DECIMALS), }; await expectLiquidityResult( @@ -178,8 +178,8 @@ describe('AssetBuyer', () => { remainingFillableMakerAssetAmounts: [baseUnitAmount(1), baseUnitAmount(3)], }; const expectedResult = { - tokensAvailableInBaseUnits: baseUnitAmount(4).toNumber(), - ethValueAvailableInWei: baseUnitAmount(3.5, WETH_DECIMALS).toNumber(), + tokensAvailableInBaseUnits: baseUnitAmount(4), + ethValueAvailableInWei: baseUnitAmount(3.5, WETH_DECIMALS), }; await expectLiquidityResult( @@ -196,8 +196,8 @@ describe('AssetBuyer', () => { remainingFillableMakerAssetAmounts: [baseUnitAmount(0), baseUnitAmount(0)], }; const expectedResult = { - tokensAvailableInBaseUnits: baseUnitAmount(0).toNumber(), - ethValueAvailableInWei: baseUnitAmount(0, WETH_DECIMALS).toNumber(), + tokensAvailableInBaseUnits: baseUnitAmount(0), + ethValueAvailableInWei: baseUnitAmount(0, WETH_DECIMALS), }; await expectLiquidityResult( -- cgit v1.2.3 From 92f5ad4f1518b2aaa3f1754b44a3059ac1610e0c Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Wed, 16 Jan 2019 17:12:08 -0800 Subject: Use more specific helper method decodeAssetDataOrThrow --- packages/asset-buyer/src/asset_buyer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/asset-buyer') diff --git a/packages/asset-buyer/src/asset_buyer.ts b/packages/asset-buyer/src/asset_buyer.ts index 4344f070c..ad4b3bb60 100644 --- a/packages/asset-buyer/src/asset_buyer.ts +++ b/packages/asset-buyer/src/asset_buyer.ts @@ -193,7 +193,7 @@ export class AssetBuyer { ): Promise { const shouldForceOrderRefresh = options.shouldForceOrderRefresh !== undefined ? options.shouldForceOrderRefresh : false; - assert.isString('assetData', assetData); + assetDataUtils.decodeAssetDataOrThrow(assetData); assert.isBoolean('options.shouldForceOrderRefresh', shouldForceOrderRefresh); const assetPairs = await this.orderProvider.getAvailableMakerAssetDatasAsync(assetData); -- cgit v1.2.3