switchboard_solana/attestation_program/instructions/
routine_init.rs

1use crate::prelude::*;
2
3#[derive(Accounts)]
4#[instruction(params:FunctionRoutineInitParams)]
5pub struct FunctionRoutineInit<'info> {
6    #[account(
7        mut,
8        signer,
9        owner = system_program.key(),
10        constraint = function.data_len() == 0 && function.lamports() == 0,
11    )]
12    pub routine: AccountInfo<'info>,
13
14    /// CHECK:
15    pub authority: AccountInfo<'info>,
16
17    #[account(mut)]
18    pub function: AccountInfo<'info>,
19
20    #[account(signer)]
21    pub function_authority: Option<AccountInfo<'info>>,
22
23    /// CHECK: handle this manually because the PDA seed can vary
24    #[account(mut)]
25    pub escrow_wallet: AccountInfo<'info>,
26
27    #[account(signer)]
28    pub escrow_wallet_authority: Option<AccountInfo<'info>>,
29
30    /// CHECK: handle this manually because the PDA seed can vary
31    #[account(mut)]
32    pub escrow_token_wallet: AccountInfo<'info>,
33
34    #[account(address = anchor_spl::token::spl_token::native_mint::ID)]
35    pub mint: AccountInfo<'info>,
36
37    pub attestation_queue: AccountInfo<'info>,
38
39    #[account(mut, signer)]
40    pub payer: AccountInfo<'info>,
41
42    #[account(address = solana_program::system_program::ID)]
43    pub system_program: AccountInfo<'info>,
44    #[account(address = anchor_spl::token::ID)]
45    pub token_program: AccountInfo<'info>,
46    #[account(address = anchor_spl::associated_token::ID)]
47    pub associated_token_program: AccountInfo<'info>,
48}
49
50#[derive(Clone, AnchorSerialize, AnchorDeserialize)]
51pub struct FunctionRoutineInitParams {
52    // Metadata
53    pub name: Option<Vec<u8>>,
54    pub metadata: Option<Vec<u8>>,
55
56    // Fees
57    pub bounty: Option<u64>,
58
59    // Execution
60    pub schedule: Vec<u8>,
61    pub max_container_params_len: Option<u32>,
62    pub container_params: Vec<u8>,
63}
64
65impl InstructionData for FunctionRoutineInitParams {}
66
67impl Discriminator for FunctionRoutineInitParams {
68    const DISCRIMINATOR: [u8; 8] = [70, 25, 243, 23, 253, 78, 27, 169];
69}
70
71impl Discriminator for FunctionRoutineInit<'_> {
72    const DISCRIMINATOR: [u8; 8] = [70, 25, 243, 23, 253, 78, 27, 169];
73}
74
75impl<'info> FunctionRoutineInit<'info> {
76    pub fn get_instruction(
77        &self,
78        program_id: Pubkey,
79        params: &FunctionRoutineInitParams,
80    ) -> anchor_lang::Result<Instruction> {
81        let accounts = self.to_account_metas(None);
82
83        let mut data: Vec<u8> = FunctionRoutineInit::discriminator().try_to_vec()?;
84        data.append(&mut params.try_to_vec()?);
85
86        let instruction = Instruction::new_with_bytes(program_id, &data, accounts);
87        Ok(instruction)
88    }
89
90    pub fn invoke(
91        &self,
92        program: AccountInfo<'info>,
93        params: &FunctionRoutineInitParams,
94    ) -> ProgramResult {
95        let instruction = self.get_instruction(*program.key, params)?;
96        let account_infos = self.to_account_infos();
97
98        invoke(&instruction, &account_infos[..])
99    }
100
101    pub fn invoke_signed(
102        &self,
103        program: AccountInfo<'info>,
104        params: &FunctionRoutineInitParams,
105        signer_seeds: &[&[&[u8]]],
106    ) -> ProgramResult {
107        let instruction = self.get_instruction(*program.key, params)?;
108        let account_infos = self.to_account_infos();
109
110        invoke_signed(&instruction, &account_infos[..], signer_seeds)
111    }
112
113    fn to_account_infos(&self) -> Vec<AccountInfo<'info>> {
114        let mut account_infos = Vec::new();
115        account_infos.extend(self.routine.to_account_infos());
116        account_infos.extend(self.authority.to_account_infos());
117        account_infos.extend(self.function.to_account_infos());
118        account_infos.extend(self.function_authority.to_account_infos());
119        account_infos.extend(self.escrow_wallet.to_account_infos());
120        account_infos.extend(self.escrow_wallet_authority.to_account_infos());
121        account_infos.extend(self.escrow_token_wallet.to_account_infos());
122        account_infos.extend(self.mint.to_account_infos());
123        account_infos.extend(self.attestation_queue.to_account_infos());
124        account_infos.extend(self.payer.to_account_infos());
125        account_infos.extend(self.system_program.to_account_infos());
126        account_infos.extend(self.token_program.to_account_infos());
127        account_infos.extend(self.associated_token_program.to_account_infos());
128        account_infos
129    }
130
131    #[allow(unused_variables)]
132    fn to_account_metas(&self, is_signer: Option<bool>) -> Vec<AccountMeta> {
133        let mut account_metas = Vec::new();
134        account_metas.extend(self.routine.to_account_metas(None));
135        account_metas.extend(self.authority.to_account_metas(None));
136        account_metas.extend(self.function.to_account_metas(None));
137        if let Some(function_authority) = &self.function_authority {
138            account_metas.extend(function_authority.to_account_metas(None));
139        } else {
140            account_metas.push(AccountMeta::new_readonly(
141                SWITCHBOARD_ATTESTATION_PROGRAM_ID,
142                false,
143            ));
144        }
145        account_metas.extend(self.escrow_wallet.to_account_metas(None));
146        if let Some(escrow_wallet_authority) = &self.escrow_wallet_authority {
147            account_metas.extend(escrow_wallet_authority.to_account_metas(None));
148        } else {
149            account_metas.push(AccountMeta::new_readonly(
150                SWITCHBOARD_ATTESTATION_PROGRAM_ID,
151                false,
152            ));
153        }
154        account_metas.extend(self.escrow_token_wallet.to_account_metas(None));
155        account_metas.extend(self.mint.to_account_metas(None));
156        account_metas.extend(self.attestation_queue.to_account_metas(None));
157        account_metas.extend(self.payer.to_account_metas(None));
158        account_metas.extend(self.system_program.to_account_metas(None));
159        account_metas.extend(self.token_program.to_account_metas(None));
160        account_metas.extend(self.associated_token_program.to_account_metas(None));
161
162        account_metas
163    }
164}