Skip to content
This repository has been archived by the owner on Oct 15, 2024. It is now read-only.

Commit

Permalink
Batch fetch orders for /price endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
dekz committed Jan 14, 2020
1 parent 9bf7f9a commit ec38ac0
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 126 deletions.
4 changes: 2 additions & 2 deletions src/handlers/swap_handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ export class SwapHandlers {
res.status(HttpStatus.OK).send({ tokens: filteredTokens });
}
// tslint:disable-next-line:prefer-function-over-method
public async getTokenPricesAsync(_req: express.Request, res: express.Response): Promise<void> {
const prices = await this._swapService.getTokenPricesAsync();
public async getTokenPricesAsync(req: express.Request, res: express.Response): Promise<void> {
const prices = await this._swapService.getTokenPricesAsync(req.query.sellToken || 'WETH');
res.status(HttpStatus.OK).send({ prices });
}
}
Expand Down
20 changes: 18 additions & 2 deletions src/services/orderbook_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { WSClient } from '@0x/mesh-rpc-client';
import { assetDataUtils } from '@0x/order-utils';
import { AssetPairsItem, OrdersRequestOpts, SignedOrder } from '@0x/types';
import * as _ from 'lodash';
import { Connection } from 'typeorm';
import { Connection, In } from 'typeorm';

