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}