spl_token_wrap/mint_customizer/
default_token_2022.rs

1use {
2    crate::{get_wrapped_mint_authority, mint_customizer::interface::MintCustomizer},
3    solana_account_info::AccountInfo,
4    solana_cpi::invoke,
5    solana_program_error::{ProgramError, ProgramResult},
6    solana_pubkey::Pubkey,
7    spl_token_2022::{
8        extension::{
9            confidential_transfer::instruction::initialize_mint as initialize_confidential_transfer_mint,
10            metadata_pointer::instruction::initialize as initialize_metadata_pointer,
11            ExtensionType::{self},
12            PodStateWithExtensions,
13        },
14        pod::PodMint,
15        state::Mint,
16    },
17};
18
19/// This implementation adds the `ConfidentialTransferMint` & `MetadataPointer`
20/// extensions by default.
21pub struct DefaultToken2022Customizer;
22
23impl MintCustomizer for DefaultToken2022Customizer {
24    fn get_token_2022_mint_space() -> Result<usize, ProgramError> {
25        // Calculate space for all extensions that are initialized *before* the base
26        // mint. The TokenMetadata extension is initialized *after* and its
27        // `initialize` instruction handles its own reallocation.
28        ExtensionType::try_calculate_account_len::<Mint>(&[
29            ExtensionType::ConfidentialTransferMint,
30            ExtensionType::MetadataPointer,
31        ])
32    }
33
34    fn initialize_extensions(
35        wrapped_mint_account: &AccountInfo,
36        wrapped_token_program_account: &AccountInfo,
37    ) -> ProgramResult {
38        // Initialize confidential transfer ext
39        invoke(
40            &initialize_confidential_transfer_mint(
41                wrapped_token_program_account.key,
42                wrapped_mint_account.key,
43                None, // Immutable. No one can later change privacy settings.
44                true, // No approvals necessary to use.
45                None, // No auditor can decrypt transaction amounts.
46            )?,
47            &[wrapped_mint_account.clone()],
48        )?;
49
50        // Initialize metadata pointer
51        let wrapped_mint_authority = get_wrapped_mint_authority(wrapped_mint_account.key);
52        invoke(
53            &initialize_metadata_pointer(
54                wrapped_token_program_account.key,
55                wrapped_mint_account.key,
56                Some(wrapped_mint_authority),
57                Some(*wrapped_mint_account.key),
58            )?,
59            &[wrapped_mint_account.clone()],
60        )?;
61
62        Ok(())
63    }
64
65    fn get_freeze_auth_and_decimals(
66        unwrapped_mint_account: &AccountInfo,
67    ) -> Result<(Option<Pubkey>, u8), ProgramError> {
68        // Copy fields over from original mint
69        let unwrapped_mint_data = unwrapped_mint_account.try_borrow_data()?;
70        let pod_mint = PodStateWithExtensions::<PodMint>::unpack(&unwrapped_mint_data)?.base;
71        let freeze_authority = pod_mint.freeze_authority.ok_or(()).ok();
72        let decimals = pod_mint.decimals;
73        Ok((freeze_authority, decimals))
74    }
75}