name_tokenizer/processor/
create_mint.rs

1//! Create the NFT mint
2
3use crate::{cpi::Cpi, state::MINT_PREFIX};
4
5use {
6    bonfida_utils::{
7        checks::{check_account_key, check_account_owner, check_signer},
8        BorshSize, InstructionsAccount,
9    },
10    borsh::{BorshDeserialize, BorshSerialize},
11    solana_program::{
12        account_info::{next_account_info, AccountInfo},
13        entrypoint::ProgramResult,
14        msg,
15        program::invoke_signed,
16        program_error::ProgramError,
17        program_pack::Pack,
18        pubkey::Pubkey,
19        system_program, sysvar,
20    },
21    spl_token::{instruction::initialize_mint, state::Mint},
22};
23
24#[derive(BorshDeserialize, BorshSerialize, BorshSize)]
25pub struct Params {}
26
27#[derive(InstructionsAccount)]
28pub struct Accounts<'a, T> {
29    /// The mint of the NFT
30    #[cons(writable)]
31    pub mint: &'a T,
32
33    /// The domain name account
34    #[cons(writable)]
35    pub name_account: &'a T,
36
37    /// The central state account
38    pub central_state: &'a T,
39
40    /// The SPL token program account
41    pub spl_token_program: &'a T,
42
43    /// The system program account
44    pub system_program: &'a T,
45
46    /// Rent sysvar account
47    pub rent_account: &'a T,
48
49    /// Fee payer account
50    pub fee_payer: &'a T,
51}
52
53impl<'a, 'b: 'a> Accounts<'a, AccountInfo<'b>> {
54    pub fn parse(
55        accounts: &'a [AccountInfo<'b>],
56        _program_id: &Pubkey,
57    ) -> Result<Self, ProgramError> {
58        let accounts_iter = &mut accounts.iter();
59        let accounts = Accounts {
60            mint: next_account_info(accounts_iter)?,
61            name_account: next_account_info(accounts_iter)?,
62            central_state: next_account_info(accounts_iter)?,
63            spl_token_program: next_account_info(accounts_iter)?,
64            system_program: next_account_info(accounts_iter)?,
65            rent_account: next_account_info(accounts_iter)?,
66            fee_payer: next_account_info(accounts_iter)?,
67        };
68
69        // Check keys
70        check_account_key(accounts.central_state, &crate::central_state::KEY)?;
71        check_account_key(accounts.spl_token_program, &spl_token::ID)?;
72        check_account_key(accounts.system_program, &system_program::ID)?;
73        check_account_key(accounts.rent_account, &sysvar::rent::ID)?;
74
75        // Check owners
76        check_account_owner(accounts.mint, &system_program::ID)?;
77        check_account_owner(accounts.name_account, &spl_name_service::ID)?;
78
79        // Check signer
80        check_signer(accounts.fee_payer)?;
81
82        Ok(accounts)
83    }
84}
85
86pub fn process(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
87    let accounts = Accounts::parse(accounts, program_id)?;
88
89    let (mint, mint_nonce) = Pubkey::find_program_address(
90        &[MINT_PREFIX, &accounts.name_account.key.to_bytes()],
91        program_id,
92    );
93    check_account_key(accounts.mint, &mint)?;
94
95    msg!("+ Creating mint");
96
97    // Create mint account
98    let seeds: &[&[u8]] = &[
99        MINT_PREFIX,
100        &accounts.name_account.key.to_bytes(),
101        &[mint_nonce],
102    ];
103    Cpi::create_account(
104        &spl_token::ID,
105        accounts.system_program,
106        accounts.fee_payer,
107        accounts.mint,
108        seeds,
109        Mint::LEN,
110    )?;
111
112    // Initialize mint
113    let ix = initialize_mint(
114        &spl_token::ID,
115        &mint,
116        &crate::central_state::KEY,
117        Some(&crate::central_state::KEY),
118        0,
119    )?;
120    invoke_signed(
121        &ix,
122        &[
123            accounts.spl_token_program.clone(),
124            accounts.mint.clone(),
125            accounts.rent_account.clone(),
126        ],
127        &[seeds],
128    )?;
129
130    Ok(())
131}