|
1 | 1 | import { Logger } from "@nestjs/common"; |
2 | | -import ccxt, { Exchange, pro, Trade } from "ccxt"; |
| 2 | +import ccxt, { Exchange, Trade } from "ccxt"; |
3 | 3 | import { readFileSync } from "fs"; |
4 | 4 | import { FeedId, FeedValueData } from "../dto/provider-requests.dto"; |
5 | 5 | import { BaseDataFeed } from "./base-feed"; |
@@ -116,48 +116,10 @@ export class CcxtFeed implements BaseDataFeed { |
116 | 116 | marketIds.push(market.id); |
117 | 117 | } |
118 | 118 |
|
119 | | - await this.populateInitialPrices(marketIds, exchangeName, exchange); |
120 | | - |
121 | 119 | void this.watch(exchange, marketIds, exchangeName); |
122 | 120 | } |
123 | 121 | } |
124 | 122 |
|
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 | | - |
161 | 123 | private async watch(exchange: Exchange, marketIds: string[], exchangeName: string) { |
162 | 124 | this.logger.log(`Watching trades for ${marketIds} on exchange ${exchangeName}`); |
163 | 125 |
|
@@ -251,13 +213,43 @@ export class CcxtFeed implements BaseDataFeed { |
251 | 213 |
|
252 | 214 | if (prices.length === 0) { |
253 | 215 | 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); |
254 | 218 | return undefined; |
255 | 219 | } |
256 | 220 |
|
257 | 221 | this.logger.debug(`Calculating results for ${JSON.stringify(feedId)}`); |
258 | 222 | return this.weightedMedian(prices); |
259 | 223 | } |
260 | 224 |
|
| 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 | + |
261 | 253 | private weightedMedian(prices: PriceInfo[]): number { |
262 | 254 | if (prices.length === 0) { |
263 | 255 | throw new Error("Price list cannot be empty."); |
|
0 commit comments