HermesClient.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import yargs from "yargs";
  2. import { hideBin } from "yargs/helpers";
  3. import { HermesClient, PriceUpdate } from "../HermesClient";
  4. function sleep(ms: number) {
  5. return new Promise((resolve) => setTimeout(resolve, ms));
  6. }
  7. const argv = yargs(hideBin(process.argv))
  8. .option("endpoint", {
  9. description:
  10. "Endpoint URL for the price service. e.g: https://endpoint/example",
  11. type: "string",
  12. required: true,
  13. })
  14. .option("price-ids", {
  15. description:
  16. "Space separated price feed ids (in hex without leading 0x) to fetch." +
  17. " e.g: f9c0172ba10dfa4d19088d...",
  18. type: "array",
  19. required: true,
  20. })
  21. .help()
  22. .alias("help", "h")
  23. .parserConfiguration({
  24. "parse-numbers": false,
  25. })
  26. .parseSync();
  27. /**
  28. * Extracts the endpoint and basic authorization headers from a given URL string.
  29. *
  30. * @param {string} urlString - The URL string containing the endpoint and optional basic auth credentials.
  31. * @returns {{ endpoint: string; headers: HeadersInit }} An object containing the endpoint URL and headers.
  32. */
  33. function extractBasicAuthorizationHeadersFromUrl(urlString: string): {
  34. endpoint: string;
  35. headers: HeadersInit;
  36. } {
  37. const url = new URL(urlString);
  38. const headers: HeadersInit = {};
  39. if (url.username && url.password) {
  40. headers["Authorization"] = `Basic ${btoa(
  41. `${url.username}:${url.password}`
  42. )}`;
  43. url.username = "";
  44. url.password = "";
  45. }
  46. return { endpoint: url.toString(), headers };
  47. }
  48. async function run() {
  49. const { endpoint, headers } = extractBasicAuthorizationHeadersFromUrl(
  50. argv.endpoint
  51. );
  52. const connection = new HermesClient(endpoint, { headers });
  53. const priceIds = argv.priceIds as string[];
  54. // Get price feeds
  55. console.log(`Price feeds matching "btc" with asset type "crypto":`);
  56. const priceFeeds = await connection.getPriceFeeds({
  57. query: "btc",
  58. assetType: "crypto",
  59. });
  60. console.log(priceFeeds);
  61. // Latest price updates
  62. console.log(`Latest price updates for price IDs ${priceIds}:`);
  63. const priceUpdates = await connection.getLatestPriceUpdates(priceIds);
  64. console.log(priceUpdates);
  65. // Get the latest 5 second TWAPs
  66. console.log(`Latest 5 second TWAPs for price IDs ${priceIds}`);
  67. const twapUpdates = await connection.getLatestTwaps(priceIds, 5);
  68. console.log(twapUpdates);
  69. // Streaming price updates
  70. console.log(`Streaming latest prices for price IDs ${priceIds}...`);
  71. const eventSource = await connection.getPriceUpdatesStream(priceIds, {
  72. encoding: "hex",
  73. parsed: true,
  74. allowUnordered: false,
  75. benchmarksOnly: true,
  76. });
  77. eventSource.onmessage = (event: MessageEvent<string>) => {
  78. console.log("Received price update:", event.data);
  79. // Variable intentionally unused, prefixed with underscore
  80. const _priceUpdate = JSON.parse(event.data) as PriceUpdate;
  81. };
  82. eventSource.onerror = (error: Event) => {
  83. console.error("Error receiving updates:", error);
  84. eventSource.close();
  85. };
  86. await sleep(5000);
  87. // To stop listening to the updates, you can call eventSource.close();
  88. console.log("Closing event source.");
  89. eventSource.close();
  90. }
  91. run();