Skip to main content

light_token_client/actions/
transfer_checked.rs

1//! Transfer checked action for Light Token.
2//!
3//! This action provides a clean interface for transferring Light Tokens with decimal validation.
4
5use light_client::rpc::{Rpc, RpcError};
6use light_token::instruction::TransferChecked as TransferCheckedInstruction;
7use solana_keypair::Keypair;
8use solana_pubkey::Pubkey;
9use solana_signature::Signature;
10use solana_signer::Signer;
11
12/// Parameters for transferring Light Tokens with decimal validation.
13///
14/// Unlike the basic transfer, this validates the amount against
15/// the token's decimals to ensure the transfer is using the correct precision.
16///
17/// # Example
18/// ```ignore
19/// TransferChecked {
20///     source,
21///     mint,
22///     destination,
23///     amount: 1000,
24///     decimals: 9,
25///     ..Default::default()
26/// }.execute(&mut rpc, &payer, &authority).await?;
27/// ```
28#[derive(Default, Clone, Debug)]
29pub struct TransferChecked {
30    /// Source token account.
31    pub source: Pubkey,
32    /// The mint public key.
33    pub mint: Pubkey,
34    /// Destination token account.
35    pub destination: Pubkey,
36    /// Amount of tokens to transfer.
37    pub amount: u64,
38    /// Expected decimals for the token.
39    pub decimals: u8,
40}
41
42impl TransferChecked {
43    /// Execute the transfer_checked action via RPC.
44    ///
45    /// # Arguments
46    /// * `rpc` - RPC client
47    /// * `payer` - Transaction fee payer keypair (also pays for rent top-ups)
48    /// * `authority` - Authority that can spend from the source account
49    ///
50    /// # Returns
51    /// `Result<Signature, RpcError>` - The transaction signature
52    pub async fn execute<R: Rpc>(
53        self,
54        rpc: &mut R,
55        payer: &Keypair,
56        authority: &Keypair,
57    ) -> Result<Signature, RpcError> {
58        // Only set fee_payer if payer differs from authority
59        let fee_payer = if payer.pubkey() != authority.pubkey() {
60            Some(payer.pubkey())
61        } else {
62            None
63        };
64
65        let ix = TransferCheckedInstruction {
66            source: self.source,
67            mint: self.mint,
68            destination: self.destination,
69            amount: self.amount,
70            decimals: self.decimals,
71            authority: authority.pubkey(),
72            max_top_up: None,
73            fee_payer,
74        }
75        .instruction()
76        .map_err(|e| RpcError::CustomError(format!("Failed to create instruction: {}", e)))?;
77
78        let mut signers = vec![payer];
79        if authority.pubkey() != payer.pubkey() {
80            signers.push(authority);
81        }
82
83        rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &signers)
84            .await
85    }
86}