token_acl_client/
metadata.rs1use std::str::FromStr;
2
3use solana_instruction::Instruction;
4use solana_pubkey::Pubkey;
5use spl_token_2022_interface::{
6 extension::{BaseStateWithExtensions, PodStateWithExtensions},
7 pod::PodMint,
8 ID as SPL_TOKEN_2022_ID,
9};
10use spl_token_metadata_interface::state::{Field, TokenMetadata};
11use token_acl_interface::error::ThawFreezeGateError;
12
13pub const TOKEN_ACL_METADATA_KEY: &str = "token_acl";
14
15pub fn set_mint_tacl_metadata_ix(
16 mint: &Pubkey,
17 metadata_authority: &Pubkey,
18 gating_program: &Pubkey,
19) -> Instruction {
20 spl_token_metadata_interface::instruction::update_field(
21 &SPL_TOKEN_2022_ID,
22 mint,
23 metadata_authority,
24 Field::Key(TOKEN_ACL_METADATA_KEY.to_string()),
25 gating_program.to_string(),
26 )
27}
28
29pub fn get_gating_program_from_mint_data(data: &[u8]) -> Result<Pubkey, ThawFreezeGateError> {
30 let mint = PodStateWithExtensions::<PodMint>::unpack(data)
31 .map_err(|_| ThawFreezeGateError::InvalidTokenMint)?;
32
33 let metadata = mint
34 .get_variable_len_extension::<TokenMetadata>()
35 .map_err(|_| ThawFreezeGateError::InvalidTokenMint)?;
36
37 let gating_program = metadata
38 .additional_metadata
39 .iter()
40 .find(|(key, _)| key == TOKEN_ACL_METADATA_KEY)
41 .map(|(_, val)| val)
42 .ok_or(ThawFreezeGateError::InvalidTokenMint)?;
43
44 Pubkey::from_str(&gating_program).map_err(|_| ThawFreezeGateError::InvalidTokenMint)
45}
46
47#[cfg(feature = "fetch")]
48pub fn get_gating_program_from_mint(
49 rpc: &solana_client::rpc_client::RpcClient,
50 mint_pubkey: &Pubkey,
51) -> Result<Pubkey, ThawFreezeGateError> {
52 let account = rpc
53 .get_account(mint_pubkey)
54 .map_err(|_| ThawFreezeGateError::InvalidTokenMint)?;
55
56 get_gating_program_from_mint_data(&account.data)
57}