light_sdk/cpi/v2/
invoke.rs1use light_compressed_account::instruction_data::{
2 compressed_proof::ValidityProof, with_account_info::InstructionDataInvokeCpiWithAccountInfo,
3};
4use light_sdk_types::CpiSigner;
5
6#[cfg(feature = "cpi-context")]
7use super::lowlevel::CompressedCpiContext;
8use super::lowlevel::{to_account_metas, InAccount, InstructionDataInvokeCpiWithReadOnly};
9#[cfg(feature = "poseidon")]
10use crate::{account::poseidon::LightAccount as LightAccountPoseidon, DataHasher};
11use crate::{
12 account::LightAccount,
13 cpi::{account::CpiAccountsTrait, instruction::LightCpiInstruction, v2::CpiAccounts},
14 error::LightSdkError,
15 instruction::account_info::CompressedAccountInfoTrait,
16 AccountInfo, AccountMeta, AnchorDeserialize, AnchorSerialize, LightDiscriminator, ProgramError,
17};
18
19impl<'info> CpiAccountsTrait<'info> for CpiAccounts<'_, 'info> {
20 fn to_account_infos(&self) -> Vec<AccountInfo<'info>> {
21 self.to_account_infos()
22 }
23
24 fn to_account_metas(&self) -> Result<Vec<AccountMeta>, ProgramError> {
25 to_account_metas(self).map_err(ProgramError::from)
26 }
27
28 fn get_mode(&self) -> Option<u8> {
29 Some(1) }
31}
32
33impl LightCpiInstruction for InstructionDataInvokeCpiWithReadOnly {
34 fn new_cpi(cpi_signer: CpiSigner, proof: ValidityProof) -> Self {
35 Self {
36 bump: cpi_signer.bump,
37 invoking_program_id: cpi_signer.program_id.into(),
38 proof: proof.into(),
39 mode: 1,
40 ..Default::default()
41 }
42 }
43
44 fn with_light_account<A>(mut self, account: LightAccount<A>) -> Result<Self, ProgramError>
45 where
46 A: AnchorSerialize + AnchorDeserialize + LightDiscriminator + Default,
47 {
48 if account.read_only_account_hash.is_some() {
50 let read_only_account = account.to_packed_read_only_account()?;
51 self.read_only_accounts.push(read_only_account);
52 return Ok(self);
53 }
54
55 let account_info = account.to_account_info()?;
57
58 if let Some(input_account) = account_info
60 .input_compressed_account(self.invoking_program_id.to_bytes().into())
61 .map_err(LightSdkError::from)
62 .map_err(ProgramError::from)?
63 {
64 let in_account = InAccount {
66 discriminator: input_account
67 .compressed_account
68 .data
69 .as_ref()
70 .map(|d| d.discriminator)
71 .unwrap_or_default(),
72 data_hash: input_account
73 .compressed_account
74 .data
75 .as_ref()
76 .map(|d| d.data_hash)
77 .unwrap_or_default(),
78 merkle_context: input_account.merkle_context,
79 root_index: input_account.root_index,
80 lamports: input_account.compressed_account.lamports,
81 address: input_account.compressed_account.address,
82 };
83 self.input_compressed_accounts.push(in_account);
84 }
85
86 if let Some(output_account) = account_info
88 .output_compressed_account(self.invoking_program_id.to_bytes().into())
89 .map_err(LightSdkError::from)
90 .map_err(ProgramError::from)?
91 {
92 self.output_compressed_accounts.push(output_account);
93 }
94
95 Ok(self)
96 }
97
98 #[cfg(feature = "poseidon")]
99 fn with_light_account_poseidon<A>(
100 mut self,
101 account: LightAccountPoseidon<A>,
102 ) -> Result<Self, ProgramError>
103 where
104 A: AnchorSerialize + AnchorDeserialize + DataHasher + LightDiscriminator + Default,
105 {
106 if account.read_only_account_hash.is_some() {
108 let read_only_account = account.to_packed_read_only_account()?;
109 self.read_only_accounts.push(read_only_account);
110 return Ok(self);
111 }
112
113 let account_info = account.to_account_info()?;
115
116 if let Some(input_account) = account_info
118 .input_compressed_account(self.invoking_program_id.to_bytes().into())
119 .map_err(LightSdkError::from)
120 .map_err(ProgramError::from)?
121 {
122 let in_account = InAccount {
124 discriminator: input_account
125 .compressed_account
126 .data
127 .as_ref()
128 .map(|d| d.discriminator)
129 .unwrap_or_default(),
130 data_hash: input_account
131 .compressed_account
132 .data
133 .as_ref()
134 .map(|d| d.data_hash)
135 .unwrap_or_default(),
136 merkle_context: input_account.merkle_context,
137 root_index: input_account.root_index,
138 lamports: input_account.compressed_account.lamports,
139 address: input_account.compressed_account.address,
140 };
141 self.input_compressed_accounts.push(in_account);
142 }
143
144 if let Some(output_account) = account_info
146 .output_compressed_account(self.invoking_program_id.to_bytes().into())
147 .map_err(LightSdkError::from)
148 .map_err(ProgramError::from)?
149 {
150 self.output_compressed_accounts.push(output_account);
151 }
152
153 Ok(self)
154 }
155
156 #[cfg(feature = "cpi-context")]
157 fn write_to_cpi_context_first(self) -> Self {
158 self.write_to_cpi_context_first()
159 }
160
161 #[cfg(feature = "cpi-context")]
162 fn write_to_cpi_context_set(self) -> Self {
163 self.write_to_cpi_context_set()
164 }
165
166 #[cfg(feature = "cpi-context")]
167 fn execute_with_cpi_context(self) -> Self {
168 self.execute_with_cpi_context()
169 }
170
171 fn get_mode(&self) -> u8 {
172 self.mode
173 }
174
175 #[cfg(feature = "cpi-context")]
176 fn get_with_cpi_context(&self) -> bool {
177 self.with_cpi_context
178 }
179
180 #[cfg(feature = "cpi-context")]
181 fn get_cpi_context(&self) -> &CompressedCpiContext {
182 &self.cpi_context
183 }
184
185 fn get_bump(&self) -> u8 {
186 self.bump
187 }
188
189 #[cfg(feature = "cpi-context")]
190 fn has_read_only_accounts(&self) -> bool {
191 !self.read_only_accounts.is_empty()
192 }
193}
194
195impl LightCpiInstruction for InstructionDataInvokeCpiWithAccountInfo {
196 fn new_cpi(cpi_signer: CpiSigner, proof: ValidityProof) -> Self {
197 Self {
198 bump: cpi_signer.bump,
199 invoking_program_id: cpi_signer.program_id.into(),
200 proof: proof.into(),
201 mode: 1,
202 ..Default::default()
203 }
204 }
205
206 fn with_light_account<A>(mut self, account: LightAccount<A>) -> Result<Self, ProgramError>
207 where
208 A: AnchorSerialize + AnchorDeserialize + LightDiscriminator + Default,
209 {
210 if account.read_only_account_hash.is_some() {
212 let read_only_account = account.to_packed_read_only_account()?;
213 self.read_only_accounts.push(read_only_account);
214 return Ok(self);
215 }
216
217 let account_info = account.to_account_info()?;
219 self.account_infos.push(account_info);
220 Ok(self)
221 }
222
223 #[cfg(feature = "poseidon")]
224 fn with_light_account_poseidon<A>(
225 mut self,
226 account: crate::account::poseidon::LightAccount<A>,
227 ) -> Result<Self, ProgramError>
228 where
229 A: AnchorSerialize + AnchorDeserialize + LightDiscriminator + DataHasher + Default,
230 {
231 if account.read_only_account_hash.is_some() {
233 let read_only_account = account.to_packed_read_only_account()?;
234 self.read_only_accounts.push(read_only_account);
235 return Ok(self);
236 }
237
238 let account_info = account.to_account_info()?;
240 self.account_infos.push(account_info);
241 Ok(self)
242 }
243
244 #[cfg(feature = "cpi-context")]
245 fn write_to_cpi_context_first(self) -> Self {
246 self.write_to_cpi_context_first()
247 }
248
249 #[cfg(feature = "cpi-context")]
250 fn write_to_cpi_context_set(self) -> Self {
251 self.write_to_cpi_context_set()
252 }
253
254 #[cfg(feature = "cpi-context")]
255 fn execute_with_cpi_context(self) -> Self {
256 self.execute_with_cpi_context()
257 }
258
259 fn get_mode(&self) -> u8 {
260 self.mode
261 }
262
263 #[cfg(feature = "cpi-context")]
264 fn get_with_cpi_context(&self) -> bool {
265 self.with_cpi_context
266 }
267
268 #[cfg(feature = "cpi-context")]
269 fn get_cpi_context(&self) -> &CompressedCpiContext {
270 &self.cpi_context
271 }
272
273 fn get_bump(&self) -> u8 {
274 self.bump
275 }
276
277 #[cfg(feature = "cpi-context")]
278 fn has_read_only_accounts(&self) -> bool {
279 !self.read_only_accounts.is_empty()
280 }
281}