Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add : Client example #1824

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 113 additions & 18 deletions target_chains/solana/pyth_solana_receiver_sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,37 +22,132 @@ You should also check the `verification_level` of the account. Read more about t
A Solana program can consume price update accounts created by the Pyth Solana Receiver using this SDK:

```rust

use anchor_lang::prelude::*;
use pyth_solana_receiver_sdk::price_update::{get_feed_id_from_hex, PriceUpdateV2};

declare_id!("2e5gZD3suxgJgkCg4pkoogxDKszy1SAwokz8mNeZUj4M");
declare_id!("2UA3M6dSJQjrfTdzAiL2vMvubWoch1nTXK5TRaNGuiY4");

pub const MAXIMUM_AGE: u64 = 60; // One minute
pub const FEED_ID: &str = "0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d"; // SOL/USD price feed id from https://pyth.network/developers/price-feed-ids
#[derive(Accounts)]
#[instruction(id:String)]
pub struct Sample<'info> {
#[account(mut)]
pub payer: Signer<'info>,
// Add this account to any instruction Context that needs price data.
pub price_update: Account<'info, PriceUpdateV2>,
}

#[program]
pub mod my_first_pyth_app {
pub mod pyth_oracle_1 {

use super::*;

pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
pub fn sample(ctx: Context<Sample>, id: String) -> Result<()> {
let price_update = &mut ctx.accounts.price_update;
let price = price_update.get_price_no_older_than(
&Clock::get()?,
MAXIMUM_AGE,
&get_feed_id_from_hex(FEED_ID)?,
)?;
/// Do something with the price
let maximum_age: u64 = 30;
let feed_id: [u8; 32] = get_feed_id_from_hex(&id)?;
let price = price_update.get_price_no_older_than(&Clock::get()?, maximum_age, &feed_id)?;

msg!(
"The price is ({} ± {}) * 10^{}",
price.price,
price.conf,
price.exponent
);
Ok(())
}
}

#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(mut)]
pub payer: Signer<'info>,
pub price_update: Account<'info, PriceUpdateV2>,
// Add more accounts here
}
```
## Test
To test this contract :

```typescript

import * as anchor from "@coral-xyz/anchor";
import { Program } from "@coral-xyz/anchor";
import { PythOracle1 } from "../target/types/pyth_oracle_1";
import {
PythSolanaReceiver,
InstructionWithEphemeralSigners,
} from "@pythnetwork/pyth-solana-receiver";
import * as buffer from "buffer";
import { AnchorProvider, BN, Wallet } from "@coral-xyz/anchor";
import { PriceServiceConnection } from "@pythnetwork/price-service-client";
import { Transaction } from "@solana/web3.js";
const { SystemProgram, Keypair, Connection, PublicKey } = require('@solana/web3.js');
const fs = require('fs');
const path = require('path');
const readline = require('readline');
const SOL_PRICE_FEED_ID = "0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43"; //BTC/USD
const HERMES_URL = "https://hermes.pyth.network/";
const DEVNET_RPC_URL = "https://api.devnet.solana.com";
const connection = new Connection(DEVNET_RPC_URL);
const provider = anchor.AnchorProvider.env()
const wallet = anchor.web3.Keypair.fromSecretKey(new Uint8Array(JSON.parse(fs.readFileSync("PATH_TO_WALLET", 'utf8'))));

describe("pyth_oracle_1", () => {

anchor.setProvider(provider);

const program = anchor.workspace.PythOracle1 as Program<PythOracle1>;

it("Is initialized!", async () => {
const priceServiceConnection = new PriceServiceConnection(HERMES_URL, {
priceFeedRequestConfig: { binary: true },
});

const pythSolanaReceiver = new PythSolanaReceiver({
connection: connection,
wallet: new Wallet(wallet),
});
const priceUpdateData = await priceServiceConnection.getLatestVaas([SOL_PRICE_FEED_ID]);

// Build transaction
const transactionBuilder = pythSolanaReceiver.newTransactionBuilder({
closeUpdateAccounts: true,
});
await transactionBuilder.addPostPriceUpdates([priceUpdateData[0]]);

await transactionBuilder.addPriceConsumerInstructions(
async (getPriceUpdateAccount: (priceFeedId: string) => typeof PublicKey): Promise<InstructionWithEphemeralSigners[]> => {
return [{
instruction: await program.methods
.sample(SOL_PRICE_FEED_ID) // Replace with your actual method and parameters
.accounts({
payer: wallet.publicKey,
priceUpdate: getPriceUpdateAccount(SOL_PRICE_FEED_ID),
// Add other required accounts here
})
.instruction(),
signers: [],
}];
}
);

const txs = await pythSolanaReceiver.provider.sendAll(
await transactionBuilder.buildVersionedTransactions({
computeUnitPriceMicroLamports: 50000,
}),
{ skipPreflight: true }
);
for (const signature of txs) {
try {
const tx = await connection.getTransaction(signature, { maxSupportedTransactionVersion: 0 }, { commitment: 'confirmed' });

if (tx && tx.meta && tx.meta.logMessages) {
console.log("Transaction logs:", tx.meta.logMessages);
} else {
console.log(" Solana Explorer:");
console.log(`https://explorer.solana.com/tx/${signature}?cluster=devnet`);
}
} catch (error) {
console.error("Error fetching transaction logs for signature:", signature, error);
}
}


});
});

```
Loading