Skip to content

Commit 9f10b48

Browse files
committed
Switch to lazy last price fetching - "fetchTickers" doesn't seem to necessarily return all requested tickers and fetching all tickers one by one takes unnecessarily long.
1 parent acaebe5 commit 9f10b48

File tree

1 file changed

+31
-39
lines changed

1 file changed

+31
-39
lines changed

src/data-feeds/ccxt-provider-service.ts

Lines changed: 31 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Logger } from "@nestjs/common";
2-
import ccxt, { Exchange, pro, Trade } from "ccxt";
2+
import ccxt, { Exchange, Trade } from "ccxt";
33
import { readFileSync } from "fs";
44
import { FeedId, FeedValueData } from "../dto/provider-requests.dto";
55
import { BaseDataFeed } from "./base-feed";
@@ -116,48 +116,10 @@ export class CcxtFeed implements BaseDataFeed {
116116
marketIds.push(market.id);
117117
}
118118

119-
await this.populateInitialPrices(marketIds, exchangeName, exchange);
120-
121119
void this.watch(exchange, marketIds, exchangeName);
122120
}
123121
}
124122

125-
private async populateInitialPrices(marketIds: string[], exchangeName: string, exchange: Exchange) {
126-
try {
127-
if (exchange.has["fetchTickers"]) {
128-
this.logger.log(`Fetching last prices for ${marketIds} on ${exchangeName}`);
129-
const tickers = await exchange.fetchTickers(marketIds);
130-
for (const [marketId, ticker] of Object.entries(tickers)) {
131-
if (ticker.last === undefined) {
132-
this.logger.warn(`No last price found for ${marketId} on ${exchangeName}`);
133-
continue;
134-
}
135-
136-
this.setPrice(exchangeName, ticker.symbol, ticker.last, ticker.timestamp);
137-
}
138-
} else {
139-
throw new Error("Exchange does not support fetchTickers");
140-
}
141-
} catch (e) {
142-
this.logger.log(`Unable to retrieve ticker batch on ${exchangeName}: ${e}`);
143-
this.logger.log(`Falling back to fetching individual tickers`);
144-
for (const marketId of marketIds) {
145-
this.logger.log(`Fetching last price for ${marketId} on ${exchangeName}`);
146-
const ticker = await exchange.fetchTicker(marketId);
147-
if (ticker === undefined) {
148-
this.logger.warn(`Ticker not found for ${marketId} on ${exchangeName}`);
149-
continue;
150-
}
151-
if (ticker.last === undefined) {
152-
this.logger.log(`No last price found for ${marketId} on ${exchangeName}`);
153-
continue;
154-
}
155-
156-
this.setPrice(exchangeName, ticker.symbol, ticker.last, ticker.timestamp);
157-
}
158-
}
159-
}
160-
161123
private async watch(exchange: Exchange, marketIds: string[], exchangeName: string) {
162124
this.logger.log(`Watching trades for ${marketIds} on exchange ${exchangeName}`);
163125

@@ -251,13 +213,43 @@ export class CcxtFeed implements BaseDataFeed {
251213

252214
if (prices.length === 0) {
253215
this.logger.warn(`No prices found for ${JSON.stringify(feedId)}`);
216+
// Attempt to fetch last known price from exchanges. Don't block on this request - data will be available later on re-query.
217+
void this.fetchLastPrices(config);
254218
return undefined;
255219
}
256220

257221
this.logger.debug(`Calculating results for ${JSON.stringify(feedId)}`);
258222
return this.weightedMedian(prices);
259223
}
260224

225+
private fetchAttempted = new Set<FeedId>();
226+
227+
private async fetchLastPrices(config: FeedConfig) {
228+
if (this.fetchAttempted.has(config.feed)) {
229+
return;
230+
} else {
231+
this.fetchAttempted.add(config.feed);
232+
}
233+
234+
for (const source of config.sources) {
235+
const exchange: Exchange = this.exchangeByName.get(source.exchange);
236+
const market = exchange.markets[source.symbol];
237+
if (market == undefined) continue;
238+
this.logger.log(`Fetching last price for ${market.id} on ${source.exchange}`);
239+
const ticker = await exchange.fetchTicker(market.id);
240+
if (ticker === undefined) {
241+
this.logger.warn(`Ticker not found for ${market.id} on ${source.exchange}`);
242+
continue;
243+
}
244+
if (ticker.last === undefined) {
245+
this.logger.log(`No last price found for ${market.id} on ${source.exchange}`);
246+
continue;
247+
}
248+
249+
this.setPrice(source.exchange, ticker.symbol, ticker.last, ticker.timestamp);
250+
}
251+
}
252+
261253
private weightedMedian(prices: PriceInfo[]): number {
262254
if (prices.length === 0) {
263255
throw new Error("Price list cannot be empty.");

0 commit comments

Comments
 (0)