@pythnetwork/price-pusher
Version:
Pyth Price Pusher
69 lines (68 loc) • 2.78 kB
JavaScript
;
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;