fetch-and-verify-update.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import { SuiClient } from "@mysten/sui/client";
  2. import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
  3. import { Transaction } from "@mysten/sui/transactions";
  4. import { PythLazerClient } from "@pythnetwork/pyth-lazer-sdk";
  5. import yargs from "yargs";
  6. import { hideBin } from "yargs/helpers";
  7. import { addParseAndVerifyLeEcdsaUpdateCall } from "../src/client.js";
  8. async function getOneLeEcdsaUpdate(token: string) {
  9. const lazer = await PythLazerClient.create({
  10. token,
  11. });
  12. const latestPrice = await lazer.get_latest_price({
  13. priceFeedIds: [1],
  14. properties: ["price", "bestBidPrice", "bestAskPrice", "exponent"],
  15. formats: ["leEcdsa"],
  16. channel: "fixed_rate@200ms",
  17. jsonBinaryEncoding: "hex",
  18. });
  19. return latestPrice;
  20. }
  21. async function main() {
  22. const args = await yargs(hideBin(process.argv))
  23. .option("fullnodeUrl", {
  24. type: "string",
  25. description:
  26. "URL of the full Sui node RPC endpoint. e.g: https://fullnode.testnet.sui.io:443",
  27. demandOption: true,
  28. })
  29. .option("packageId", {
  30. type: "string",
  31. description: "Lazer contract package ID",
  32. demandOption: true,
  33. })
  34. .option("stateObjectId", {
  35. type: "string",
  36. description: "Lazer contract shared State object ID",
  37. demandOption: true,
  38. })
  39. .option("lazerUrls", {
  40. type: "array",
  41. string: true,
  42. description: "Lazer WebSocket URLs",
  43. default: [
  44. "wss://pyth-lazer-0.dourolabs.app/v1/stream",
  45. "wss://pyth-lazer-1.dourolabs.app/v1/stream",
  46. ],
  47. })
  48. .option("lazerToken", {
  49. type: "string",
  50. description: "Lazer authentication token",
  51. demandOption: true,
  52. })
  53. .help()
  54. .parseAsync();
  55. // Defined as a dependency in turbo.json
  56. // eslint-disable-next-line n/no-process-env
  57. if (process.env.SUI_KEY === undefined) {
  58. throw new Error(
  59. `SUI_KEY environment variable should be set to your Sui private key in hex format.`,
  60. );
  61. }
  62. const provider = new SuiClient({ url: args.fullnodeUrl });
  63. // Fetch the price update
  64. const update = await getOneLeEcdsaUpdate(args.lazerToken);
  65. // Build the Sui transaction
  66. const tx = new Transaction();
  67. // Add the parse and verify call
  68. addParseAndVerifyLeEcdsaUpdateCall({
  69. tx,
  70. packageId: args.packageId,
  71. stateObjectId: args.stateObjectId,
  72. updateBytes: Buffer.from(update.leEcdsa?.data ?? "", "hex"),
  73. });
  74. // --- You can add more calls to the transaction that consume the parsed update here ---
  75. const wallet = Ed25519Keypair.fromSecretKey(
  76. // eslint-disable-next-line n/no-process-env
  77. Buffer.from(process.env.SUI_KEY, "hex"),
  78. );
  79. const res = await provider.signAndExecuteTransaction({
  80. signer: wallet,
  81. transaction: tx,
  82. options: { showEffects: true, showEvents: true },
  83. });
  84. // eslint-disable-next-line no-console
  85. console.log("Execution result:", JSON.stringify(res, undefined, 2));
  86. }
  87. // eslint-disable-next-line unicorn/prefer-top-level-await
  88. main().catch((error: unknown) => {
  89. throw error;
  90. });