UNPKG

@pythnetwork/price-pusher

Version:
69 lines (68 loc) 2.78 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PythPriceListener = void 0; class PythPriceListener { hermesClient; priceIds; priceIdToAlias; latestPriceInfo; logger; lastUpdated; healthCheckInterval; constructor(hermesClient, priceItems, logger) { this.hermesClient = hermesClient; this.priceIds = priceItems.map((priceItem) => priceItem.id); this.priceIdToAlias = new Map(priceItems.map((priceItem) => [priceItem.id, priceItem.alias])); this.latestPriceInfo = new Map(); this.logger = logger; } // This method should be awaited on and once it finishes it has the latest value // for the given price feeds (if they exist). async start() { const eventSource = await this.hermesClient.getPriceUpdatesStream(this.priceIds, { parsed: true, ignoreInvalidPriceIds: true, }); eventSource.onmessage = (event) => { const priceUpdates = JSON.parse(event.data); priceUpdates.parsed?.forEach((priceUpdate) => { this.logger.debug(`Received new price feed update from Pyth price service: ${this.priceIdToAlias.get(priceUpdate.id)} ${priceUpdate.id}`); // Consider price to be currently available if it is not older than 60s const currentPrice = Date.now() / 1000 - priceUpdate.price.publish_time > 60 ? undefined : priceUpdate.price; if (currentPrice === undefined) { this.logger.debug("Price is older than 60s, skipping"); return; } const priceInfo = { conf: currentPrice.conf, price: currentPrice.price, publishTime: currentPrice.publish_time, }; this.latestPriceInfo.set(priceUpdate.id, priceInfo); this.lastUpdated = Date.now(); }); }; eventSource.onerror = (error) => { console.error("Error receiving updates from Hermes:", error); eventSource.close(); }; // Store health check interval reference this.healthCheckInterval = setInterval(() => { if (this.lastUpdated === undefined || this.lastUpdated < Date.now() - 30 * 1000) { throw new Error("Hermes Price feeds are not updating."); } }, 5000); } getLatestPriceInfo(priceId) { return this.latestPriceInfo.get(priceId); } cleanup() { if (this.healthCheckInterval) { clearInterval(this.healthCheckInterval); } } } exports.PythPriceListener = PythPriceListener;