gmsol/pyth/pull_oracle/receiver/
mod.rs1use std::{ops::Deref, sync::Arc};
2
3use anchor_client::solana_sdk::{
4 pubkey::Pubkey, signature::Keypair, signer::Signer, system_program,
5};
6use gmsol_solana_utils::{
7 compute_budget::ComputeBudget, program::Program, transaction_builder::TransactionBuilder,
8};
9use pythnet_sdk::wire::v1::MerklePriceUpdate;
10
11mod accounts;
12mod instruction;
13
14pub const TREASURY_SEED: &[u8] = b"treasury";
16
17pub const CONFIG_SEED: &[u8] = b"config";
19
20pub const POST_PRICE_UPDATE_COMPUTE_BUDGET: u32 = 80_000;
22
23pub const RECLAIM_RENT_COMPUTE_BUDGET: u32 = 4_000;
25
26pub fn find_treasury_pda(treasury_id: u8) -> (Pubkey, u8) {
28 Pubkey::find_program_address(
29 &[TREASURY_SEED, &[treasury_id]],
30 &pyth_solana_receiver_sdk::ID,
31 )
32}
33
34pub fn find_config_pda() -> (Pubkey, u8) {
36 Pubkey::find_program_address(&[CONFIG_SEED], &pyth_solana_receiver_sdk::ID)
37}
38
39pub trait PythReceiverOps<C> {
41 fn post_price_update<'a>(
43 &'a self,
44 price_update: Keypair,
45 update: &MerklePriceUpdate,
46 encoded_vaa: &Pubkey,
47 ) -> crate::Result<TransactionBuilder<'a, C, Pubkey>>;
48
49 fn reclaim_rent(&self, price_update: &Pubkey) -> TransactionBuilder<C>;
51}
52
53impl<S, C> PythReceiverOps<C> for Program<C>
54where
55 C: Deref<Target = S> + Clone,
56 S: Signer,
57{
58 fn post_price_update<'a>(
59 &'a self,
60 price_update: Keypair,
61 update: &MerklePriceUpdate,
62 encoded_vaa: &Pubkey,
63 ) -> crate::Result<TransactionBuilder<'a, C, Pubkey>> {
64 let treasury_id = rand::random();
65 Ok(self
66 .transaction()
67 .output(price_update.pubkey())
68 .anchor_args(instruction::PostUpdate {
69 merkle_price_update: update.clone(),
70 treasury_id,
71 })
72 .anchor_accounts(accounts::PostUpdate {
73 payer: self.payer(),
74 encoded_vaa: *encoded_vaa,
75 config: find_config_pda().0,
76 treasury: find_treasury_pda(treasury_id).0,
77 price_update_account: price_update.pubkey(),
78 system_program: system_program::ID,
79 write_authority: self.payer(),
80 })
81 .owned_signer(Arc::new(price_update))
82 .compute_budget(ComputeBudget::default().with_limit(POST_PRICE_UPDATE_COMPUTE_BUDGET)))
83 }
84
85 fn reclaim_rent(&self, price_update: &Pubkey) -> TransactionBuilder<C> {
86 self.transaction()
87 .anchor_args(instruction::ReclaimRent {})
88 .anchor_accounts(accounts::ReclaimRent {
89 payer: self.payer(),
90 price_update_account: *price_update,
91 })
92 .compute_budget(ComputeBudget::default().with_limit(RECLAIM_RENT_COMPUTE_BUDGET))
93 }
94}