light_token_client/actions/
wrap.rs1use light_client::rpc::{Rpc, RpcError};
6use light_token::{
7 constants::{SPL_TOKEN_2022_PROGRAM_ID, SPL_TOKEN_PROGRAM_ID},
8 instruction::TransferFromSpl,
9 spl_interface::{find_spl_interface_pda, has_restricted_extensions},
10};
11use solana_keypair::Keypair;
12use solana_pubkey::Pubkey;
13use solana_signature::Signature;
14use solana_signer::Signer;
15
16#[derive(Default, Clone, Debug)]
32pub struct Wrap {
33 pub source_spl_ata: Pubkey,
35 pub destination: Pubkey,
37 pub mint: Pubkey,
39 pub amount: u64,
41 pub decimals: u8,
43}
44
45impl Wrap {
46 pub async fn execute<R: Rpc>(
56 self,
57 rpc: &mut R,
58 payer: &Keypair,
59 authority: &Keypair,
60 ) -> Result<Signature, RpcError> {
61 let source_account_info = rpc.get_account(self.source_spl_ata).await?.ok_or_else(|| {
63 RpcError::CustomError("Source SPL token account not found".to_string())
64 })?;
65
66 let spl_token_program = source_account_info.owner;
67
68 if spl_token_program != SPL_TOKEN_PROGRAM_ID
70 && spl_token_program != SPL_TOKEN_2022_PROGRAM_ID
71 {
72 return Err(RpcError::CustomError(format!(
73 "Source SPL token account {} is owned by an unsupported program {}. \
74 Expected SPL Token ({}) or Token-2022 ({}).",
75 self.source_spl_ata,
76 source_account_info.owner,
77 SPL_TOKEN_PROGRAM_ID,
78 SPL_TOKEN_2022_PROGRAM_ID
79 )));
80 }
81
82 let restricted = if spl_token_program == SPL_TOKEN_2022_PROGRAM_ID {
84 let mint_account = rpc
85 .get_account(self.mint)
86 .await?
87 .ok_or_else(|| RpcError::CustomError("Mint account not found".to_string()))?;
88 has_restricted_extensions(&mint_account.data)
89 } else {
90 false
91 };
92
93 let (spl_interface_pda, bump) = find_spl_interface_pda(&self.mint, restricted);
94
95 let ix = TransferFromSpl {
96 amount: self.amount,
97 spl_interface_pda_bump: bump,
98 decimals: self.decimals,
99 source_spl_token_account: self.source_spl_ata,
100 destination: self.destination,
101 authority: authority.pubkey(),
102 mint: self.mint,
103 payer: payer.pubkey(),
104 spl_interface_pda,
105 spl_token_program,
106 }
107 .instruction()
108 .map_err(|e| RpcError::CustomError(format!("Failed to create instruction: {}", e)))?;
109
110 let mut signers: Vec<&Keypair> = vec![payer];
111 if authority.pubkey() != payer.pubkey() {
112 signers.push(authority);
113 }
114
115 rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &signers)
116 .await
117 }
118}