Skip to content

Commit

Permalink
chore: add post partially verified updates example (#2177)
Browse files Browse the repository at this point in the history
* go

* go
  • Loading branch information
guibescos authored Dec 9, 2024
1 parent b451050 commit 26236b8
Showing 1 changed file with 98 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -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();

0 comments on commit 26236b8

Please sign in to comment.