light_client/indexer/types/
token.rs1use borsh::BorshDeserialize;
2use light_compressed_account::compressed_account::CompressedAccountWithMerkleContext;
3use light_token::compat::{AccountState, TokenData};
4use light_token_interface::state::ExtensionStruct;
5use solana_pubkey::Pubkey;
6
7use super::{
8 super::{base58::decode_base58_to_fixed_array, IndexerError},
9 account::CompressedAccount,
10};
11
12#[derive(Clone, Default, Debug, PartialEq)]
13pub struct CompressedTokenAccount {
14 pub token: TokenData,
16 pub account: CompressedAccount,
18}
19
20fn parse_token_data(td: &photon_api::types::TokenData) -> Result<TokenData, IndexerError> {
21 Ok(TokenData {
22 mint: Pubkey::new_from_array(decode_base58_to_fixed_array(&td.mint)?),
23 owner: Pubkey::new_from_array(decode_base58_to_fixed_array(&td.owner)?),
24 amount: *td.amount,
25 delegate: td
26 .delegate
27 .as_ref()
28 .map(|d| decode_base58_to_fixed_array(d).map(Pubkey::new_from_array))
29 .transpose()?,
30 state: match td.state {
31 photon_api::types::AccountState::Initialized => AccountState::Initialized,
32 photon_api::types::AccountState::Frozen => AccountState::Frozen,
33 },
34 tlv: td
35 .tlv
36 .as_ref()
37 .map(|tlv| {
38 let bytes = base64::decode_config(&**tlv, base64::STANDARD_NO_PAD)
39 .map_err(|e| IndexerError::decode_error("tlv", e))?;
40 Vec::<ExtensionStruct>::deserialize(&mut bytes.as_slice())
41 .map_err(|e| IndexerError::decode_error("extensions", e))
42 })
43 .transpose()?,
44 })
45}
46
47impl TryFrom<&photon_api::types::TokenAccount> for CompressedTokenAccount {
48 type Error = IndexerError;
49
50 fn try_from(token_account: &photon_api::types::TokenAccount) -> Result<Self, Self::Error> {
51 let account = CompressedAccount::try_from(&token_account.account)?;
52 let token = parse_token_data(&token_account.token_data)?;
53 Ok(CompressedTokenAccount { token, account })
54 }
55}
56
57impl TryFrom<&photon_api::types::TokenAccountV2> for CompressedTokenAccount {
58 type Error = IndexerError;
59
60 fn try_from(token_account: &photon_api::types::TokenAccountV2) -> Result<Self, Self::Error> {
61 let account = CompressedAccount::try_from(&token_account.account)?;
62 let token = parse_token_data(&token_account.token_data)?;
63 Ok(CompressedTokenAccount { token, account })
64 }
65}
66
67#[allow(clippy::from_over_into)]
68impl Into<light_token::compat::TokenDataWithMerkleContext> for CompressedTokenAccount {
69 fn into(self) -> light_token::compat::TokenDataWithMerkleContext {
70 let compressed_account = CompressedAccountWithMerkleContext::from(self.account);
71
72 light_token::compat::TokenDataWithMerkleContext {
73 token_data: self.token,
74 compressed_account,
75 }
76 }
77}
78
79#[allow(clippy::from_over_into)]
80impl Into<Vec<light_token::compat::TokenDataWithMerkleContext>>
81 for super::super::response::Response<
82 super::super::response::ItemsWithCursor<CompressedTokenAccount>,
83 >
84{
85 fn into(self) -> Vec<light_token::compat::TokenDataWithMerkleContext> {
86 self.value
87 .items
88 .into_iter()
89 .map(
90 |token_account| light_token::compat::TokenDataWithMerkleContext {
91 token_data: token_account.token,
92 compressed_account: CompressedAccountWithMerkleContext::from(
93 token_account.account.clone(),
94 ),
95 },
96 )
97 .collect::<Vec<light_token::compat::TokenDataWithMerkleContext>>()
98 }
99}
100
101impl TryFrom<light_token::compat::TokenDataWithMerkleContext> for CompressedTokenAccount {
102 type Error = IndexerError;
103
104 fn try_from(
105 token_data_with_context: light_token::compat::TokenDataWithMerkleContext,
106 ) -> Result<Self, Self::Error> {
107 let account = CompressedAccount::try_from(token_data_with_context.compressed_account)?;
108
109 Ok(CompressedTokenAccount {
110 token: token_data_with_context.token_data,
111 account,
112 })
113 }
114}
115
116#[derive(Clone, Default, Debug, PartialEq)]
117pub struct TokenBalance {
118 pub balance: u64,
119 pub mint: Pubkey,
120}
121
122impl TryFrom<&photon_api::types::TokenBalance> for TokenBalance {
123 type Error = IndexerError;
124
125 fn try_from(token_balance: &photon_api::types::TokenBalance) -> Result<Self, Self::Error> {
126 Ok(TokenBalance {
127 balance: *token_balance.balance,
128 mint: Pubkey::new_from_array(decode_base58_to_fixed_array(&token_balance.mint)?),
129 })
130 }
131}
132
133#[derive(Debug, Clone, PartialEq, Default)]
134pub struct OwnerBalance {
135 pub balance: u64,
136 pub owner: Pubkey,
137}
138
139impl TryFrom<&photon_api::types::OwnerBalance> for OwnerBalance {
140 type Error = IndexerError;
141
142 fn try_from(owner_balance: &photon_api::types::OwnerBalance) -> Result<Self, Self::Error> {
143 Ok(OwnerBalance {
144 balance: *owner_balance.balance,
145 owner: Pubkey::new_from_array(decode_base58_to_fixed_array(&owner_balance.owner)?),
146 })
147 }
148}