import { SignedOrderEntity } from '../entities';
import { ValidationError } from '../errors';
Expand Down Expand Up @@ -75,7 +75,6 @@ export class OrderBookService {
where: { takerAssetData: quoteAssetData, makerAssetData: baseAssetData },
}),
]);
console.log(bidSignedOrderEntities.length, askSignedOrderEntities.length);
const bidApiOrders: APIOrder[] = (bidSignedOrderEntities as Array<Required<SignedOrderEntity>>)
.map(orderUtils.deserializeOrderToAPIOrder)
.sort((orderA, orderB) => orderUtils.compareBidOrder(orderA.order, orderB.order));
Expand Down Expand Up @@ -157,6 +156,23 @@ export class OrderBookService {
const paginatedApiOrders = paginationUtils.paginate(apiOrders, page, perPage);
return paginatedApiOrders;
}
public async getBatchOrdersAsync(
page: number,
perPage: number,
makerAssetDatas: string[],
takerAssetDatas: string[],
): Promise<PaginatedCollection<APIOrder>> {
const filterObject = {
makerAssetData: In(makerAssetDatas),
takerAssetData: In(takerAssetDatas),
};
const signedOrderEntities = (await this._connection.manager.find(SignedOrderEntity, {
where: filterObject,
})) as Array<Required<SignedOrderEntity>>;
const apiOrders = _.map(signedOrderEntities, orderUtils.deserializeOrderToAPIOrder);
const paginatedApiOrders = paginationUtils.paginate(apiOrders, page, perPage);
return paginatedApiOrders;
}
constructor(connection: Connection, meshClient?: WSClient) {
this._meshClient = meshClient;
this._connection = connection;
Expand Down
56 changes: 36 additions & 20 deletions src/services/swap_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { logger } from '../logger';
import { TokenMetadatasForChains } from '../token_metadatas_for_networks';
import { CalculateSwapQuoteParams, GetSwapQuoteResponse } from '../types';
import { orderUtils } from '../utils/order_utils';
import { findTokenDecimalsIfExists } from '../utils/token_metadata_utils';
import { findTokenDecimalsIfExists, getTokenMetadataIfExists } from '../utils/token_metadata_utils';

export class SwapService {
private readonly _provider: SupportedProvider;
Expand Down Expand Up @@ -48,9 +48,9 @@ export class SwapService {
from,
} = params;
const assetSwapperOpts = {
...ASSET_SWAPPER_MARKET_ORDERS_OPTS,
slippagePercentage,
gasPrice: providedGasPrice,
...ASSET_SWAPPER_MARKET_ORDERS_OPTS,
};
if (sellAmount !== undefined) {
swapQuote = await this._swapQuoter.getMarketSellSwapQuoteAsync(
Expand Down Expand Up @@ -104,9 +104,7 @@ export class SwapService {

const buyTokenDecimals = await this._fetchTokenDecimalsIfRequiredAsync(buyTokenAddress);
const sellTokenDecimals = await this._fetchTokenDecimalsIfRequiredAsync(sellTokenAddress);
const price = Web3Wrapper.toUnitAmount(makerAssetAmount, buyTokenDecimals)
.dividedBy(Web3Wrapper.toUnitAmount(totalTakerAssetAmount, sellTokenDecimals))
.decimalPlaces(sellTokenDecimals);
const price = calculatePrice(makerAssetAmount, buyTokenDecimals, totalTakerAssetAmount, sellTokenDecimals);

const apiSwapQuote: GetSwapQuoteResponse = {
price,
Expand All @@ -124,42 +122,48 @@ export class SwapService {
return apiSwapQuote;
}

public async getTokenPricesAsync(): Promise<Array<{ symbol: string; price: BigNumber }>> {
const baseAssetSymbol = 'WETH';
const unitAmount = new BigNumber(1);
const baseAsset = TokenMetadatasForChains.find(m => m.symbol === baseAssetSymbol);
public async getTokenPricesAsync(baseAssetSymbol: string): Promise<Array<{ symbol: string; price: BigNumber }>> {
const baseAsset = getTokenMetadataIfExists(baseAssetSymbol, CHAIN_ID);
if (!baseAsset) {
throw new Error('Invalid Base Asset');
}
const takerAssetData = assetDataUtils.encodeERC20AssetData(baseAsset.tokenAddresses[CHAIN_ID]); // WETH
const unitAmount = new BigNumber(1);
const takerAssetData = assetDataUtils.encodeERC20AssetData(baseAsset.tokenAddress);
const queryAssetData = TokenMetadatasForChains.filter(m => m.symbol !== baseAssetSymbol);
const tokenMetadataChunks = _.chunk(queryAssetData, 10);
const chunkSize = 10;
const assetDataChunks = _.chunk(queryAssetData, chunkSize);
const allResults = _.flatten(
await Promise.all(
tokenMetadataChunks.map(async chunk => {
const makerAssetDatas = chunk.map(m =>
assetDataChunks.map(async a => {
const encodedAssetData = a.map(m =>
assetDataUtils.encodeERC20AssetData(m.tokenAddresses[CHAIN_ID]),
);
const amounts = chunk.map(m => Web3Wrapper.toBaseUnitAmount(unitAmount, m.decimals));
return this._swapQuoter.getMultipleMarketBuySwapQuoteForAssetDataAsync(
makerAssetDatas,
const amounts = a.map(m => Web3Wrapper.toBaseUnitAmount(unitAmount, m.decimals));
const quotes = await this._swapQuoter.getBatchMarketBuySwapQuoteForAssetDataAsync(
encodedAssetData,
takerAssetData,
amounts,
{ slippagePercentage: 0 },
{
...ASSET_SWAPPER_MARKET_ORDERS_OPTS,
slippagePercentage: 0,
bridgeSlippage: 0,
numSamples: 1,
runLimit: 1,
},
);
return quotes;
}),
),
);

const prices = allResults.map((quote, i) => {
if (!quote) {
return { symbol: queryAssetData[i].symbol, price: ZERO };
}
const buyTokenDecimals = queryAssetData[i].decimals;
const sellTokenDecimals = baseAsset.decimals;
const { makerAssetAmount, totalTakerAssetAmount } = quote.bestCaseQuoteInfo;
const makerAssetUnitAmount = Web3Wrapper.toUnitAmount(makerAssetAmount, buyTokenDecimals);
const takerAssetUnitAmount = Web3Wrapper.toUnitAmount(totalTakerAssetAmount, sellTokenDecimals);
const price = makerAssetUnitAmount.dividedBy(takerAssetUnitAmount).decimalPlaces(sellTokenDecimals);
const price = calculatePrice(makerAssetAmount, buyTokenDecimals, totalTakerAssetAmount, sellTokenDecimals);
return {
symbol: queryAssetData[i].symbol,
price,
Expand Down Expand Up @@ -255,6 +259,18 @@ export class SwapService {
}
}

const calculatePrice = (
makerAssetAmount: BigNumber,
makerAssetDecimals: number,
takerAssetAmount: BigNumber,
takerAssetDecimals: number,
): BigNumber => {
const makerAssetUnitAmount = Web3Wrapper.toUnitAmount(makerAssetAmount, makerAssetDecimals);
const takerAssetUnitAmount = Web3Wrapper.toUnitAmount(takerAssetAmount, takerAssetDecimals);
const price = makerAssetUnitAmount.dividedBy(takerAssetUnitAmount).decimalPlaces(takerAssetDecimals);
return price;
};

const throwIfRevertError = (result: string): void => {
let revertError;
try {
Expand Down
Loading

0 comments on commit ec38ac0

Please sign in to comment.