Skip to main content

token_acl_client/
metadata.rs

1use 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}