Skip to main content

light_token/instruction/
mint_to.rs

1use light_sdk_types::LIGHT_TOKEN_PROGRAM_ID;
2use solana_account_info::AccountInfo;
3use solana_cpi::{invoke, invoke_signed};
4use solana_instruction::{AccountMeta, Instruction};
5use solana_program_error::ProgramError;
6use solana_pubkey::Pubkey;
7
8/// # Mint tokens to a ctoken account (simple 3-account instruction):
9/// ```rust
10/// # use solana_pubkey::Pubkey;
11/// # use light_token::instruction::MintTo;
12/// # let mint = Pubkey::new_unique();
13/// # let destination = Pubkey::new_unique();
14/// # let authority = Pubkey::new_unique();
15/// # let fee_payer = Pubkey::new_unique();
16/// let instruction = MintTo {
17///     mint,
18///     destination,
19///     amount: 100,
20///     authority,
21///     fee_payer,
22/// }.instruction()?;
23/// # Ok::<(), solana_program_error::ProgramError>(())
24/// ```
25pub struct MintTo {
26    /// Mint account (supply tracking)
27    pub mint: Pubkey,
28    /// Destination Light Token account to mint to
29    pub destination: Pubkey,
30    /// Amount of tokens to mint
31    pub amount: u64,
32    /// Mint authority
33    pub authority: Pubkey,
34    /// Fee payer for rent top-ups.
35    pub fee_payer: Pubkey,
36}
37
38/// # Mint to ctoken via CPI:
39/// ```rust,no_run
40/// # use light_token::instruction::MintToCpi;
41/// # use solana_account_info::AccountInfo;
42/// # let mint: AccountInfo = todo!();
43/// # let destination: AccountInfo = todo!();
44/// # let authority: AccountInfo = todo!();
45/// # let system_program: AccountInfo = todo!();
46/// # let fee_payer: AccountInfo = todo!();
47/// MintToCpi {
48///     mint,
49///     destination,
50///     amount: 100,
51///     authority,
52///     system_program,
53///     fee_payer,
54/// }
55/// .invoke()?;
56/// # Ok::<(), solana_program_error::ProgramError>(())
57/// ```
58pub struct MintToCpi<'info> {
59    pub mint: AccountInfo<'info>,
60    pub destination: AccountInfo<'info>,
61    pub amount: u64,
62    pub authority: AccountInfo<'info>,
63    pub system_program: AccountInfo<'info>,
64    /// Fee payer for rent top-ups.
65    pub fee_payer: AccountInfo<'info>,
66}
67
68impl<'info> MintToCpi<'info> {
69    pub fn instruction(&self) -> Result<Instruction, ProgramError> {
70        MintTo::from(self).instruction()
71    }
72
73    pub fn invoke(self) -> Result<(), ProgramError> {
74        let instruction = MintTo::from(&self).instruction()?;
75        let account_infos = [
76            self.mint,
77            self.destination,
78            self.authority,
79            self.system_program,
80            self.fee_payer,
81        ];
82        invoke(&instruction, &account_infos)
83    }
84
85    pub fn invoke_signed(self, signer_seeds: &[&[&[u8]]]) -> Result<(), ProgramError> {
86        let instruction = MintTo::from(&self).instruction()?;
87        let account_infos = [
88            self.mint,
89            self.destination,
90            self.authority,
91            self.system_program,
92            self.fee_payer,
93        ];
94        invoke_signed(&instruction, &account_infos, signer_seeds)
95    }
96}
97
98impl<'info> From<&MintToCpi<'info>> for MintTo {
99    fn from(cpi: &MintToCpi<'info>) -> Self {
100        Self {
101            mint: *cpi.mint.key,
102            destination: *cpi.destination.key,
103            amount: cpi.amount,
104            authority: *cpi.authority.key,
105            fee_payer: *cpi.fee_payer.key,
106        }
107    }
108}
109
110impl_with_top_up!(MintTo, MintToWithTopUp);
111
112impl MintTo {
113    fn build_instruction(self, max_top_up: Option<u16>) -> Result<Instruction, ProgramError> {
114        let accounts = vec![
115            AccountMeta::new(self.mint, false),
116            AccountMeta::new(self.destination, false),
117            AccountMeta::new_readonly(self.authority, true),
118            AccountMeta::new_readonly(Pubkey::default(), false),
119            AccountMeta::new(self.fee_payer, true),
120        ];
121
122        let mut data = vec![7u8];
123        data.extend_from_slice(&self.amount.to_le_bytes());
124        if let Some(max_top_up) = max_top_up {
125            data.extend_from_slice(&max_top_up.to_le_bytes());
126        }
127
128        Ok(Instruction {
129            program_id: Pubkey::from(LIGHT_TOKEN_PROGRAM_ID),
130            accounts,
131            data,
132        })
133    }
134}