controller.ts 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. import { UnixTimestamp } from "@pythnetwork/price-service-client";
  2. import { DurationInSeconds, sleep } from "./utils";
  3. import { IPriceListener, IPricePusher } from "./interface";
  4. import { PriceConfig, shouldUpdate, UpdateCondition } from "./price-config";
  5. export class Controller {
  6. private pushingFrequency: DurationInSeconds;
  7. constructor(
  8. private priceConfigs: PriceConfig[],
  9. private sourcePriceListener: IPriceListener,
  10. private targetPriceListener: IPriceListener,
  11. private targetChainPricePusher: IPricePusher,
  12. config: {
  13. pushingFrequency: DurationInSeconds;
  14. }
  15. ) {
  16. this.pushingFrequency = config.pushingFrequency;
  17. }
  18. async start() {
  19. // start the listeners
  20. await this.sourcePriceListener.start();
  21. await this.targetPriceListener.start();
  22. // wait for the listeners to get updated. There could be a restart
  23. // before this run and we need to respect the cooldown duration as
  24. // their might be a message sent before.
  25. await sleep(this.pushingFrequency * 1000);
  26. for (;;) {
  27. // We will push all prices whose update condition is YES or EARLY as long as there is
  28. // at least one YES.
  29. let pushThresholdMet = false;
  30. const pricesToPush: PriceConfig[] = [];
  31. const pubTimesToPush: UnixTimestamp[] = [];
  32. for (const priceConfig of this.priceConfigs) {
  33. const priceId = priceConfig.id;
  34. const targetLatestPrice =
  35. this.targetPriceListener.getLatestPriceInfo(priceId);
  36. const sourceLatestPrice =
  37. this.sourcePriceListener.getLatestPriceInfo(priceId);
  38. const priceShouldUpdate = shouldUpdate(
  39. priceConfig,
  40. sourceLatestPrice,
  41. targetLatestPrice
  42. );
  43. if (priceShouldUpdate == UpdateCondition.YES) {
  44. pushThresholdMet = true;
  45. }
  46. if (
  47. priceShouldUpdate == UpdateCondition.YES ||
  48. priceShouldUpdate == UpdateCondition.EARLY
  49. ) {
  50. pricesToPush.push(priceConfig);
  51. pubTimesToPush.push((targetLatestPrice?.publishTime || 0) + 1);
  52. }
  53. }
  54. if (pushThresholdMet) {
  55. console.log(
  56. "Some of the above values passed the threshold. Will push the price."
  57. );
  58. // note that the priceIds are without leading "0x"
  59. const priceIds = pricesToPush.map((priceConfig) => priceConfig.id);
  60. this.targetChainPricePusher.updatePriceFeed(priceIds, pubTimesToPush);
  61. } else {
  62. console.log(
  63. "None of the above values passed the threshold. No push needed."
  64. );
  65. }
  66. await sleep(this.pushingFrequency * 1000);
  67. }
  68. }
  69. }