switchboard_solana/attestation_program/instructions/
request_init.rs

1use crate::prelude::*;
2
3#[derive(Accounts)]
4#[instruction(params:FunctionRequestInitParams)]
5pub struct FunctionRequestInit<'info> {
6    #[account(
7        mut,
8        signer,
9        owner = system_program.key(),
10        constraint = request.data_len() == 0 && request.lamports() == 0,
11    )]
12    pub request: AccountInfo<'info>,
13
14    /// CHECK: the authority of the request
15    pub authority: AccountInfo<'info>,
16
17    #[account(mut)]
18    pub function: AccountInfo<'info>,
19
20    /// CHECK: function authority required to permit new requests
21    #[account(signer)]
22    pub function_authority: Option<AccountInfo<'info>>,
23
24    #[account(
25        mut,
26        owner = system_program.key(),
27        constraint = request.data_len() == 0 && request.lamports() == 0,
28    )]
29    pub escrow: AccountInfo<'info>,
30
31    #[account(address = anchor_spl::token::spl_token::native_mint::ID)]
32    pub mint: AccountInfo<'info>,
33
34    pub state: AccountInfo<'info>,
35    pub attestation_queue: AccountInfo<'info>,
36
37    #[account(mut, signer)]
38    pub payer: AccountInfo<'info>,
39    #[account(address = solana_program::system_program::ID)]
40    pub system_program: AccountInfo<'info>,
41    #[account(address = anchor_spl::token::ID)]
42    pub token_program: AccountInfo<'info>,
43    #[account(address = anchor_spl::associated_token::ID)]
44    pub associated_token_program: AccountInfo<'info>,
45}
46
47#[derive(Clone, AnchorSerialize, AnchorDeserialize)]
48pub struct FunctionRequestInitParams {
49    pub max_container_params_len: Option<u32>,
50    pub container_params: Vec<u8>,
51    pub garbage_collection_slot: Option<u64>,
52}
53
54impl InstructionData for FunctionRequestInitParams {}
55
56impl Discriminator for FunctionRequestInitParams {
57    const DISCRIMINATOR: [u8; 8] = [118, 8, 251, 119, 88, 174, 81, 239];
58}
59
60impl Discriminator for FunctionRequestInit<'_> {
61    const DISCRIMINATOR: [u8; 8] = [118, 8, 251, 119, 88, 174, 81, 239];
62}
63
64impl<'info> FunctionRequestInit<'info> {
65    pub fn get_instruction(
66        &self,
67        program_id: Pubkey,
68        params: FunctionRequestInitParams,
69    ) -> anchor_lang::Result<Instruction> {
70        let accounts = self.to_account_metas(None);
71
72        let mut data: Vec<u8> = FunctionRequestInit::discriminator().try_to_vec()?;
73        let mut param_vec: Vec<u8> = params.try_to_vec()?;
74        data.append(&mut param_vec);
75
76        let instruction = Instruction::new_with_bytes(program_id, &data, accounts);
77        Ok(instruction)
78    }
79
80    /// Invokes the instruction using a signed authority.
81    ///
82    /// # Arguments
83    ///
84    /// * `program`: The Switchboard Attestation program AccountInfo.
85    ///
86    /// * `max_container_params_len`: The maximum length of the vector containing the container parameters.
87    ///   - Default: 256 bytes.
88    ///   - Example: `Some(512)`.
89    ///
90    /// * `container_params`: The parameters for the container.
91    ///   - Default: Empty vector.
92    ///   - Example: `Some(request_params.into_bytes())`.
93    ///
94    /// * `garbage_collection_slot`: The slot when the request can be closed by anyone and is considered expired.
95    ///   - Default: None, meaning only the authority can close the request.
96    ///
97    /// # Returns
98    ///
99    /// * `ProgramResult`: Indicates the result of the instruction execution.
100    pub fn invoke(
101        &self,
102        program: AccountInfo<'info>,
103        max_container_params_len: Option<u32>,
104        container_params: Option<Vec<u8>>,
105        garbage_collection_slot: Option<u64>,
106    ) -> ProgramResult {
107        let instruction = self.get_instruction(
108            *program.key,
109            FunctionRequestInitParams {
110                max_container_params_len,
111                container_params: container_params.unwrap_or_default(),
112                garbage_collection_slot,
113            },
114        )?;
115        let account_infos = self.to_account_infos();
116
117        invoke(&instruction, &account_infos[..])
118    }
119
120    /// Invokes the instruction using a signed authority.
121    ///
122    /// # Arguments
123    ///
124    /// * `program`: The Switchboard Attestation program AccountInfo.
125    ///
126    /// * `max_container_params_len`: The maximum length of the vector containing the container parameters.
127    ///   - Default: 256 bytes.
128    ///   - Example: `Some(512)`.
129    ///
130    /// * `container_params`: The parameters for the container.
131    ///   - Default: Empty vector.
132    ///   - Example: `Some(request_params.into_bytes())`.
133    ///
134    /// * `garbage_collection_slot`: The slot when the request can be closed by anyone and is considered expired.
135    ///   - Default: None, meaning only the authority can close the request.
136    ///
137    /// * `signer_seeds`: Seeds used for signing.
138    ///
139    /// # Returns
140    ///
141    /// * `ProgramResult`: Indicates the result of the instruction execution.
142    pub fn invoke_signed(
143        &self,
144        program: AccountInfo<'info>,
145        max_container_params_len: Option<u32>,
146        container_params: Option<Vec<u8>>,
147        garbage_collection_slot: Option<u64>,
148        signer_seeds: &[&[&[u8]]],
149    ) -> ProgramResult {
150        let instruction = self.get_instruction(
151            *program.key,
152            FunctionRequestInitParams {
153                max_container_params_len,
154                container_params: container_params.unwrap_or_default(),
155                garbage_collection_slot,
156            },
157        )?;
158        let account_infos = self.to_account_infos();
159
160        invoke_signed(&instruction, &account_infos[..], signer_seeds)
161    }
162
163    fn to_account_infos(&self) -> Vec<AccountInfo<'info>> {
164        let mut account_infos = Vec::new();
165        account_infos.extend(self.request.to_account_infos());
166        account_infos.extend(self.authority.to_account_infos());
167        account_infos.extend(self.function.to_account_infos());
168        account_infos.extend(self.function_authority.to_account_infos());
169        account_infos.extend(self.escrow.to_account_infos());
170        account_infos.extend(self.mint.to_account_infos());
171        account_infos.extend(self.state.to_account_infos());
172        account_infos.extend(self.attestation_queue.to_account_infos());
173        account_infos.extend(self.payer.to_account_infos());
174        account_infos.extend(self.system_program.to_account_infos());
175        account_infos.extend(self.token_program.to_account_infos());
176        account_infos.extend(self.associated_token_program.to_account_infos());
177        account_infos
178    }
179
180    #[allow(unused_variables)]
181    fn to_account_metas(&self, is_signer: Option<bool>) -> Vec<AccountMeta> {
182        let mut account_metas = Vec::new();
183        account_metas.extend(self.request.to_account_metas(Some(true)));
184        account_metas.extend(self.authority.to_account_metas(None));
185        account_metas.extend(self.function.to_account_metas(None));
186        if let Some(function_authority) = &self.function_authority {
187            account_metas.extend(function_authority.to_account_metas(Some(true)));
188        } else {
189            account_metas.push(AccountMeta::new_readonly(
190                SWITCHBOARD_ATTESTATION_PROGRAM_ID,
191                false,
192            ));
193        }
194        account_metas.extend(self.escrow.to_account_metas(None));
195        account_metas.extend(self.mint.to_account_metas(None));
196        account_metas.extend(self.state.to_account_metas(None));
197        account_metas.extend(self.attestation_queue.to_account_metas(None));
198        account_metas.extend(self.payer.to_account_metas(None));
199        account_metas.extend(self.system_program.to_account_metas(None));
200        account_metas.extend(self.token_program.to_account_metas(None));
201        account_metas.extend(self.associated_token_program.to_account_metas(None));
202        account_metas
203    }
204}