light_compressed_pda/invoke/
sol_compression.rs

1use crate::{
2    errors::CompressedPdaError,
3    sdk::accounts::{InvokeAccounts, SignerAccounts},
4    InstructionDataInvoke,
5};
6use aligned_sized::*;
7use anchor_lang::{
8    prelude::*,
9    solana_program::{account_info::AccountInfo, pubkey::Pubkey},
10    Bumps,
11};
12
13#[account]
14#[aligned_sized(anchor)]
15pub struct CompressedSolPda {}
16
17#[constant]
18pub const COMPRESSED_SOL_PDA_SEED: &[u8] = b"compressed_sol_pda";
19
20pub fn compression_lamports<
21    'a,
22    'b,
23    'c: 'info,
24    'info,
25    A: InvokeAccounts<'info> + SignerAccounts<'info> + Bumps,
26>(
27    inputs: &'a InstructionDataInvoke,
28    ctx: &'a Context<'a, 'b, 'c, 'info, A>,
29) -> Result<()> {
30    if inputs.is_compress {
31        compress_lamports(inputs, ctx)
32    } else if inputs.compression_lamports.is_some() {
33        decompress_lamports(inputs, ctx)
34    } else {
35        Ok(())
36    }
37}
38
39pub fn decompress_lamports<
40    'a,
41    'b,
42    'c: 'info,
43    'info,
44    A: InvokeAccounts<'info> + SignerAccounts<'info> + Bumps,
45>(
46    inputs: &'a InstructionDataInvoke,
47    ctx: &'a Context<'a, 'b, 'c, 'info, A>,
48) -> Result<()> {
49    let recipient = match ctx.accounts.get_compression_recipient().as_ref() {
50        Some(compression_recipient) => compression_recipient.to_account_info(),
51        None => return err!(CompressedPdaError::DecompressRecipientUndefinedForDecompressSol),
52    };
53    let compressed_sol_pda = match ctx.accounts.get_compressed_sol_pda().as_ref() {
54        Some(compressed_sol_pda) => compressed_sol_pda.to_account_info(),
55        None => return err!(CompressedPdaError::CompressedSolPdaUndefinedForDecompressSol),
56    };
57    let lamports = match inputs.compression_lamports {
58        Some(lamports) => lamports,
59        None => return err!(CompressedPdaError::DeCompressLamportsUndefinedForDecompressSol),
60    };
61
62    transfer_lamports(&compressed_sol_pda, &recipient, lamports)?;
63
64    Ok(())
65}
66
67pub fn compress_lamports<
68    'a,
69    'b,
70    'c: 'info,
71    'info,
72    A: InvokeAccounts<'info> + SignerAccounts<'info> + Bumps,
73>(
74    inputs: &'a InstructionDataInvoke,
75    ctx: &'a Context<'a, 'b, 'c, 'info, A>,
76) -> Result<()> {
77    let recipient = match ctx.accounts.get_compressed_sol_pda().as_ref() {
78        Some(compressed_sol_pda) => compressed_sol_pda.to_account_info(),
79        None => return err!(CompressedPdaError::CompressedSolPdaUndefinedForCompressSol),
80    };
81    let lamports = match inputs.compression_lamports {
82        Some(lamports) => lamports,
83        None => return err!(CompressedPdaError::DeCompressLamportsUndefinedForCompressSol),
84    };
85
86    transfer_lamports_compress(
87        &ctx.accounts.get_authority().to_account_info(),
88        &recipient,
89        lamports,
90    )
91}
92
93pub fn transfer_lamports_compress<'info>(
94    from: &AccountInfo<'info>,
95    to: &AccountInfo<'info>,
96    lamports: u64,
97) -> Result<()> {
98    let instruction =
99        anchor_lang::solana_program::system_instruction::transfer(from.key, to.key, lamports);
100    anchor_lang::solana_program::program::invoke(&instruction, &[from.clone(), to.clone()])?;
101    Ok(())
102}
103
104pub fn transfer_lamports<'info>(
105    from: &AccountInfo<'info>,
106    to: &AccountInfo<'info>,
107    lamports: u64,
108) -> Result<()> {
109    let instruction =
110        anchor_lang::solana_program::system_instruction::transfer(from.key, to.key, lamports);
111    let (_, bump) =
112        anchor_lang::prelude::Pubkey::find_program_address(&[COMPRESSED_SOL_PDA_SEED], &crate::ID);
113    let bump = &[bump];
114    let seeds = &[&[COMPRESSED_SOL_PDA_SEED, bump][..]];
115    anchor_lang::solana_program::program::invoke_signed(
116        &instruction,
117        &[from.clone(), to.clone()],
118        seeds,
119    )?;
120    Ok(())
121}