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