gmsol/pyth/pull_oracle/wormhole/
mod.rs1use std::{future::Future, ops::Deref, sync::Arc};
2
3use anchor_client::{
4 solana_sdk::{pubkey::Pubkey, signature::Keypair, signer::Signer, system_instruction},
5 ClientError,
6};
7use gmsol_solana_utils::{
8 compute_budget::ComputeBudget, program::Program, transaction_builder::TransactionBuilder,
9};
10
11mod accounts;
12mod instruction;
13
14pub const WORMHOLE_PROGRAM_ID: Pubkey = Pubkey::new_from_array([
16 241, 11, 180, 229, 13, 86, 253, 161, 61, 254, 31, 50, 155, 141, 57, 61, 210, 74, 1, 69, 145,
17 225, 131, 22, 151, 148, 13, 124, 52, 163, 141, 221,
18]);
19
20pub const VAA_START: u64 = 46;
22
23pub const GUARDIAN_SET_SEED: &[u8] = b"GuardianSet";
25
26pub const INIT_ENCODED_VAA_COMPUTE_BUDGET: u32 = 3_000;
28
29pub const WRITE_ENCODED_VAA_COMPUTE_BUDGET: u32 = 3_000;
31
32pub const VERIFY_ENCODED_VAA_V1_COMPUTE_BUDGET: u32 = 350_000;
34
35pub const CLOSE_ENCODED_VAA_COMPUTE_BUDGET: u32 = 3_000;
37
38pub fn find_guardian_set_pda(guardian_set_index: i32) -> (Pubkey, u8) {
40 Pubkey::find_program_address(
41 &[GUARDIAN_SET_SEED, &guardian_set_index.to_be_bytes()],
42 &WORMHOLE_PROGRAM_ID,
43 )
44}
45
46pub trait WormholeOps<C> {
48 fn create_encoded_vaa(
50 &self,
51 encoded_vaa: Keypair,
52 vaa_buffer_len: u64,
53 ) -> impl Future<Output = crate::Result<TransactionBuilder<C, Pubkey>>>;
54
55 fn write_encoded_vaa(
57 &self,
58 draft_vaa: &Pubkey,
59 index: u32,
60 data: &[u8],
61 ) -> TransactionBuilder<C>;
62
63 fn verify_encoded_vaa_v1(
65 &self,
66 draft_vaa: &Pubkey,
67 guardian_set_index: i32,
68 ) -> TransactionBuilder<C>;
69
70 fn close_encoded_vaa(&self, encoded_vaa: &Pubkey) -> TransactionBuilder<C>;
72}
73
74impl<S, C> WormholeOps<C> for Program<C>
75where
76 C: Deref<Target = S> + Clone,
77 S: Signer,
78{
79 async fn create_encoded_vaa(
80 &self,
81 encoded_vaa: Keypair,
82 vaa_buffer_len: u64,
83 ) -> crate::Result<TransactionBuilder<C, Pubkey>> {
84 let space = vaa_buffer_len + VAA_START;
85 let lamports = self
86 .rpc()
87 .get_minimum_balance_for_rent_exemption(space as usize)
88 .await
89 .map_err(ClientError::from)?;
90 let request = self
91 .transaction()
92 .pre_instruction(system_instruction::create_account(
93 &self.payer(),
94 &encoded_vaa.pubkey(),
95 lamports,
96 space,
97 self.id(),
98 ))
99 .anchor_args(instruction::InitEncodedVaa {})
100 .anchor_accounts(accounts::InitEncodedVaa {
101 write_authority: self.payer(),
102 encoded_vaa: encoded_vaa.pubkey(),
103 })
104 .output(encoded_vaa.pubkey())
105 .owned_signer(Arc::new(encoded_vaa))
106 .compute_budget(ComputeBudget::default().with_limit(INIT_ENCODED_VAA_COMPUTE_BUDGET));
107 Ok(request)
108 }
109
110 fn write_encoded_vaa(
111 &self,
112 draft_vaa: &Pubkey,
113 index: u32,
114 data: &[u8],
115 ) -> TransactionBuilder<C> {
116 self.transaction()
117 .anchor_args(instruction::WriteEncodedVaa {
118 index,
119 data: data.to_owned(),
120 })
121 .anchor_accounts(accounts::WriteEncodedVaa {
122 write_authority: self.payer(),
123 draft_vaa: *draft_vaa,
124 })
125 .compute_budget(ComputeBudget::default().with_limit(WRITE_ENCODED_VAA_COMPUTE_BUDGET))
126 }
127
128 fn verify_encoded_vaa_v1(
129 &self,
130 draft_vaa: &Pubkey,
131 guardian_set_index: i32,
132 ) -> TransactionBuilder<C> {
133 self.transaction()
134 .anchor_args(instruction::VerifyEncodedVaaV1 {})
135 .anchor_accounts(accounts::VerifyEncodedVaaV1 {
136 write_authority: self.payer(),
137 draft_vaa: *draft_vaa,
138 guardian_set: find_guardian_set_pda(guardian_set_index).0,
139 })
140 .compute_budget(
141 ComputeBudget::default().with_limit(VERIFY_ENCODED_VAA_V1_COMPUTE_BUDGET),
142 )
143 }
144
145 fn close_encoded_vaa(&self, encoded_vaa: &Pubkey) -> TransactionBuilder<C> {
146 self.transaction()
147 .anchor_args(instruction::CloseEncodedVaa {})
148 .anchor_accounts(accounts::CloseEncodedVaa {
149 write_authority: self.payer(),
150 encoded_vaa: *encoded_vaa,
151 })
152 .compute_budget(ComputeBudget::default().with_limit(CLOSE_ENCODED_VAA_COMPUTE_BUDGET))
153 }
154}