Skip to content

Commit fdc9690

Browse files
committed
test: CompressAndClose with cpi context
1 parent b48bb44 commit fdc9690

File tree

10 files changed

+428
-45
lines changed

10 files changed

+428
-45
lines changed

sdk-libs/compressed-token-sdk/src/instructions/compress_and_close.rs

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ use crate::{
44
instructions::{
55
transfer2::{
66
account_metas::Transfer2AccountsMetaConfig, create_transfer2_instruction,
7-
Transfer2Inputs,
7+
Transfer2Config, Transfer2Inputs,
88
},
99
CTokenDefaultAccounts,
1010
},
1111
};
12+
use light_compressed_account::instruction_data::cpi_context::CompressedCpiContext;
1213
use light_ctoken_types::state::{CompressedToken, ZExtensionStruct};
1314
use light_profiler::profile;
1415
use light_sdk::{
@@ -175,7 +176,7 @@ pub fn compress_and_close_ctoken_accounts_with_indices<'info>(
175176
idx.source_index,
176177
idx.authority_index,
177178
idx.rent_recipient_index,
178-
i as u8, // Pass the index in the output array
179+
i as u8, // Pass the index in the output array
179180
)?;
180181

181182
token_accounts.push(token_account);
@@ -190,19 +191,37 @@ pub fn compress_and_close_ctoken_accounts_with_indices<'info>(
190191
is_writable: info.is_writable,
191192
});
192193
}
193-
let meta_config = if cpi_context_pubkey.is_some() {
194-
msg!("cpi_context_pubkey is not supported yet");
195-
unimplemented!()
194+
let (meta_config, transfer_config) = if let Some(cpi_context) = cpi_context_pubkey {
195+
let cpi_context_config = CompressedCpiContext {
196+
set_context: false,
197+
first_set_context: false,
198+
cpi_context_account_index: 0, // unused
199+
};
200+
201+
(
202+
Transfer2AccountsMetaConfig {
203+
fee_payer: Some(fee_payer),
204+
cpi_context: Some(cpi_context),
205+
decompressed_accounts_only: false,
206+
sol_pool_pda: None,
207+
sol_decompression_recipient: None,
208+
with_sol_pool: false,
209+
packed_accounts: Some(packed_account_metas.to_vec()),
210+
},
211+
Transfer2Config::default().with_cpi_context(cpi_context, cpi_context_config),
212+
)
196213
} else {
197-
Transfer2AccountsMetaConfig::new(fee_payer, packed_account_metas.to_vec())
214+
(
215+
Transfer2AccountsMetaConfig::new(fee_payer, packed_account_metas.to_vec()),
216+
Transfer2Config::default(),
217+
)
198218
};
199219

200220
// Create the transfer2 instruction with all CompressAndClose operations
201221
let inputs = Transfer2Inputs {
202222
meta_config,
203223
token_accounts,
204-
//transfer_config: Transfer2Config::default()
205-
// .with_cpi_context(cpi_context_pubkey, cpi_context)
224+
transfer_config,
206225
..Default::default()
207226
};
208227

@@ -226,7 +245,6 @@ pub fn compress_and_close_ctoken_accounts<'info>(
226245
fee_payer: Pubkey,
227246
with_rent_authority: bool,
228247
output_queue: AccountInfo<'info>,
229-
cpi_context_pubkey: Option<Pubkey>,
230248
ctoken_solana_accounts: &[&AccountInfo<'info>],
231249
packed_accounts: &[AccountInfo<'info>],
232250
) -> Result<Instruction, TokenSdkError> {
@@ -326,7 +344,7 @@ pub fn compress_and_close_ctoken_accounts<'info>(
326344
// Delegate to the with_indices version
327345
compress_and_close_ctoken_accounts_with_indices(
328346
fee_payer,
329-
cpi_context_pubkey,
347+
None,
330348
&indices_vec,
331349
packed_accounts_vec.as_slice(),
332350
)
@@ -361,7 +379,7 @@ impl AccountMetasVec for CompressAndCloseAccounts {
361379
cpi_context: self.cpi_context,
362380
..Default::default()
363381
};
364-
accounts.add_system_accounts(config)?;
382+
accounts.add_system_accounts_small(config)?;
365383
}
366384
// Add both accounts in one operation for better performance
367385
accounts.pre_accounts.extend_from_slice(&[

sdk-libs/compressed-token-sdk/src/instructions/transfer2/instruction.rs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use light_ctoken_types::{
44
};
55
use light_profiler::profile;
66
use solana_instruction::{AccountMeta, Instruction};
7-
use solana_msg::msg;
87
use solana_pubkey::Pubkey;
98

109
use crate::{
@@ -93,7 +92,6 @@ pub fn create_transfer2_instruction(inputs: Transfer2Inputs) -> Result<Instructi
9392
collected_compressions.push(*compression);
9493
}
9594
let (inputs, output) = token_account.into_inputs_and_outputs();
96-
msg!("output {:?}", output);
9795
// Collect inputs directly (they're already in the right format)
9896
input_token_data_with_context.extend(inputs);
9997

@@ -144,16 +142,6 @@ pub fn create_transfer2_instruction(inputs: Transfer2Inputs) -> Result<Instructi
144142
}
145143
}
146144

147-
// Moved assignment to account meta config
148-
// Add tree accounts first
149-
//for tree_pubkey in tree_pubkeys {
150-
// account_metas.push(AccountMeta::new(tree_pubkey, false));
151-
// }
152-
// Add packed accounts second
153-
// for packed_pubkey in packed_pubkeys {
154-
// account_metas.push(AccountMeta::new(packed_pubkey, false));
155-
// }
156-
println!("account metas {:?}", account_metas);
157145
Ok(Instruction {
158146
program_id: Pubkey::from(COMPRESSED_TOKEN_PROGRAM_ID),
159147
accounts: account_metas,

sdk-libs/sdk-types/src/cpi_accounts_small.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ impl<'a, T: AccountInfoTrait + Clone> CpiAccountsSmall<'a, T> {
5757
.ok_or(LightSdkTypesError::CpiAccountsIndexOutOfBounds(index))
5858
}
5959

60+
pub fn light_system_program(&self) -> Result<&'a T> {
61+
let index = CompressionCpiAccountIndexSmall::LightSystemProgram as usize;
62+
self.accounts
63+
.get(index)
64+
.ok_or(LightSdkTypesError::CpiAccountsIndexOutOfBounds(index))
65+
}
66+
6067
pub fn registered_program_pda(&self) -> Result<&'a T> {
6168
let index = CompressionCpiAccountIndexSmall::RegisteredProgramPda as usize;
6269
self.accounts

sdk-libs/token-client/src/instructions/create_mint.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ pub async fn create_compressed_mint_instruction<R: Rpc + Indexer>(
4343

4444
let output_queue = rpc.get_random_state_tree_info()?.queue;
4545

46-
// Derive compressed mint address using utility function
4746
let compressed_mint_address =
4847
derive_compressed_mint_address(&mint_seed.pubkey(), &address_tree_pubkey);
4948

sdk-tests/sdk-token-test/src/lib.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ use light_compressed_token_sdk::{instructions::Recipient, TokenAccountMeta, Vali
66
use light_sdk::instruction::{PackedAddressTreeInfo, ValidityProof as LightValidityProof};
77

88
mod ctoken_pda;
9+
pub mod mint_compressed_tokens_cpi_write;
910
mod pda_ctoken;
1011
mod process_batch_compress_tokens;
1112
mod process_compress_and_close_cpi;
13+
mod process_compress_and_close_cpi_context;
1214
mod process_compress_and_close_cpi_indices;
1315
mod process_compress_full_and_close;
1416
mod process_compress_tokens;
@@ -63,7 +65,10 @@ use crate::{
6365
ctoken_pda::*, process_create_compressed_account::deposit_tokens,
6466
process_four_transfer2::FourTransfer2Params, process_update_deposit::process_update_deposit,
6567
};
66-
68+
use crate::{
69+
mint_compressed_tokens_cpi_write::MintCompressedTokensCpiWriteParams,
70+
process_compress_and_close_cpi_context::process_compress_and_close_cpi_context,
71+
};
6772
#[program]
6873
pub mod sdk_token_test {
6974

@@ -112,6 +117,20 @@ pub mod sdk_token_test {
112117
process_compress_and_close_cpi(ctx, with_rent_authority, system_accounts_offset)
113118
}
114119

120+
/// Process compress_and_close using the new CompressAndClose mode
121+
/// Compress and close using the higher-level SDK function
122+
/// This uses compress_and_close_ctoken_accounts which handles all index discovery
123+
pub fn compress_and_close_cpi_with_cpi_context<'info>(
124+
ctx: Context<'_, '_, '_, 'info, Generic<'info>>,
125+
indices: Vec<
126+
light_compressed_token_sdk::instructions::compress_and_close::CompressAndCloseIndices,
127+
>,
128+
system_accounts_offset: u8,
129+
params: MintCompressedTokensCpiWriteParams,
130+
) -> Result<()> {
131+
process_compress_and_close_cpi_context(ctx, indices, system_accounts_offset, params)
132+
}
133+
115134
/// Compress and close with manual indices
116135
/// This atomically compresses tokens and closes the account in a single instruction
117136
pub fn compress_and_close_cpi_indices<'info>(
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
use anchor_lang::{prelude::*, solana_program::program::invoke};
2+
use light_compressed_token_sdk::instructions::{
3+
mint_action::{MintActionCpiWriteAccounts, MintActionType},
4+
mint_action_cpi_write, MintActionInputsCpiWrite, MintToRecipient,
5+
};
6+
use light_ctoken_types::instructions::mint_action::CompressedMintWithContext;
7+
use light_sdk::cpi::CpiAccountsSmall;
8+
9+
use crate::Generic;
10+
11+
#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
12+
pub struct MintCompressedTokensCpiWriteParams {
13+
pub compressed_mint_with_context: CompressedMintWithContext,
14+
pub recipients: Vec<MintToRecipient>,
15+
pub cpi_context: light_ctoken_types::instructions::mint_action::CpiContext,
16+
pub cpi_context_pubkey: Pubkey,
17+
}
18+
19+
/// Process minting compressed tokens to an existing mint using CPI write
20+
/// This sets up the CPI context for subsequent operations
21+
pub fn process_mint_compressed_tokens_cpi_write<'info>(
22+
ctx: &Context<'_, '_, '_, 'info, Generic<'info>>,
23+
params: MintCompressedTokensCpiWriteParams,
24+
token_program_cpi_authority: &AccountInfo<'info>,
25+
cpi_accounts: &CpiAccountsSmall<'_, 'info>,
26+
) -> Result<()> {
27+
msg!("Minting compressed tokens with CPI write");
28+
29+
let actions = vec![MintActionType::MintTo {
30+
recipients: params.recipients,
31+
lamports: None,
32+
token_account_version: 2,
33+
}];
34+
35+
let mint_action_inputs = MintActionInputsCpiWrite {
36+
compressed_mint_inputs: params.compressed_mint_with_context,
37+
mint_seed: None, // Not needed for existing mint
38+
mint_bump: None, // Not needed for existing mint
39+
create_mint: false, // Using existing mint
40+
authority: ctx.accounts.signer.key(),
41+
payer: ctx.accounts.signer.key(),
42+
actions,
43+
input_queue: None,
44+
cpi_context: params.cpi_context,
45+
cpi_context_pubkey: *cpi_accounts.cpi_context().unwrap().key,
46+
};
47+
msg!("mint_action_inputs {:?}", mint_action_inputs);
48+
49+
let mint_action_instruction = mint_action_cpi_write(mint_action_inputs).unwrap();
50+
51+
let mint_action_account_infos = MintActionCpiWriteAccounts {
52+
light_system_program: cpi_accounts.light_system_program().unwrap(),
53+
mint_signer: None, // No mint signer for existing mint
54+
authority: ctx.accounts.signer.as_ref(),
55+
fee_payer: ctx.accounts.signer.as_ref(),
56+
cpi_authority_pda: token_program_cpi_authority,
57+
cpi_context: cpi_accounts.cpi_context().unwrap(),
58+
cpi_signer: crate::LIGHT_CPI_SIGNER,
59+
recipient_token_accounts: vec![],
60+
};
61+
msg!(
62+
"mint_action_account_infos.to_account_infos() {:?}",
63+
mint_action_account_infos
64+
.to_account_infos()
65+
.iter()
66+
.map(|x| x.key)
67+
.collect::<Vec<_>>()
68+
);
69+
invoke(
70+
&mint_action_instruction,
71+
&mint_action_account_infos.to_account_infos(),
72+
)?;
73+
74+
msg!("Minting completed, CPI context populated");
75+
76+
Ok(())
77+
}

sdk-tests/sdk-token-test/src/process_compress_and_close_cpi.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::OneCTokenAccount;
22
use anchor_lang::{prelude::*, solana_program::program::invoke};
33
use light_compressed_token_sdk::instructions::compress_and_close_ctoken_accounts;
4-
use light_sdk::cpi::CpiAccounts;
4+
use light_sdk::cpi::CpiAccountsSmall;
55
use light_sdk_types::CpiAccountsConfig;
66

77
/// Process compress_and_close operation using the higher-level compress_and_close_ctoken_accounts function
@@ -17,8 +17,11 @@ pub fn process_compress_and_close_cpi<'info>(
1717
.remaining_accounts
1818
.split_at(system_accounts_offset as usize);
1919

20-
let cpi_accounts =
21-
CpiAccounts::new_with_config(ctx.accounts.signer.as_ref(), system_account_infos, config);
20+
let cpi_accounts = CpiAccountsSmall::new_with_config(
21+
ctx.accounts.signer.as_ref(),
22+
system_account_infos,
23+
config,
24+
);
2225
// Use the higher-level compress_and_close_ctoken_accounts function
2326
// This function handles:
2427
// - Deserializing the compressed token accounts
@@ -29,9 +32,8 @@ pub fn process_compress_and_close_cpi<'info>(
2932
*ctx.accounts.signer.key, // fee_payer
3033
with_rent_authority, // whether to use rent authority from extension
3134
ctx.accounts.output_queue.to_account_info(), // output queue where compressed accounts will be stored
32-
None, // cpi_context_pubkey (not used in this example)
3335
&[&ctx.accounts.ctoken_account.to_account_info()], // slice of ctoken account infos
34-
cpi_accounts.tree_accounts().unwrap(), // packed accounts for the instruction
36+
cpi_accounts.tree_accounts().unwrap(), // packed accounts for the instruction
3537
)
3638
.map_err(|_| ProgramError::InvalidInstructionData)?;
3739

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
use crate::{
2+
mint_compressed_tokens_cpi_write::{
3+
process_mint_compressed_tokens_cpi_write, MintCompressedTokensCpiWriteParams,
4+
},
5+
Generic,
6+
};
7+
use anchor_lang::{prelude::*, solana_program::program::invoke};
8+
use light_compressed_token_sdk::instructions::compress_and_close::{
9+
compress_and_close_ctoken_accounts_with_indices, CompressAndCloseIndices,
10+
};
11+
use light_sdk_types::{CpiAccountsConfig, CpiAccountsSmall};
12+
13+
/// Process compress_and_close operation using the new CompressAndClose mode with manual indices
14+
/// This combines token compression and account closure in a single atomic transaction
15+
pub fn process_compress_and_close_cpi_context<'info>(
16+
ctx: Context<'_, '_, '_, 'info, Generic<'info>>,
17+
indices: Vec<CompressAndCloseIndices>,
18+
system_accounts_offset: u8,
19+
params: MintCompressedTokensCpiWriteParams,
20+
) -> Result<()> {
21+
// Parse CPI accounts following the established pattern
22+
let config = CpiAccountsConfig::new(crate::LIGHT_CPI_SIGNER);
23+
let (_token_account_infos, system_account_infos) = ctx
24+
.remaining_accounts
25+
.split_at(system_accounts_offset as usize);
26+
27+
let cpi_accounts = CpiAccountsSmall::new_with_config(
28+
ctx.accounts.signer.as_ref(),
29+
system_account_infos,
30+
config,
31+
);
32+
33+
process_mint_compressed_tokens_cpi_write(
34+
&ctx,
35+
params,
36+
&_token_account_infos[1], // ctoken cpi authority
37+
&cpi_accounts,
38+
)?;
39+
40+
// Get the tree accounts (packed accounts) from CPI accounts
41+
let packed_accounts = cpi_accounts
42+
.tree_accounts()
43+
.map_err(|e| ProgramError::Custom(e.into()))?;
44+
msg!(
45+
"packed_accounts {:?}",
46+
packed_accounts
47+
.iter()
48+
.map(|x| { x.key })
49+
.collect::<Vec<_>>()
50+
);
51+
// Use the SDK's compress_and_close function with the provided indices
52+
let instruction = compress_and_close_ctoken_accounts_with_indices(
53+
*ctx.accounts.signer.key,
54+
Some(*cpi_accounts.cpi_context().unwrap().key), // Use the CPI context from params
55+
&indices,
56+
&packed_accounts[1..], // skip cpi context account
57+
)
58+
.map_err(ProgramError::from)?;
59+
60+
// Execute the single instruction that handles both compression and closure
61+
let account_infos = [
62+
&[cpi_accounts.fee_payer().clone()][..],
63+
ctx.remaining_accounts,
64+
]
65+
.concat();
66+
67+
invoke(&instruction, account_infos.as_slice())?;
68+
69+
Ok(())
70+
}

sdk-tests/sdk-token-test/src/process_compress_and_close_cpi_indices.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use anchor_lang::{prelude::*, solana_program::program::invoke};
33
use light_compressed_token_sdk::instructions::compress_and_close::{
44
compress_and_close_ctoken_accounts_with_indices, CompressAndCloseIndices,
55
};
6-
use light_sdk::cpi::CpiAccounts;
6+
use light_sdk::cpi::CpiAccountsSmall;
77
use light_sdk_types::CpiAccountsConfig;
88

99
/// Process compress_and_close operation using the new CompressAndClose mode with manual indices
@@ -19,8 +19,11 @@ pub fn process_compress_and_close_cpi_indices<'info>(
1919
.remaining_accounts
2020
.split_at(system_accounts_offset as usize);
2121

22-
let cpi_accounts =
23-
CpiAccounts::new_with_config(ctx.accounts.signer.as_ref(), system_account_infos, config);
22+
let cpi_accounts = CpiAccountsSmall::new_with_config(
23+
ctx.accounts.signer.as_ref(),
24+
system_account_infos,
25+
config,
26+
);
2427

2528
// Get the tree accounts (packed accounts) from CPI accounts
2629
let packed_accounts = cpi_accounts

0 commit comments

Comments
 (0)