Skip to main content

light_compressed_account/instruction_data/
invoke_cpi.rs

1use light_zero_copy::ZeroCopyMut;
2
3use super::{
4    cpi_context::CompressedCpiContext,
5    data::{NewAddressParamsPacked, OutputCompressedAccountWithPackedContext},
6};
7use crate::{
8    compressed_account::PackedCompressedAccountWithMerkleContext,
9    discriminators::DISCRIMINATOR_INVOKE_CPI,
10    instruction_data::{compressed_proof::CompressedProof, traits::LightInstructionData},
11    InstructionDiscriminator, Vec,
12};
13
14#[repr(C)]
15#[cfg_attr(
16    all(feature = "std", feature = "anchor"),
17    derive(anchor_lang::AnchorDeserialize, anchor_lang::AnchorSerialize)
18)]
19#[cfg_attr(
20    not(feature = "anchor"),
21    derive(borsh::BorshDeserialize, borsh::BorshSerialize)
22)]
23#[derive(Debug, PartialEq, Default, Clone, ZeroCopyMut)]
24pub struct InstructionDataInvokeCpi {
25    pub proof: Option<CompressedProof>,
26    pub new_address_params: Vec<NewAddressParamsPacked>,
27    pub input_compressed_accounts_with_merkle_context:
28        Vec<PackedCompressedAccountWithMerkleContext>,
29    pub output_compressed_accounts: Vec<OutputCompressedAccountWithPackedContext>,
30    pub relay_fee: Option<u64>,
31    pub compress_or_decompress_lamports: Option<u64>,
32    pub is_compress: bool,
33    pub cpi_context: Option<CompressedCpiContext>,
34}
35
36impl LightInstructionData for InstructionDataInvokeCpi {
37    #[cfg(feature = "alloc")]
38    fn data(&self) -> Result<Vec<u8>, crate::CompressedAccountError> {
39        #[cfg(feature = "anchor")]
40        use anchor_lang::AnchorSerialize as BorshSerialize;
41        #[cfg(not(feature = "anchor"))]
42        use borsh::BorshSerialize;
43
44        let inputs = self
45            .try_to_vec()
46            .map_err(|_| crate::CompressedAccountError::InvalidArgument)?;
47        let mut data = Vec::with_capacity(12 + inputs.len());
48        data.extend_from_slice(self.discriminator());
49        data.extend_from_slice(&(inputs.len() as u32).to_le_bytes());
50        data.extend_from_slice(inputs.as_slice());
51        Ok(data)
52    }
53}
54
55impl InstructionDataInvokeCpi {
56    pub fn new(proof: Option<CompressedProof>) -> Self {
57        Self {
58            proof,
59            ..Default::default()
60        }
61    }
62
63    #[must_use = "with_new_addresses returns a new value"]
64    pub fn with_new_addresses(mut self, new_address_params: &[NewAddressParamsPacked]) -> Self {
65        if !new_address_params.is_empty() {
66            self.new_address_params
67                .extend_from_slice(new_address_params);
68        }
69        self
70    }
71
72    #[must_use = "with_input_compressed_accounts_with_merkle_context returns a new value"]
73    pub fn with_input_compressed_accounts_with_merkle_context(
74        mut self,
75        input_compressed_accounts_with_merkle_context: &[PackedCompressedAccountWithMerkleContext],
76    ) -> Self {
77        if !input_compressed_accounts_with_merkle_context.is_empty() {
78            self.input_compressed_accounts_with_merkle_context
79                .extend_from_slice(input_compressed_accounts_with_merkle_context);
80        }
81        self
82    }
83
84    #[must_use = "with_output_compressed_accounts returns a new value"]
85    pub fn with_output_compressed_accounts(
86        mut self,
87        output_compressed_accounts: &[OutputCompressedAccountWithPackedContext],
88    ) -> Self {
89        if !output_compressed_accounts.is_empty() {
90            self.output_compressed_accounts
91                .extend_from_slice(output_compressed_accounts);
92        }
93        self
94    }
95
96    #[must_use = "compress_lamports returns a new value"]
97    pub fn compress_lamports(mut self, lamports: u64) -> Self {
98        self.compress_or_decompress_lamports = Some(lamports);
99        self.is_compress = true;
100        self
101    }
102
103    #[must_use = "decompress_lamports returns a new value"]
104    pub fn decompress_lamports(mut self, lamports: u64) -> Self {
105        self.compress_or_decompress_lamports = Some(lamports);
106        self.is_compress = false;
107        self
108    }
109
110    #[must_use = "write_to_cpi_context_set returns a new value"]
111    pub fn write_to_cpi_context_set(mut self) -> Self {
112        self.cpi_context = Some(CompressedCpiContext::set());
113        self
114    }
115
116    #[must_use = "write_to_cpi_context_first returns a new value"]
117    pub fn write_to_cpi_context_first(mut self) -> Self {
118        self.cpi_context = Some(CompressedCpiContext::first());
119        self
120    }
121
122    #[must_use = "with_cpi_context returns a new value"]
123    pub fn with_cpi_context(mut self, cpi_context: CompressedCpiContext) -> Self {
124        self.cpi_context = Some(cpi_context);
125        self
126    }
127}
128
129impl InstructionDiscriminator for InstructionDataInvokeCpi {
130    fn discriminator(&self) -> &'static [u8] {
131        &DISCRIMINATOR_INVOKE_CPI
132    }
133}