light_compressed_token_sdk/
compat.rs1use light_compressed_account::compressed_account::CompressedAccountWithMerkleContext;
7use light_sdk::light_hasher::{sha256::Sha256BE, HasherError};
8use solana_program_error::ProgramError;
9use solana_pubkey::Pubkey;
10
11use crate::{AnchorDeserialize, AnchorSerialize};
12
13#[derive(Clone, Copy, Debug, PartialEq, Eq, AnchorDeserialize, AnchorSerialize, Default)]
14#[repr(u8)]
15pub enum AccountState {
16 #[default]
17 Initialized = 0,
18 Frozen = 1,
19}
20
21impl From<AccountState> for light_token_interface::state::CompressedTokenAccountState {
22 fn from(state: AccountState) -> Self {
23 match state {
24 AccountState::Initialized => {
25 light_token_interface::state::CompressedTokenAccountState::Initialized
26 }
27 AccountState::Frozen => {
28 light_token_interface::state::CompressedTokenAccountState::Frozen
29 }
30 }
31 }
32}
33
34impl TryFrom<u8> for AccountState {
35 type Error = ProgramError;
36
37 fn try_from(value: u8) -> Result<Self, Self::Error> {
38 match value {
39 0 => Ok(AccountState::Initialized),
40 1 => Ok(AccountState::Frozen),
41 _ => Err(ProgramError::InvalidAccountData),
42 }
43 }
44}
45
46#[derive(Debug, PartialEq, Eq, AnchorDeserialize, AnchorSerialize, Clone, Default)]
50pub struct TokenData {
51 pub mint: Pubkey,
53 pub owner: Pubkey,
55 pub amount: u64,
57 pub delegate: Option<Pubkey>,
59 pub state: AccountState,
61 pub tlv: Option<Vec<light_token_interface::state::ExtensionStruct>>,
63}
64
65impl TokenData {
66 #[inline(always)]
69 pub fn hash_sha_flat(&self) -> Result<[u8; 32], HasherError> {
70 use light_sdk::light_hasher::Hasher;
71 let bytes = self.try_to_vec().map_err(|_| HasherError::BorshError)?;
72 Sha256BE::hash(bytes.as_slice())
73 }
74}
75
76#[derive(Debug, Clone, PartialEq)]
78pub struct TokenDataWithMerkleContext {
79 pub token_data: TokenData,
80 pub compressed_account: CompressedAccountWithMerkleContext,
81}
82
83impl TokenDataWithMerkleContext {
84 pub fn hash(&self) -> Result<[u8; 32], HasherError> {
86 if let Some(data) = self.compressed_account.compressed_account.data.as_ref() {
87 match data.discriminator {
88 [0, 0, 0, 0, 0, 0, 0, 4] => self.token_data.hash_sha_flat(),
89 _ => Err(HasherError::EmptyInput),
90 }
91 } else {
92 Err(HasherError::EmptyInput)
93 }
94 }
95}
96
97impl From<TokenData> for light_token_interface::state::TokenData {
98 fn from(data: TokenData) -> Self {
99 use light_token_interface::state::CompressedTokenAccountState;
100
101 Self {
102 mint: data.mint.to_bytes().into(),
103 owner: data.owner.to_bytes().into(),
104 amount: data.amount,
105 delegate: data.delegate.map(|d| d.to_bytes().into()),
106 state: match data.state {
107 AccountState::Initialized => CompressedTokenAccountState::Initialized as u8,
108 AccountState::Frozen => CompressedTokenAccountState::Frozen as u8,
109 },
110 tlv: data.tlv,
111 }
112 }
113}
114
115impl From<light_token_interface::state::TokenData> for TokenData {
116 fn from(data: light_token_interface::state::TokenData) -> Self {
117 Self {
118 mint: Pubkey::new_from_array(data.mint.to_bytes()),
119 owner: Pubkey::new_from_array(data.owner.to_bytes()),
120 amount: data.amount,
121 delegate: data.delegate.map(|d| Pubkey::new_from_array(d.to_bytes())),
122 state: AccountState::try_from(data.state).unwrap_or(AccountState::Initialized),
123 tlv: data.tlv,
124 }
125 }
126}
127
128pub type InputTokenDataCompressible =
130 light_token_interface::instructions::transfer2::MultiTokenTransferOutputData;