UNPKG

@pythnetwork/price-pusher

Version:
104 lines (103 loc) 5.35 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Controller = void 0; const utils_1 = require("./utils"); const price_config_1 = require("./price-config"); class Controller { priceConfigs; sourcePriceListener; targetPriceListener; targetChainPricePusher; logger; pushingFrequency; metrics; constructor(priceConfigs, sourcePriceListener, targetPriceListener, targetChainPricePusher, logger, config) { this.priceConfigs = priceConfigs; this.sourcePriceListener = sourcePriceListener; this.targetPriceListener = targetPriceListener; this.targetChainPricePusher = targetChainPricePusher; this.logger = logger; this.pushingFrequency = config.pushingFrequency; this.metrics = config.metrics; // Set the number of price feeds if metrics are enabled this.metrics?.setPriceFeedsTotal(this.priceConfigs.length); } async start() { // start the listeners await this.sourcePriceListener.start(); await this.targetPriceListener.start(); // wait for the listeners to get updated. There could be a restart // before this run and we need to respect the cooldown duration as // their might be a message sent before. await (0, utils_1.sleep)(this.pushingFrequency * 1000); for (;;) { // We will push all prices whose update condition is YES or EARLY as long as there is // at least one YES. let pushThresholdMet = false; const pricesToPush = []; const pubTimesToPush = []; for (const priceConfig of this.priceConfigs) { const priceId = priceConfig.id; const alias = priceConfig.alias; const targetLatestPrice = this.targetPriceListener.getLatestPriceInfo(priceId); const sourceLatestPrice = this.sourcePriceListener.getLatestPriceInfo(priceId); // Update metrics for the last published time if available if (this.metrics && targetLatestPrice) { this.metrics.updateLastPublishedTime(priceId, alias, targetLatestPrice); } const priceShouldUpdate = (0, price_config_1.shouldUpdate)(priceConfig, sourceLatestPrice, targetLatestPrice, this.logger); // Record update condition in metrics if (this.metrics) { this.metrics.recordUpdateCondition(priceId, alias, priceShouldUpdate); } if (priceShouldUpdate == price_config_1.UpdateCondition.YES) { pushThresholdMet = true; } if (priceShouldUpdate == price_config_1.UpdateCondition.YES || priceShouldUpdate == price_config_1.UpdateCondition.EARLY) { pricesToPush.push(priceConfig); pubTimesToPush.push((targetLatestPrice?.publishTime || 0) + 1); } } if (pushThresholdMet) { this.logger.info({ priceIds: pricesToPush.map((priceConfig) => ({ id: priceConfig.id, alias: priceConfig.alias, })), }, "Some of the checks triggered pushing update. Will push the updates for some feeds."); // note that the priceIds are without leading "0x" const priceIds = pricesToPush.map((priceConfig) => priceConfig.id); try { await this.targetChainPricePusher.updatePriceFeed(priceIds, pubTimesToPush); // Record successful updates if (this.metrics) { for (const config of pricesToPush) { const triggerValue = (0, price_config_1.shouldUpdate)(config, this.sourcePriceListener.getLatestPriceInfo(config.id), this.targetPriceListener.getLatestPriceInfo(config.id), this.logger) === price_config_1.UpdateCondition.YES ? "yes" : "early"; this.metrics.recordPriceUpdate(config.id, config.alias, triggerValue); } } } catch (error) { this.logger.error({ error, priceIds }, "Error pushing price updates to chain"); // Record errors in metrics if (this.metrics) { for (const config of pricesToPush) { const triggerValue = (0, price_config_1.shouldUpdate)(config, this.sourcePriceListener.getLatestPriceInfo(config.id), this.targetPriceListener.getLatestPriceInfo(config.id), this.logger) === price_config_1.UpdateCondition.YES ? "yes" : "early"; this.metrics.recordPriceUpdateError(config.id, config.alias, triggerValue); } } } } else { this.logger.info("None of the checks were triggered. No push needed."); } await (0, utils_1.sleep)(this.pushingFrequency * 1000); } } } exports.Controller = Controller;