gmsol/pyth/pull_oracle/receiver/
mod.rs

1use 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
14/// Treasury account seed.
15pub const TREASURY_SEED: &[u8] = b"treasury";
16
17/// Config account seed.
18pub const CONFIG_SEED: &[u8] = b"config";
19
20/// `post_price_update` compute budget.
21pub const POST_PRICE_UPDATE_COMPUTE_BUDGET: u32 = 80_000;
22
23/// `reclaim_rent` compute budget.
24pub const RECLAIM_RENT_COMPUTE_BUDGET: u32 = 4_000;
25
26/// Find PDA for treasury account.
27pub 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
34/// Find PDA for config account.
35pub fn find_config_pda() -> (Pubkey, u8) {
36    Pubkey::find_program_address(&[CONFIG_SEED], &pyth_solana_receiver_sdk::ID)
37}
38
39/// Pyth Receiver Ops.
40pub trait PythReceiverOps<C> {
41    /// Post price update.
42    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    /// Reclaim rent.
50    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}