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