소스 검색

chore: add post partially verified updates example (#2177)

* go

* go
guibescos 11 달 전
부모
커밋
26236b8407
1개의 변경된 파일98개의 추가작업 그리고 0개의 파일을 삭제
  1. 98 0
      target_chains/solana/sdk/js/pyth_solana_receiver/examples/post_price_update_atomic.ts

+ 98 - 0
target_chains/solana/sdk/js/pyth_solana_receiver/examples/post_price_update_atomic.ts

@@ -0,0 +1,98 @@
+import { Connection, Keypair, PublicKey } from "@solana/web3.js";
+import { InstructionWithEphemeralSigners, PythSolanaReceiver } from "../";
+import { Wallet } from "@coral-xyz/anchor";
+import fs from "fs";
+import os from "os";
+import { HermesClient } from "@pythnetwork/hermes-client";
+
+// Get price feed ids from https://pyth.network/developers/price-feed-ids#pyth-evm-stable
+const SOL_PRICE_FEED_ID =
+  "0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d";
+
+let keypairFile = "";
+if (process.env["SOLANA_KEYPAIR"]) {
+  keypairFile = process.env["SOLANA_KEYPAIR"];
+} else {
+  keypairFile = `${os.homedir()}/.config/solana/id.json`;
+}
+
+async function main() {
+  const connection = new Connection("https://api.devnet.solana.com");
+  const keypair = await loadKeypairFromFile(keypairFile);
+  console.log(
+    `Sending transactions from account: ${keypair.publicKey.toBase58()}`
+  );
+  const wallet = new Wallet(keypair);
+  const pythSolanaReceiver = new PythSolanaReceiver({ connection, wallet });
+
+  // Get the price update from hermes
+  const priceUpdateData = await getPriceUpdateData();
+  console.log(`Posting price update: ${priceUpdateData}`);
+
+  // If closeUpdateAccounts = true, the builder will automatically generate instructions to close the ephemeral price update accounts
+  // at the end of the transaction. Closing the accounts will reclaim their rent.
+  // The example is using closeUpdateAccounts = false so you can easily look up the price update account in an explorer.
+  const transactionBuilder = pythSolanaReceiver.newTransactionBuilder({
+    closeUpdateAccounts: false,
+  });
+  // Post the price updates to ephemeral accounts, one per price feed.
+  // Using this method we can post the price update in a single transaction.
+  // With 5 signatures, the transaction size is 1197 bytes
+  // With 3 signatures, the transaction size is 1065 bytes
+  await transactionBuilder.addPostPartiallyVerifiedPriceUpdates(
+    priceUpdateData
+  );
+  console.log(
+    "The SOL/USD price update will get posted to:",
+    transactionBuilder.getPriceUpdateAccount(SOL_PRICE_FEED_ID).toBase58()
+  );
+
+  await transactionBuilder.addPriceConsumerInstructions(
+    async (
+      getPriceUpdateAccount: (priceFeedId: string) => PublicKey
+    ): Promise<InstructionWithEphemeralSigners[]> => {
+      // You can generate instructions here that use the price updates posted above.
+      // getPriceUpdateAccount(<price feed id>) will give you the account you need.
+      // These accounts will be packed into transactions by the builder.
+      return [];
+    }
+  );
+
+  // Send the instructions in the builder in 1 or more transactions.
+  // The builder will pack the instructions into transactions automatically.
+  await pythSolanaReceiver.provider.sendAll(
+    await transactionBuilder.buildVersionedTransactions({
+      computeUnitPriceMicroLamports: 100000,
+    }),
+    { preflightCommitment: "processed" }
+  );
+}
+
+// Fetch price update data from Hermes
+async function getPriceUpdateData() {
+  const priceServiceConnection = new HermesClient(
+    "https://hermes.pyth.network/",
+    {}
+  );
+
+  const response = await priceServiceConnection.getLatestPriceUpdates(
+    [SOL_PRICE_FEED_ID],
+    { encoding: "base64" }
+  );
+
+  return response.binary.data;
+}
+
+// Load a solana keypair from an id.json file
+async function loadKeypairFromFile(filePath: string): Promise<Keypair> {
+  try {
+    const keypairData = JSON.parse(
+      await fs.promises.readFile(filePath, "utf8")
+    );
+    return Keypair.fromSecretKey(Uint8Array.from(keypairData));
+  } catch (error) {
+    throw new Error(`Error loading keypair from file: ${error}`);
+  }
+}
+
+main();