light_token_interface/instructions/mint_action/
instruction_data.rs1use light_compressed_account::{instruction_data::compressed_proof::CompressedProof, Pubkey};
2use light_compressible::compression_info::CompressionInfo;
3use light_zero_copy::ZeroCopy;
4
5use super::{
6 CompressAndCloseMintAction, CpiContext, DecompressMintAction, MintToAction,
7 MintToCompressedAction, RemoveMetadataKeyAction, UpdateAuthority,
8 UpdateMetadataAuthorityAction, UpdateMetadataFieldAction,
9};
10use crate::{
11 instructions::extensions::{ExtensionInstructionData, ZExtensionInstructionData},
12 state::{AdditionalMetadata, BaseMint, ExtensionStruct, Mint, MintMetadata, TokenMetadata},
13 AnchorDeserialize, AnchorSerialize, TokenError,
14};
15
16#[repr(C)]
17#[derive(Debug, Clone, AnchorSerialize, AnchorDeserialize, ZeroCopy)]
18pub enum Action {
19 MintToCompressed(MintToCompressedAction),
21 UpdateMintAuthority(UpdateAuthority),
23 UpdateFreezeAuthority(UpdateAuthority),
25 MintTo(MintToAction),
28 UpdateMetadataField(UpdateMetadataFieldAction),
29 UpdateMetadataAuthority(UpdateMetadataAuthorityAction),
30 RemoveMetadataKey(RemoveMetadataKeyAction),
31 DecompressMint(DecompressMintAction),
34 CompressAndCloseMint(CompressAndCloseMintAction),
37}
38
39#[repr(C)]
40#[derive(Debug, Clone, AnchorSerialize, AnchorDeserialize, ZeroCopy)]
41pub struct MintActionCompressedInstructionData {
42 pub leaf_index: u32,
44 pub prove_by_index: bool,
46 pub root_index: u16,
50 pub max_top_up: u16,
52 pub create_mint: Option<CreateMint>,
53 pub actions: Vec<Action>,
54 pub proof: Option<CompressedProof>,
55 pub cpi_context: Option<CpiContext>,
56 pub mint: Option<MintInstructionData>,
57}
58
59#[repr(C)]
60#[derive(Debug, Clone, AnchorSerialize, Default, AnchorDeserialize, ZeroCopy)]
61pub struct CreateMint {
62 pub read_only_address_trees: [u8; 4],
65 pub read_only_address_tree_root_indices: [u16; 4],
68}
69
70#[repr(C)]
71#[derive(Debug, Clone, AnchorSerialize, AnchorDeserialize, ZeroCopy, PartialEq)]
72pub struct MintWithContext {
73 pub leaf_index: u32,
74 pub prove_by_index: bool,
75 pub root_index: u16,
76 pub address: [u8; 32],
77 pub mint: Option<MintInstructionData>,
78}
79
80#[repr(C)]
81#[derive(Debug, PartialEq, Eq, Clone, AnchorSerialize, AnchorDeserialize, ZeroCopy)]
82pub struct MintInstructionData {
83 pub supply: u64,
85 pub decimals: u8,
87 pub metadata: MintMetadata,
89 pub mint_authority: Option<Pubkey>,
94 pub freeze_authority: Option<Pubkey>,
96 pub extensions: Option<Vec<ExtensionInstructionData>>,
98}
99
100impl TryFrom<Mint> for MintInstructionData {
101 type Error = TokenError;
102
103 fn try_from(mint: Mint) -> Result<Self, Self::Error> {
104 let extensions = match mint.extensions {
105 Some(exts) if !exts.is_empty() => {
106 let mut extension_list = Vec::with_capacity(exts.len());
107 for ext in exts {
108 match ext {
109 ExtensionStruct::TokenMetadata(token_metadata) => {
110 extension_list.push(ExtensionInstructionData::TokenMetadata(
111 crate::instructions::extensions::token_metadata::TokenMetadataInstructionData {
112 update_authority: if token_metadata.update_authority == [0u8;32] {None}else {Some(token_metadata.update_authority)},
113 name: token_metadata.name,
114 symbol: token_metadata.symbol,
115 uri: token_metadata.uri,
116 additional_metadata: Some(token_metadata.additional_metadata),
117 },
118 ));
119 }
120 _ => {
121 return Err(TokenError::UnsupportedExtension);
122 }
123 }
124 }
125 Some(extension_list)
126 }
127 _ => None,
128 };
129
130 Ok(Self {
131 supply: mint.base.supply,
132 decimals: mint.base.decimals,
133 metadata: mint.metadata,
134 mint_authority: mint.base.mint_authority,
135 freeze_authority: mint.base.freeze_authority,
136 extensions,
137 })
138 }
139}
140
141impl<'a> TryFrom<&ZMintInstructionData<'a>> for Mint {
142 type Error = TokenError;
143
144 fn try_from(instruction_data: &ZMintInstructionData<'a>) -> Result<Self, Self::Error> {
145 let extensions = match &instruction_data.extensions {
146 Some(exts) => {
147 let converted_exts: Vec<_> = exts
148 .iter()
149 .map(|ext| match ext {
150 ZExtensionInstructionData::TokenMetadata(token_metadata_data) => {
151 Ok(ExtensionStruct::TokenMetadata(TokenMetadata {
152 update_authority: token_metadata_data
153 .update_authority
154 .map(|p| *p)
155 .unwrap_or_else(|| Pubkey::from([0u8; 32])),
156 mint: instruction_data.metadata.mint, name: token_metadata_data.name.to_vec(),
158 symbol: token_metadata_data.symbol.to_vec(),
159 uri: token_metadata_data.uri.to_vec(),
160 additional_metadata: token_metadata_data
161 .additional_metadata
162 .as_ref()
163 .map(|ams| {
164 ams.iter()
165 .map(|am| AdditionalMetadata {
166 key: am.key.to_vec(),
167 value: am.value.to_vec(),
168 })
169 .collect()
170 })
171 .unwrap_or_else(Vec::new),
172 }))
173 }
174 _ => Err(TokenError::UnsupportedExtension),
175 })
176 .collect::<Result<Vec<_>, _>>()?;
177 if converted_exts.is_empty() {
178 None
179 } else {
180 Some(converted_exts)
181 }
182 }
183 None => None,
184 };
185
186 Ok(Self {
187 base: BaseMint {
188 mint_authority: instruction_data.mint_authority.map(|p| *p),
189 supply: instruction_data.supply.into(),
190 decimals: instruction_data.decimals,
191 is_initialized: true, freeze_authority: instruction_data.freeze_authority.map(|p| *p),
193 },
194 metadata: MintMetadata {
195 version: instruction_data.metadata.version,
196 mint_decompressed: instruction_data.metadata.mint_decompressed != 0,
197 mint: instruction_data.metadata.mint,
198 mint_signer: instruction_data.metadata.mint_signer,
199 bump: instruction_data.metadata.bump,
200 },
201 reserved: [0u8; 16],
202 account_type: crate::state::mint::ACCOUNT_TYPE_MINT,
203 compression: CompressionInfo::default(),
204 extensions,
205 })
206 }
207}