parse-price-feed-updates.tsx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import {
  2. BTCUSD,
  3. ETHUSD,
  4. getLatestPriceUpdate,
  5. solidity,
  6. ethersJS,
  7. writeApi,
  8. } from "./common";
  9. import { ParameterType } from "../../components/EvmApi";
  10. export const parsePriceFeedUpdates = writeApi<
  11. "updateData" | "priceId" | "minPublishTime" | "maxPublishTime" | "fee"
  12. >({
  13. name: "parsePriceFeedUpdates",
  14. summary:
  15. "Parse `updateData` to return prices if the prices are published within the given time range.",
  16. description: `
  17. This method parse \`updateData\` and return the price feeds for the given \`priceIds\`
  18. within, if they are all published between \`minPublishTime\` and
  19. \`maxPublishTime\` (\`minPublishTime <= publishTime <= maxPublishTime\`).
  20. Use this function if you want to use a Pyth price for a fixed time and not the most
  21. recent price; otherwise, consider using [updatePriceFeeds](update-price-feeds)
  22. followed by [getPriceNoOlderThan](get-price-no-older-than) or one of its variants.
  23. Unlike [updatePriceFeeds](updatePriceFeeds), calling this function will **not** update the on-chain price.
  24. If you need to make sure the price update is the earliest update after the
  25. \`minPublishTime\` consider using
  26. [parsePriceFeedUpdatesUnique](parse-price-feed-updates-unique).
  27. This method requires the caller to pay a fee in wei; the required fee can be
  28. computed by calling [getUpdateFee](get-update-fee) with \`updateData\`.
  29. ### Error Response
  30. The above method can return the following error response:
  31. - \`PriceFeedNotFoundWithinRange\`: No price feed was found within the given time range.
  32. - \`InvalidUpdateData\`: The provided update data is invalid or incorrectly signed.
  33. - \`InsufficientFee\`: The fee provided is less than the required fee. Try calling [getUpdateFee](getUpdateFee) to get the required fee.
  34. `,
  35. parameters: [
  36. {
  37. name: "updateData",
  38. type: ParameterType.HexArray,
  39. description:
  40. "The price update data for the contract to verify. Fetch this data from [Hermes API](https://hermes.pyth.network/docs/#/rest/latest_price_updates).",
  41. defaultValue:
  42. "0x504e41550100000003b801000000040d00cea20e5677f66ed178e9410ddd8280617c06921916e8fd4b71e597d7f6c6d0a14daf3bb3e1a0d8c9e051c8d0................",
  43. },
  44. {
  45. name: "priceId",
  46. type: ParameterType.PriceFeedIdArray,
  47. description: "The price ids whose feeds will be returned.",
  48. },
  49. {
  50. name: "minPublishTime",
  51. type: ParameterType.Int,
  52. description: "The minimum timestamp for each returned feed.",
  53. defaultValue: "1721765108",
  54. },
  55. {
  56. name: "maxPublishTime",
  57. type: ParameterType.Int,
  58. description: "The maximum timestamp for each returned feed.",
  59. defaultValue: "1721765108",
  60. },
  61. {
  62. name: "fee",
  63. type: ParameterType.Int,
  64. description:
  65. "The update fee in wei. This fee is sent as the value of the transaction.",
  66. defaultValue: "1",
  67. },
  68. ],
  69. valueParam: "fee",
  70. examples: [
  71. {
  72. name: "Latest BTC/USD update data",
  73. parameters: (ctx) => getParams(BTCUSD, ctx),
  74. },
  75. {
  76. name: "Latest ETH/USD update data",
  77. parameters: (ctx) => getParams(ETHUSD, ctx),
  78. },
  79. ],
  80. code: [
  81. solidity(
  82. ({ updateData, priceId, minPublishTime, maxPublishTime, fee }) => `
  83. bytes[] memory updateData = new bytes[](1);
  84. updateData[0] = ${updateData ? `hex"${updateData}` : "/* <updateData> */"};
  85. bytes32[] memory priceIds = new bytes32[](1);
  86. priceIds[0] = ${priceId ?? "/* <priceId> */"};
  87. uint64 minPublishTime = ${minPublishTime ?? "/* <minPublishTime> */"};
  88. uint64 maxPublishTime = ${maxPublishTime ?? "/* <maxPublishTime> */"};
  89. uint fee = ${fee ?? "/* <fee> */"};
  90. pyth.parsePriceFeedUpdates{value: fee}(updateData, priceIds, minPublishTime, maxPublishTime);
  91. `,
  92. ),
  93. ethersJS(
  94. ({ updateData, priceId, minPublishTime, maxPublishTime, fee }) => `
  95. const updateData = ${updateData ? `['${updateData}']` : "/* <updateData> */"};
  96. const priceIds = ${priceId ? `['${priceId}']` : "/* <priceId> */"};
  97. const minPublishTime = ethers.toBigInt(${minPublishTime ?? "/* <minPublishTime> */"});
  98. const maxPublishTime = ethers.toBigInt(${maxPublishTime ?? "/* <maxPublishTime> */"});
  99. const fee = ethers.toBigInt(${fee ?? "/* <fee> */"});
  100. const tx = await contract.parsePriceFeedUpdates(updateData, priceIds, minPublishTime, maxPublishTime, {value: fee});
  101. const receipt = await tx.wait();
  102. `,
  103. ),
  104. ],
  105. });
  106. const getParams = async (
  107. priceId: string,
  108. ctx: {
  109. readContract: (name: string, args: unknown[]) => Promise<unknown>;
  110. },
  111. ) => {
  112. const feed = await getLatestPriceUpdate(priceId);
  113. const fee = await ctx.readContract("getUpdateFee", [[feed.binary.data]]);
  114. if (typeof fee !== "bigint") {
  115. throw new TypeError("Invalid fee");
  116. }
  117. return {
  118. updateData: feed.binary.data,
  119. priceId,
  120. minPublishTime: (feed.parsed.price.publish_time - 5).toString(),
  121. maxPublishTime: (feed.parsed.price.publish_time + 5).toString(),
  122. fee: fee.toString(),
  123. };
  124. };