use light_client::rpc::{Rpc, RpcError};
use light_token::{
instruction::{SplInterface, TransferInterface as TransferInterfaceInstruction},
spl_interface::find_spl_interface_pda_with_index,
};
use solana_keypair::Keypair;
use solana_pubkey::Pubkey;
use solana_signature::Signature;
use solana_signer::Signer;
#[derive(Default, Clone, Debug)]
pub struct TransferInterface {
pub source: Pubkey,
pub mint: Pubkey,
pub destination: Pubkey,
pub amount: u64,
pub decimals: u8,
pub spl_token_program: Option<Pubkey>,
pub restricted: bool,
}
impl TransferInterface {
pub async fn execute<R: Rpc>(
self,
rpc: &mut R,
payer: &Keypair,
authority: &Keypair,
) -> Result<Signature, RpcError> {
let source_account = rpc.get_account(self.source).await?.ok_or_else(|| {
RpcError::CustomError(format!("Source account {} not found", self.source))
})?;
let destination_account = rpc.get_account(self.destination).await?.ok_or_else(|| {
RpcError::CustomError(format!(
"Destination account {} not found",
self.destination
))
})?;
let source_owner = source_account.owner;
let destination_owner = destination_account.owner;
let spl_interface = if let Some(spl_program) = self.spl_token_program {
let (spl_interface_pda, spl_interface_pda_bump) =
find_spl_interface_pda_with_index(&self.mint, 0, self.restricted);
Some(SplInterface {
mint: self.mint,
spl_token_program: spl_program,
spl_interface_pda,
spl_interface_pda_bump,
})
} else {
None
};
let ix = TransferInterfaceInstruction {
source: self.source,
destination: self.destination,
amount: self.amount,
decimals: self.decimals,
authority: authority.pubkey(),
payer: payer.pubkey(),
mint: self.mint,
spl_interface,
source_owner,
destination_owner,
}
.instruction()
.map_err(|e| RpcError::CustomError(format!("Failed to create instruction: {}", e)))?;
let mut signers = vec![payer];
if authority.pubkey() != payer.pubkey() {
signers.push(authority);
}
rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &signers)
.await
}
}