light_token/instruction/
approve.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/// # Approve a delegate for a Light Token account:
9/// ```rust
10/// # use solana_pubkey::Pubkey;
11/// # use light_token::instruction::Approve;
12/// # let token_account = Pubkey::new_unique();
13/// # let delegate = Pubkey::new_unique();
14/// # let owner = Pubkey::new_unique();
15/// let instruction = Approve {
16///     token_account,
17///     delegate,
18///     owner,
19///     amount: 100,
20/// }.instruction()?;
21/// # Ok::<(), solana_program_error::ProgramError>(())
22/// ```
23pub struct Approve {
24    /// Light Token account to approve delegation for
25    pub token_account: Pubkey,
26    /// Delegate to approve
27    pub delegate: Pubkey,
28    /// Owner of the Light Token account (signer, payer for top-up)
29    pub owner: Pubkey,
30    /// Amount of tokens to delegate
31    pub amount: u64,
32}
33
34/// # Approve Light Token via CPI:
35/// ```rust,no_run
36/// # use light_token::instruction::ApproveCpi;
37/// # use solana_account_info::AccountInfo;
38/// # let token_account: AccountInfo = todo!();
39/// # let delegate: AccountInfo = todo!();
40/// # let owner: AccountInfo = todo!();
41/// # let system_program: AccountInfo = todo!();
42/// ApproveCpi {
43///     token_account,
44///     delegate,
45///     owner,
46///     system_program,
47///     amount: 100,
48/// }
49/// .invoke()?;
50/// # Ok::<(), solana_program_error::ProgramError>(())
51/// ```
52pub struct ApproveCpi<'info> {
53    pub token_account: AccountInfo<'info>,
54    pub delegate: AccountInfo<'info>,
55    pub owner: AccountInfo<'info>,
56    pub system_program: AccountInfo<'info>,
57    pub amount: u64,
58}
59
60impl<'info> ApproveCpi<'info> {
61    pub fn instruction(&self) -> Result<Instruction, ProgramError> {
62        Approve::from(self).instruction()
63    }
64
65    pub fn invoke(self) -> Result<(), ProgramError> {
66        let instruction = Approve::from(&self).instruction()?;
67        let account_infos = [
68            self.token_account,
69            self.delegate,
70            self.owner,
71            self.system_program,
72        ];
73        invoke(&instruction, &account_infos)
74    }
75
76    pub fn invoke_signed(self, signer_seeds: &[&[&[u8]]]) -> Result<(), ProgramError> {
77        let instruction = Approve::from(&self).instruction()?;
78        let account_infos = [
79            self.token_account,
80            self.delegate,
81            self.owner,
82            self.system_program,
83        ];
84        invoke_signed(&instruction, &account_infos, signer_seeds)
85    }
86}
87
88impl<'info> From<&ApproveCpi<'info>> for Approve {
89    fn from(cpi: &ApproveCpi<'info>) -> Self {
90        Self {
91            token_account: *cpi.token_account.key,
92            delegate: *cpi.delegate.key,
93            owner: *cpi.owner.key,
94            amount: cpi.amount,
95        }
96    }
97}
98
99impl Approve {
100    pub fn instruction(self) -> Result<Instruction, ProgramError> {
101        let mut data = vec![4u8]; // CTokenApprove discriminator
102        data.extend_from_slice(&self.amount.to_le_bytes());
103
104        Ok(Instruction {
105            program_id: Pubkey::from(LIGHT_TOKEN_PROGRAM_ID),
106            accounts: vec![
107                AccountMeta::new(self.token_account, false),
108                AccountMeta::new_readonly(self.delegate, false),
109                AccountMeta::new(self.owner, true),
110                AccountMeta::new_readonly(Pubkey::default(), false),
111            ],
112            data,
113        })
114    }
115}