light_token_interface/state/compressed_token/
token_data.rs1use light_compressed_account::Pubkey;
2use light_program_profiler::profile;
3use light_zero_copy::{num_trait::ZeroCopyNumTrait, ZeroCopy, ZeroCopyMut};
4
5use crate::{
6 instructions::extensions::ZExtensionInstructionData,
7 state::extensions::{ExtensionStruct, ZExtensionStructMut},
8 AnchorDeserialize, AnchorSerialize, TokenError,
9};
10
11#[derive(Clone, Copy, Debug, PartialEq, Eq, AnchorSerialize, AnchorDeserialize)]
12#[repr(u8)]
13pub enum CompressedTokenAccountState {
14 Initialized = 0,
16 Frozen = 1,
17}
18
19impl TryFrom<u8> for CompressedTokenAccountState {
20 type Error = TokenError;
21
22 fn try_from(value: u8) -> Result<Self, Self::Error> {
23 match value {
24 0 => Ok(CompressedTokenAccountState::Initialized),
25 1 => Ok(CompressedTokenAccountState::Frozen),
26 _ => Err(TokenError::InvalidAccountState),
27 }
28 }
29}
30
31#[derive(
33 Debug, PartialEq, Eq, AnchorSerialize, AnchorDeserialize, Clone, ZeroCopy, ZeroCopyMut,
34)]
35#[repr(C)]
36pub struct TokenData {
37 pub mint: Pubkey,
39 pub owner: Pubkey,
41 pub amount: u64,
43 pub delegate: Option<Pubkey>,
46 pub state: u8,
48 pub tlv: Option<Vec<ExtensionStruct>>,
50}
51
52impl TokenData {
53 pub fn state(&self) -> Result<CompressedTokenAccountState, TokenError> {
54 CompressedTokenAccountState::try_from(self.state)
55 }
56}
57
58impl<'a> ZTokenDataMut<'a> {
60 #[inline]
63 #[profile]
64 pub fn set(
65 &mut self,
66 mint: Pubkey,
67 owner: Pubkey,
68 amount: impl ZeroCopyNumTrait,
69 delegate: Option<Pubkey>,
70 state: CompressedTokenAccountState,
71 tlv_data: Option<&[ZExtensionInstructionData<'_>]>,
72 ) -> Result<(), TokenError> {
73 self.mint = mint;
74 self.owner = owner;
75 self.amount.set(amount.into());
76 if let Some(z_delegate) = self.delegate.as_deref_mut() {
77 *z_delegate = delegate.ok_or(TokenError::InstructionDataExpectedDelegate)?;
78 }
79 if self.delegate.is_none() && delegate.is_some() {
80 return Err(TokenError::ZeroCopyExpectedDelegate);
81 }
82
83 *self.state = state as u8;
84
85 match (self.tlv.as_mut(), tlv_data) {
87 (Some(tlv_vec), Some(exts)) => {
88 if tlv_vec.len() != 1 || exts.len() != 1 {
89 return Err(TokenError::TlvExtensionLengthMismatch);
90 }
91 for (tlv_ext, instruction_ext) in tlv_vec.iter_mut().zip(exts.iter()) {
92 match (tlv_ext, instruction_ext) {
93 (
94 ZExtensionStructMut::CompressedOnly(compressed_only),
95 ZExtensionInstructionData::CompressedOnly(data),
96 ) => {
97 compressed_only.delegated_amount = data.delegated_amount;
98 compressed_only.withheld_transfer_fee = data.withheld_transfer_fee;
99 compressed_only.is_ata = if data.is_ata() { 1 } else { 0 };
100 }
101 _ => return Err(TokenError::UnsupportedTlvExtensionType),
102 }
103 }
104 }
105 (Some(_), None) | (None, Some(_)) => {
106 return Err(TokenError::TlvExtensionLengthMismatch);
107 }
108 (None, None) => {}
109 }
110
111 Ok(())
112 }
113}