light_system_program/invoke/
sol_compression.rs

1use account_compression::utils::transfer_lamports::transfer_lamports_cpi;
2use aligned_sized::*;
3use anchor_lang::{
4    prelude::*,
5    solana_program::{account_info::AccountInfo, pubkey::Pubkey},
6    Bumps,
7};
8
9use crate::{
10    errors::SystemProgramError,
11    sdk::accounts::{InvokeAccounts, SignerAccounts},
12    InstructionDataInvoke,
13};
14
15#[account]
16#[aligned_sized(anchor)]
17pub struct CompressedSolPda {}
18
19#[constant]
20pub const SOL_POOL_PDA_SEED: &[u8] = b"sol_pool_pda";
21
22pub fn compress_or_decompress_lamports<
23    'a,
24    'b,
25    'c: 'info,
26    'info,
27    A: InvokeAccounts<'info> + SignerAccounts<'info> + Bumps,
28>(
29    inputs: &'a InstructionDataInvoke,
30    ctx: &'a Context<'a, 'b, 'c, 'info, A>,
31) -> Result<()> {
32    if inputs.is_compress {
33        compress_lamports(inputs, ctx)
34    } else {
35        decompress_lamports(inputs, ctx)
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_decompression_recipient().as_ref() {
50        Some(decompression_recipient) => decompression_recipient.to_account_info(),
51        None => return err!(SystemProgramError::DecompressRecipientUndefinedForDecompressSol),
52    };
53    let sol_pool_pda = match ctx.accounts.get_sol_pool_pda().as_ref() {
54        Some(sol_pool_pda) => sol_pool_pda.to_account_info(),
55        None => return err!(SystemProgramError::CompressedSolPdaUndefinedForDecompressSol),
56    };
57    let lamports = match inputs.compress_or_decompress_lamports {
58        Some(lamports) => lamports,
59        None => return err!(SystemProgramError::DeCompressLamportsUndefinedForDecompressSol),
60    };
61
62    transfer_lamports(&sol_pool_pda, &recipient, lamports)
63}
64
65pub fn compress_lamports<
66    'a,
67    'b,
68    'c: 'info,
69    'info,
70    A: InvokeAccounts<'info> + SignerAccounts<'info> + Bumps,
71>(
72    inputs: &'a InstructionDataInvoke,
73    ctx: &'a Context<'a, 'b, 'c, 'info, A>,
74) -> Result<()> {
75    let recipient = match ctx.accounts.get_sol_pool_pda().as_ref() {
76        Some(sol_pool_pda) => sol_pool_pda.to_account_info(),
77        None => return err!(SystemProgramError::CompressedSolPdaUndefinedForCompressSol),
78    };
79    let lamports = match inputs.compress_or_decompress_lamports {
80        Some(lamports) => lamports,
81        None => return err!(SystemProgramError::DeCompressLamportsUndefinedForCompressSol),
82    };
83
84    transfer_lamports_cpi(
85        &ctx.accounts.get_fee_payer().to_account_info(),
86        &recipient,
87        lamports,
88    )
89}
90
91pub fn transfer_lamports<'info>(
92    from: &AccountInfo<'info>,
93    to: &AccountInfo<'info>,
94    lamports: u64,
95) -> Result<()> {
96    let instruction =
97        anchor_lang::solana_program::system_instruction::transfer(from.key, to.key, lamports);
98    let (_, bump) =
99        anchor_lang::prelude::Pubkey::find_program_address(&[SOL_POOL_PDA_SEED], &crate::ID);
100    let bump = &[bump];
101    let seeds = &[&[SOL_POOL_PDA_SEED, bump][..]];
102    anchor_lang::solana_program::program::invoke_signed(
103        &instruction,
104        &[from.clone(), to.clone()],
105        seeds,
106    )?;
107    Ok(())
108}