-
Notifications
You must be signed in to change notification settings - Fork 222
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: add post partially verified updates example (#2177)
* go * go
- Loading branch information
Showing
1 changed file
with
98 additions
and
0 deletions.
There are no files selected for viewing
98 changes: 98 additions & 0 deletions
98
target_chains/solana/sdk/js/pyth_solana_receiver/examples/post_price_update_atomic.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); |