parse-price-feed-updates.tsx 4.7 KB

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