Browse Source

docs(solana_sdk): Improve docs (#1414)

* Checkpoint

* Checkpoint

* Checkpoint

* Checkpoint

* fix: pusher

* Checkpoint

* Works

* fix: pass pusher program id

* Add docs

* 0.1.0

* Bump npm package

* Go

* Comment

* Add customizable shard id

* Allow configurable priority fees

* Update readme

* Update text

* readme updates

* Readme

* More text

* More text

* Review

* Text

* readme

* add processed commitment

* fix comment

* whoops

* Set compute units to a more reasonable value

---------

Co-authored-by: Jayant Krishnamurthy <jayantkrishnamurthy@gmail.com>
guibescos 1 year ago
parent
commit
bb830e1760

File diff suppressed because it is too large
+ 72 - 15
target_chains/solana/sdk/js/pyth_solana_receiver/README.md


+ 96 - 0
target_chains/solana/sdk/js/pyth_solana_receiver/examples/post_price_update.ts

@@ -0,0 +1,96 @@
+import { Connection, Keypair, PublicKey } from "@solana/web3.js";
+import { PriceServiceConnection } from "@pythnetwork/price-service-client";
+import {
+  InstructionWithEphemeralSigners,
+  PythSolanaReceiver,
+} from "@pythnetwork/pyth-solana-receiver";
+import { Wallet } from "@coral-xyz/anchor";
+import fs from "fs";
+import os from "os";
+
+// Get price feed ids from https://pyth.network/developers/price-feed-ids#pyth-evm-stable
+const SOL_PRICE_FEED_ID =
+  "0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d";
+const ETH_PRICE_FEED_ID =
+  "0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace";
+
+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.
+  await transactionBuilder.addPostPriceUpdates(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 PriceServiceConnection(
+    "https://hermes.pyth.network/",
+    { priceFeedRequestConfig: { binary: true } }
+  );
+
+  return await priceServiceConnection.getLatestVaas([
+    SOL_PRICE_FEED_ID,
+    ETH_PRICE_FEED_ID,
+  ]);
+}
+
+// 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();

+ 87 - 0
target_chains/solana/sdk/js/pyth_solana_receiver/examples/post_price_update_instructions.ts

@@ -0,0 +1,87 @@
+import { Connection, Keypair } from "@solana/web3.js";
+import { PriceServiceConnection } from "@pythnetwork/price-service-client";
+import {
+  InstructionWithEphemeralSigners,
+  PythSolanaReceiver,
+} from "@pythnetwork/pyth-solana-receiver";
+import { Wallet } from "@coral-xyz/anchor";
+import fs from "fs";
+import os from "os";
+
+// Get price feed ids from https://pyth.network/developers/price-feed-ids#pyth-evm-stable
+const SOL_PRICE_FEED_ID =
+  "0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d";
+const ETH_PRICE_FEED_ID =
+  "0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace";
+
+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}`);
+
+  // Get instructions to post the price update data and to close the accounts later
+  const {
+    postInstructions,
+    closeInstructions,
+    priceFeedIdToPriceUpdateAccount,
+  } = await pythSolanaReceiver.buildPostPriceUpdateInstructions(
+    priceUpdateData
+  );
+  console.log(
+    "The SOL/USD price update will get posted to:",
+    priceFeedIdToPriceUpdateAccount[SOL_PRICE_FEED_ID].toBase58()
+  );
+
+  // Put your instructions here
+  const consumerInstructions: InstructionWithEphemeralSigners[] = [];
+
+  const transactions = await pythSolanaReceiver.batchIntoVersionedTransactions(
+    [...postInstructions, ...consumerInstructions, ...closeInstructions],
+    { computeUnitPriceMicroLamports: 100000 }
+  ); // Put all the instructions together
+  await pythSolanaReceiver.provider.sendAll(transactions, {
+    preflightCommitment: "processed",
+  });
+}
+
+// Fetch price update data from Hermes
+async function getPriceUpdateData() {
+  const priceServiceConnection = new PriceServiceConnection(
+    "https://hermes.pyth.network/",
+    { priceFeedRequestConfig: { binary: true } }
+  );
+
+  return await priceServiceConnection.getLatestVaas([
+    SOL_PRICE_FEED_ID,
+    ETH_PRICE_FEED_ID,
+  ]);
+}
+
+// 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();

+ 96 - 0
target_chains/solana/sdk/js/pyth_solana_receiver/examples/update_price_feed.ts

@@ -0,0 +1,96 @@
+import { Connection, Keypair, PublicKey } from "@solana/web3.js";
+import { PriceServiceConnection } from "@pythnetwork/price-service-client";
+import {
+  InstructionWithEphemeralSigners,
+  PythSolanaReceiver,
+} from "@pythnetwork/pyth-solana-receiver";
+import { Wallet } from "@coral-xyz/anchor";
+import fs from "fs";
+import os from "os";
+
+// Get price feed ids from https://pyth.network/developers/price-feed-ids#pyth-evm-stable
+const SOL_PRICE_FEED_ID =
+  "0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d";
+const ETH_PRICE_FEED_ID =
+  "0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace";
+
+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}`);
+
+  // The shard indicates which set of price feed accounts you wish to update.
+  const shardId = 1;
+
+  const transactionBuilder = pythSolanaReceiver.newTransactionBuilder({});
+  // Update the price feed accounts for the feed ids in priceUpdateData (in this example, SOL and ETH) and shard id.
+  await transactionBuilder.addUpdatePriceFeed(priceUpdateData, shardId);
+  console.log(
+    "The SOL/USD price update will get posted to:",
+    pythSolanaReceiver
+      .getPriceFeedAccountAddress(shardId, 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 PriceServiceConnection(
+    "https://hermes.pyth.network/",
+    { priceFeedRequestConfig: { binary: true } }
+  );
+
+  return await priceServiceConnection.getLatestVaas([
+    SOL_PRICE_FEED_ID,
+    ETH_PRICE_FEED_ID,
+  ]);
+}
+
+// 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();

+ 1 - 1
target_chains/solana/sdk/js/pyth_solana_receiver/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@pythnetwork/pyth-solana-receiver",
   "name": "@pythnetwork/pyth-solana-receiver",
-  "version": "0.4.0",
+  "version": "0.5.0",
   "description": "Pyth solana receiver SDK",
   "description": "Pyth solana receiver SDK",
   "homepage": "https://pyth.network",
   "homepage": "https://pyth.network",
   "main": "lib/index.js",
   "main": "lib/index.js",

+ 57 - 26
target_chains/solana/sdk/js/pyth_solana_receiver/src/PythSolanaReceiver.ts

@@ -61,12 +61,21 @@ export type PythTransactionBuilderConfig = {
 
 
 /**
 /**
  * A builder class to build transactions that:
  * A builder class to build transactions that:
- * - Post price updates (fully or partially verified)
+ * - Post price updates (fully or partially verified) or update price feed accounts
  * - Consume price updates in a consumer program
  * - Consume price updates in a consumer program
  * - (Optionally) Close price update and encoded vaa accounts to recover the rent (`closeUpdateAccounts` in `PythTransactionBuilderConfig`)
  * - (Optionally) Close price update and encoded vaa accounts to recover the rent (`closeUpdateAccounts` in `PythTransactionBuilderConfig`)
  *
  *
+ * This class provides methods for working with both price update accounts and price feed accounts.
+ * Price update accounts are ephemeral accounts containing a single price update, whereas price feed accounts are long-lived
+ * accounts that always hold price data for a specific feed id. Price feed accounts can be updated to advance the current price.
+ * Applications should choose which type of account to work with based on their needs. In general, applications that
+ * want the price at a specific time (e.g., to settle a trade) should use price update accounts, while applications that want
+ * any recent price should use price feed accounts.
+ *
  * @example
  * @example
  * ```typescript
  * ```typescript
+ *
+ * // Get the price feed ids from https://pyth.network/developers/price-feed-ids#pyth-evm-stable
  *  const priceUpdateData = await priceServiceConnection.getLatestVaas([
  *  const priceUpdateData = await priceServiceConnection.getLatestVaas([
  *    SOL_PRICE_FEED_ID,
  *    SOL_PRICE_FEED_ID,
  *    ETH_PRICE_FEED_ID,
  *    ETH_PRICE_FEED_ID,
@@ -74,9 +83,10 @@ export type PythTransactionBuilderConfig = {
  *
  *
  * const transactionBuilder = pythSolanaReceiver.newTransactionBuilder({});
  * const transactionBuilder = pythSolanaReceiver.newTransactionBuilder({});
  * await transactionBuilder.addPostPriceUpdates(priceUpdateData);
  * await transactionBuilder.addPostPriceUpdates(priceUpdateData);
+ * console.log("The SOL/USD price update will get posted to:", transactionBuilder.getPriceUpdateAccount(SOL_PRICE_FEED_ID).toBase58())
  * await transactionBuilder.addPriceConsumerInstructions(...)
  * await transactionBuilder.addPriceConsumerInstructions(...)
  *
  *
- * await pythSolanaReceiver.provider.sendAll(await transactionBuilder.buildVersionedTransactions({computeUnitPriceMicroLamports:1000000}))
+ * await pythSolanaReceiver.provider.sendAll(await transactionBuilder.buildVersionedTransactions({computeUnitPriceMicroLamports:100000}))
  * ```
  * ```
  */
  */
 export class PythTransactionBuilder extends TransactionBuilder {
 export class PythTransactionBuilder extends TransactionBuilder {
@@ -98,11 +108,13 @@ export class PythTransactionBuilder extends TransactionBuilder {
 
 
   /**
   /**
    * Add instructions to post price updates to the builder.
    * Add instructions to post price updates to the builder.
+   * Use this function to post fully verified price updates from the present or from the past for your program to consume.
    *
    *
    * @param priceUpdateDataArray the output of the `@pythnetwork/price-service-client`'s `PriceServiceConnection.getLatestVaas`. This is an array of verifiable price updates.
    * @param priceUpdateDataArray the output of the `@pythnetwork/price-service-client`'s `PriceServiceConnection.getLatestVaas`. This is an array of verifiable price updates.
    *
    *
    * @example
    * @example
    * ```typescript
    * ```typescript
+   * // Get the price feed ids from https://pyth.network/developers/price-feed-ids#pyth-evm-stable
    * const priceUpdateData = await priceServiceConnection.getLatestVaas([
    * const priceUpdateData = await priceServiceConnection.getLatestVaas([
    *    SOL_PRICE_FEED_ID,
    *    SOL_PRICE_FEED_ID,
    *    ETH_PRICE_FEED_ID,
    *    ETH_PRICE_FEED_ID,
@@ -110,6 +122,7 @@ export class PythTransactionBuilder extends TransactionBuilder {
    *
    *
    * const transactionBuilder = pythSolanaReceiver.newTransactionBuilder({});
    * const transactionBuilder = pythSolanaReceiver.newTransactionBuilder({});
    * await transactionBuilder.addPostPriceUpdates(priceUpdateData);
    * await transactionBuilder.addPostPriceUpdates(priceUpdateData);
+   * console.log("The SOL/USD price update will get posted to:", transactionBuilder.getPriceUpdateAccount(SOL_PRICE_FEED_ID).toBase58())
    * await transactionBuilder.addPriceConsumerInstructions(...)
    * await transactionBuilder.addPriceConsumerInstructions(...)
    * ```
    * ```
    */
    */
@@ -131,6 +144,7 @@ export class PythTransactionBuilder extends TransactionBuilder {
 
 
   /**
   /**
    * Add instructions to post partially verified price updates to the builder.
    * Add instructions to post partially verified price updates to the builder.
+   * Use this function to post partially verified price updates from the present or from the past for your program to consume.
    *
    *
    * @param priceUpdateDataArray the output of the `@pythnetwork/price-service-client`'s `PriceServiceConnection.getLatestVaas`. This is an array of verifiable price updates.
    * @param priceUpdateDataArray the output of the `@pythnetwork/price-service-client`'s `PriceServiceConnection.getLatestVaas`. This is an array of verifiable price updates.
    *
    *
@@ -139,6 +153,7 @@ export class PythTransactionBuilder extends TransactionBuilder {
    *
    *
    * @example
    * @example
    * ```typescript
    * ```typescript
+   * // Get the price feed ids from https://pyth.network/developers/price-feed-ids#pyth-evm-stable
    * const priceUpdateData = await priceServiceConnection.getLatestVaas([
    * const priceUpdateData = await priceServiceConnection.getLatestVaas([
    *    SOL_PRICE_FEED_ID,
    *    SOL_PRICE_FEED_ID,
    *    ETH_PRICE_FEED_ID,
    *    ETH_PRICE_FEED_ID,
@@ -146,6 +161,7 @@ export class PythTransactionBuilder extends TransactionBuilder {
    *
    *
    * const transactionBuilder = pythSolanaReceiver.newTransactionBuilder({});
    * const transactionBuilder = pythSolanaReceiver.newTransactionBuilder({});
    * await transactionBuilder.addPostPartiallyVerifiedPriceUpdates(priceUpdateData);
    * 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(...)
    * await transactionBuilder.addPriceConsumerInstructions(...)
    * ...
    * ...
    * ```
    * ```
@@ -168,15 +184,14 @@ export class PythTransactionBuilder extends TransactionBuilder {
 
 
   /**
   /**
    * Add instructions to update price feed accounts to the builder.
    * Add instructions to update price feed accounts to the builder.
+   * Price feed accounts are fixed accounts per price feed id that can only be updated with a more recent price.
    *
    *
    * @param priceUpdateDataArray the output of the `@pythnetwork/price-service-client`'s `PriceServiceConnection.getLatestVaas`. This is an array of verifiable price updates.
    * @param priceUpdateDataArray the output of the `@pythnetwork/price-service-client`'s `PriceServiceConnection.getLatestVaas`. This is an array of verifiable price updates.
-   * @param shardId the shard ID of the set of price feed accounts. This shard ID allows for multiple sets of price feed accounts to be managed by the same program.
-   *
-   * Price feed accounts are a special type of price update accounts.
-   * Instead of using ephemeral addresses, they are PDAs of the Pyth Push Oracle program derived from the feed ID. They can only be updated with a more recent price update.
+   * @param shardId the shard ID of the set of price feed accounts. This shard ID allows for multiple price feed accounts for the same price feed id to exist.
    *
    *
    * @example
    * @example
    * ```typescript
    * ```typescript
+   * // Get the price feed ids from https://pyth.network/developers/price-feed-ids#pyth-evm-stable
    * const priceUpdateData = await priceServiceConnection.getLatestVaas([
    * const priceUpdateData = await priceServiceConnection.getLatestVaas([
    *    SOL_PRICE_FEED_ID,
    *    SOL_PRICE_FEED_ID,
    *    ETH_PRICE_FEED_ID,
    *    ETH_PRICE_FEED_ID,
@@ -561,7 +576,7 @@ export class PythSolanaReceiver {
    * Build a series of helper instructions that update one or many price feed accounts and another series to close the encoded vaa accounts used to update the price feed accounts.
    * Build a series of helper instructions that update one or many price feed accounts and another series to close the encoded vaa accounts used to update the price feed accounts.
    *
    *
    * @param priceUpdateDataArray the output of the `@pythnetwork/price-service-client`'s `PriceServiceConnection.getLatestVaas`. This is an array of verifiable price updates.
    * @param priceUpdateDataArray the output of the `@pythnetwork/price-service-client`'s `PriceServiceConnection.getLatestVaas`. This is an array of verifiable price updates.
-   * @param shardId the shard ID of the set of price feed accounts. This shard ID allows for multiple sets of price feed accounts to be managed by the same program.
+   * @param shardId the shard ID of the set of price feed accounts. This shard ID allows for multiple price feed accounts for the same price feed id to exist.
    * @returns `postInstructions`: the instructions to update the price feed accounts. If the price feed accounts don't contain a recent update, these should be called before consuming the price updates.
    * @returns `postInstructions`: the instructions to update the price feed accounts. If the price feed accounts don't contain a recent update, these should be called before consuming the price updates.
    * @returns `priceFeedIdToPriceUpdateAccount`: this is a map of price feed IDs to Solana address. Given a price feed ID, you can use this map to find the account where `postInstructions` will post the price update. Note that since price feed accounts are PDAs, the address of the account can also be found with `getPriceFeedAccountAddress`.
    * @returns `priceFeedIdToPriceUpdateAccount`: this is a map of price feed IDs to Solana address. Given a price feed ID, you can use this map to find the account where `postInstructions` will post the price update. Note that since price feed accounts are PDAs, the address of the account can also be found with `getPriceFeedAccountAddress`.
    * @returns `closeInstructions`: the instructions to close the encoded VAA accounts that were used to update the price feed accounts.
    * @returns `closeInstructions`: the instructions to close the encoded VAA accounts that were used to update the price feed accounts.
@@ -607,10 +622,9 @@ export class PythSolanaReceiver {
             .accounts({
             .accounts({
               pythSolanaReceiver: this.receiver.programId,
               pythSolanaReceiver: this.receiver.programId,
               encodedVaa,
               encodedVaa,
-              priceFeedAccount: getPriceFeedAccountAddress(
+              priceFeedAccount: this.getPriceFeedAccountAddress(
                 shardId,
                 shardId,
-                feedId,
-                this.pushOracle.programId
+                feedId
               ),
               ),
               treasury: getTreasuryPda(
               treasury: getTreasuryPda(
                 DEFAULT_TREASURY_ID,
                 DEFAULT_TREASURY_ID,
@@ -625,11 +639,7 @@ export class PythSolanaReceiver {
 
 
         priceFeedIdToPriceUpdateAccount[
         priceFeedIdToPriceUpdateAccount[
           "0x" + parsePriceFeedMessage(update.message).feedId.toString("hex")
           "0x" + parsePriceFeedMessage(update.message).feedId.toString("hex")
-        ] = getPriceFeedAccountAddress(
-          shardId,
-          feedId,
-          this.pushOracle.programId
-        );
+        ] = this.getPriceFeedAccountAddress(shardId, feedId);
       }
       }
     }
     }
     return {
     return {
@@ -695,7 +705,7 @@ export class PythSolanaReceiver {
 
 
   /**
   /**
    * Fetch the contents of a price feed account
    * Fetch the contents of a price feed account
-   * @param shardId The shard ID of the set of price feed accounts. This shard ID allows for multiple sets of price feed accounts to be managed by the same program.
+   * @param shardId The shard ID of the set of price feed accounts. This shard ID allows for multiple price feed accounts for the same price feed id to exist.
    * @param priceFeedId The price feed ID.
    * @param priceFeedId The price feed ID.
    * @returns The contents of the deserialized price feed account or `null` if the account doesn't exist
    * @returns The contents of the deserialized price feed account or `null` if the account doesn't exist
    */
    */
@@ -704,35 +714,56 @@ export class PythSolanaReceiver {
     priceFeedId: Buffer
     priceFeedId: Buffer
   ): Promise<PriceUpdateAccount | null> {
   ): Promise<PriceUpdateAccount | null> {
     return this.receiver.account.priceUpdateV2.fetchNullable(
     return this.receiver.account.priceUpdateV2.fetchNullable(
-      getPriceFeedAccountAddress(
-        shardId,
-        priceFeedId,
-        this.pushOracle.programId
-      )
+      this.getPriceFeedAccountAddress(shardId, priceFeedId)
+    );
+  }
+
+  /**
+   * Derive the address of a price feed account
+   * @param shardId The shard ID of the set of price feed accounts. This shard ID allows for multiple price feed accounts for the same price feed id to exist.
+   * @param priceFeedId The price feed ID.
+   * @returns The address of the price feed account
+   */
+  getPriceFeedAccountAddress(
+    shardId: number,
+    priceFeedId: Buffer | string
+  ): PublicKey {
+    return getPriceFeedAccountForProgram(
+      shardId,
+      priceFeedId,
+      this.pushOracle.programId
     );
     );
   }
   }
 }
 }
 
 
 /**
 /**
  * Derive the address of a price feed account
  * Derive the address of a price feed account
- * @param shardId The shard ID of the set of price feed accounts. This shard ID allows for multiple sets of price feed accounts to be managed by the same program.
+ * @param shardId The shard ID of the set of price feed accounts. This shard ID allows for multiple price feed accounts for the same price feed id to exist.
  * @param priceFeedId The price feed ID.
  * @param priceFeedId The price feed ID.
  * @param pushOracleProgramId The program ID of the Pyth Push Oracle program. If not provided, the default deployment will be used.
  * @param pushOracleProgramId The program ID of the Pyth Push Oracle program. If not provided, the default deployment will be used.
  * @returns The address of the price feed account
  * @returns The address of the price feed account
  */
  */
-function getPriceFeedAccountAddress(
+function getPriceFeedAccountForProgram(
   shardId: number,
   shardId: number,
-  feedId: Buffer,
+  priceFeedId: Buffer | string,
   pushOracleProgramId?: PublicKey
   pushOracleProgramId?: PublicKey
 ): PublicKey {
 ): PublicKey {
-  if (feedId.length != 32) {
+  if (typeof priceFeedId == "string") {
+    if (priceFeedId.startsWith("0x")) {
+      priceFeedId = Buffer.from(priceFeedId.slice(2), "hex");
+    } else {
+      priceFeedId = Buffer.from(priceFeedId, "hex");
+    }
+  }
+
+  if (priceFeedId.length != 32) {
     throw new Error("Feed ID should be 32 bytes long");
     throw new Error("Feed ID should be 32 bytes long");
   }
   }
   const shardBuffer = Buffer.alloc(2);
   const shardBuffer = Buffer.alloc(2);
   shardBuffer.writeUint16LE(shardId, 0);
   shardBuffer.writeUint16LE(shardId, 0);
 
 
   return PublicKey.findProgramAddressSync(
   return PublicKey.findProgramAddressSync(
-    [shardBuffer, feedId],
+    [shardBuffer, priceFeedId],
     pushOracleProgramId ?? DEFAULT_PUSH_ORACLE_PROGRAM_ID
     pushOracleProgramId ?? DEFAULT_PUSH_ORACLE_PROGRAM_ID
   )[0];
   )[0];
 }
 }

Some files were not shown because too many files changed in this diff