Skip to content

Commit 4d012c3

Browse files
committed
with cpi context works
1 parent f3373b7 commit 4d012c3

File tree

16 files changed

+213
-51
lines changed

16 files changed

+213
-51
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

program-libs/compressed-account/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ light-zero-copy = { workspace = true, features = ["std"] }
2222
light-macros = { workspace = true }
2323
pinocchio = { workspace = true, optional = true }
2424
solana-program-error = { workspace = true, optional = true }
25-
25+
solana-msg = { workspace = true }
2626
# Feature-gated dependencies
2727
anchor-lang = { workspace = true, optional = true }
2828
bytemuck = { workspace = true, optional = true, features = ["derive"] }

program-libs/compressed-account/src/compressed_account.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,8 @@ pub fn hash_with_hashed_values(
295295
vec.push(&discriminator_bytes);
296296
vec.push(data_hash);
297297
}
298-
298+
println!("hashed with hashed values {:?}", vec);
299+
solana_msg::msg!("hashed with hashed values {:?}", vec);
299300
Ok(Poseidon::hashv(&vec)?)
300301
}
301302

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,10 @@ pub mod sdk_token_test {
9696
sol_pool_pda: false,
9797
sol_compression_recipient: false,
9898
};
99+
let (token_account_infos, system_account_infos) = ctx.remaining_accounts.split_at(8);
99100
let light_cpi_accounts = CpiAccounts::new_with_config(
100101
ctx.accounts.signer.as_ref(),
101-
ctx.remaining_accounts,
102+
system_account_infos,
102103
config,
103104
);
104105

@@ -109,7 +110,19 @@ pub mod sdk_token_test {
109110
mint,
110111
recipient,
111112
deposit_amount,
113+
token_account_infos,
112114
)?;
115+
let config = CpiAccountsConfig {
116+
cpi_signer: crate::LIGHT_CPI_SIGNER,
117+
cpi_context: true,
118+
sol_pool_pda: false,
119+
sol_compression_recipient: false,
120+
};
121+
let light_cpi_accounts = CpiAccounts::new_with_config(
122+
ctx.accounts.signer.as_ref(),
123+
system_account_infos,
124+
config,
125+
);
113126
process_create_compressed_account(
114127
light_cpi_accounts,
115128
proof,

program-tests/sdk-token-test/src/process_create_compressed_account.rs

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub struct MyTokenCompressedAccount {
2121
pub owner: Pubkey,
2222
}
2323

24-
pub fn process_create_compressed_account<'info>(
24+
pub fn process_create_compressed_account(
2525
cpi_accounts: CpiAccounts,
2626
proof: ValidityProof,
2727
address_tree_info: PackedAddressTreeInfo,
@@ -58,56 +58,79 @@ pub fn process_create_compressed_account<'info>(
5858
cpi_context: Some(CompressedCpiContext {
5959
set_context: false,
6060
first_set_context: false,
61-
cpi_context_account_index: (cpi_accounts.system_accounts_len() - 1) as u8, // TODO: confirm
61+
cpi_context_account_index: 0, // seems to be useless. Seems to be unused.
62+
// TODO: unify the account meta generation on and offchain.
6263
}),
6364
..Default::default()
6465
};
65-
66+
msg!(
67+
"(cpi_accounts.system_accounts_len() - 2) {}",
68+
(cpi_accounts.system_accounts_len() - 2)
69+
);
6670
cpi_inputs
6771
.invoke_light_system_program(cpi_accounts)
6872
.map_err(ProgramError::from)?;
6973

7074
Ok(())
7175
}
7276

73-
pub fn deposit_tokens(
74-
cpi_accounts: &CpiAccounts,
75-
token_metas: Vec<TokenAccountMeta>,
76-
output_tree_index: u8,
77+
pub fn deposit_tokens<'info>(
78+
cpi_accounts: &CpiAccounts<'_, 'info>,
79+
mut token_metas: Vec<TokenAccountMeta>,
80+
mut output_tree_index: u8,
7781
mint: Pubkey,
7882
recipient: Pubkey,
7983
amount: u64,
84+
token_account_infos: &[AccountInfo<'info>],
8085
) -> Result<()> {
86+
// // Cpi context is part of the remaining accounts for the token program
87+
// // but not for the system program.
88+
// // We created the accounts from the system programs perspective
89+
// this is true but there is a bug in the system program that adds the cpi context to the remaining accounts
90+
// for token_meta in token_metas.iter_mut() {
91+
// token_meta.packed_tree_info.merkle_tree_pubkey_index += 1;
92+
// token_meta.packed_tree_info.queue_pubkey_index += 1;
93+
// }
94+
// output_tree_index += 1;
8195
let sender_account = CTokenAccount::new(
8296
mint,
8397
*cpi_accounts.fee_payer().key,
8498
token_metas,
8599
output_tree_index,
86100
);
101+
let tree_pubkeys = cpi_accounts.tree_pubkeys().unwrap();
102+
msg!("tree_pubkeys {:?}", tree_pubkeys);
103+
let cpi_context_pubkey = tree_pubkeys[0];
104+
msg!("cpi_context_pubkey {:?}", cpi_context_pubkey);
87105
let transfer_inputs = TransferInputs {
88106
fee_payer: *cpi_accounts.fee_payer().key,
89107
sender_account,
90108
// No validity proof necessary we are just storing things in the cpi context.
91109
validity_proof: None.into(),
92110
recipient,
93-
tree_pubkeys: cpi_accounts.tree_pubkeys().unwrap(),
111+
tree_pubkeys: tree_pubkeys[1..].to_vec(),
94112
config: Some(TransferConfig {
95113
cpi_context: Some(CompressedCpiContext {
96114
set_context: true,
97115
first_set_context: true,
98-
cpi_context_account_index: (cpi_accounts.system_accounts_len() - 1) as u8,
116+
cpi_context_account_index: 0, // TODO: replace with Pubkey (maybe not because it is in tree pubkeys 1 in this case)
99117
}),
118+
cpi_context_pubkey: Some(cpi_context_pubkey),
100119
..Default::default()
101120
}),
102121
amount,
103122
};
104123
let instruction =
105124
light_compressed_token_sdk::instructions::transfer::instruction::transfer(transfer_inputs)
106125
.unwrap();
126+
msg!("instruction {:?}", instruction);
107127
// We can use the property that account infos don't have to be in order if you use
108128
// solana program invoke.
109129
let mut account_infos = cpi_accounts.account_infos().to_vec();
130+
account_infos.extend_from_slice(token_account_infos);
110131
account_infos.push(cpi_accounts.fee_payer().clone());
132+
account_infos.push(cpi_accounts.registered_program_pda().unwrap().clone());
133+
111134
anchor_lang::solana_program::program::invoke(&instruction, account_infos.as_slice())?;
112135

113136
Ok(())

program-tests/sdk-token-test/tests/test_deposit.rs

Lines changed: 99 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
use anchor_lang::InstructionData;
2+
use light_client::indexer::CompressedTokenAccount;
23
use light_compressed_token_sdk::{
3-
instructions::batch_compress::{
4-
get_batch_compress_instruction_account_metas, BatchCompressMetaConfig, Recipient,
4+
instructions::{
5+
batch_compress::{
6+
get_batch_compress_instruction_account_metas, BatchCompressMetaConfig, Recipient,
7+
},
8+
transfer::account_metas::{
9+
get_transfer_instruction_account_metas, TokenAccountsMetaConfig,
10+
},
511
},
612
token_pool::find_token_pool_pda_with_index,
7-
SPL_TOKEN_PROGRAM_ID,
13+
TokenAccountMeta, SPL_TOKEN_PROGRAM_ID,
814
};
915
use light_program_test::{AddressWithTree, Indexer, LightProgramTest, ProgramTestConfig, Rpc};
1016
use light_sdk::{
@@ -32,49 +38,72 @@ async fn test_deposit_compressed_account() {
3238
.unwrap();
3339

3440
let payer = rpc.get_payer().insecure_clone();
35-
let owner = Keypair::new();
3641
let deposit_amount = 1000u64;
3742

38-
// Create recipients for batch compression
39-
let recipient1 = Keypair::new().pubkey();
40-
let recipient2 = Keypair::new().pubkey();
41-
42-
let recipients = vec![
43-
Recipient {
44-
pubkey: recipient1,
45-
amount: 100_000,
46-
},
47-
Recipient {
48-
pubkey: recipient2,
49-
amount: 200_000,
50-
},
51-
];
43+
let recipients = vec![Recipient {
44+
pubkey: payer.pubkey(),
45+
amount: 100_000,
46+
}];
5247

5348
// Execute batch compress (this will create mint, token account, and compress)
54-
batch_compress_spl_tokens(&mut rpc, &payer, recipients)
49+
batch_compress_spl_tokens(&mut rpc, &payer, recipients.clone())
5550
.await
5651
.unwrap();
5752

5853
println!("Batch compressed tokens successfully");
5954

55+
// Fetch the compressed token accounts created by batch compress
56+
let recipient1 = recipients[0].pubkey;
57+
let compressed_accounts = rpc
58+
.indexer()
59+
.unwrap()
60+
.get_compressed_token_accounts_by_owner(&recipient1, None, None)
61+
.await
62+
.unwrap()
63+
.value
64+
.items;
65+
66+
assert!(
67+
!compressed_accounts.is_empty(),
68+
"Should have compressed token accounts"
69+
);
70+
let ctoken_account = &compressed_accounts[0];
71+
72+
println!(
73+
"Found compressed token account: amount={}, owner={}",
74+
ctoken_account.token.amount, ctoken_account.token.owner
75+
);
76+
6077
// Derive the address that will be created for deposit
6178
let address_tree_info = rpc.get_address_tree_v1();
62-
let (address, _) = derive_address(
63-
&[b"deposit", owner.pubkey().to_bytes().as_ref()],
79+
let (deposit_address, _) = derive_address(
80+
&[b"deposit", payer.pubkey().to_bytes().as_ref()],
6481
&address_tree_info.tree,
6582
&sdk_token_test::ID,
6683
);
6784

68-
// Create deposit instruction
69-
create_deposit_compressed_account(&mut rpc, &payer, owner.pubkey(), deposit_amount)
70-
.await
71-
.unwrap();
85+
// Derive recipient PDA from the deposit address
86+
let (recipient_pda, _) = Pubkey::find_program_address(
87+
&[b"recipient", deposit_address.as_ref()],
88+
&sdk_token_test::ID,
89+
);
90+
91+
// Create deposit instruction with the compressed token account
92+
create_deposit_compressed_account(
93+
&mut rpc,
94+
&payer,
95+
ctoken_account,
96+
recipient_pda,
97+
deposit_amount,
98+
)
99+
.await
100+
.unwrap();
72101

73102
println!("Created compressed account deposit successfully");
74103

75104
// Verify the compressed account was created at the expected address
76105
let compressed_account = rpc
77-
.get_compressed_account(address, None)
106+
.get_compressed_account(deposit_address, None)
78107
.await
79108
.unwrap()
80109
.value;
@@ -87,33 +116,45 @@ async fn test_deposit_compressed_account() {
87116
async fn create_deposit_compressed_account(
88117
rpc: &mut LightProgramTest,
89118
payer: &Keypair,
90-
owner: Pubkey,
119+
ctoken_account: &CompressedTokenAccount,
120+
recipient: Pubkey,
91121
amount: u64,
92122
) -> Result<Signature, RpcError> {
93123
let tree_info = rpc.get_random_state_tree_info().unwrap();
124+
println!("tree_info {:?}", tree_info);
94125

95126
let mut remaining_accounts = PackedAccounts::default();
127+
let config = TokenAccountsMetaConfig::new_client();
128+
let metas = get_transfer_instruction_account_metas(config);
129+
println!("metas {:?}", metas);
130+
println!("metas len() {}", metas.len());
131+
remaining_accounts.add_pre_accounts_metas(metas.as_slice());
96132

97-
let output_tree_index = tree_info
98-
.pack_output_tree_index(&mut remaining_accounts)
99-
.unwrap();
100133
let config = SystemAccountMetaConfig::new_with_cpi_context(
101134
sdk_token_test::ID,
102135
tree_info.cpi_context.unwrap(),
103136
);
137+
println!("cpi_context {:?}", config);
104138
remaining_accounts.add_system_accounts(config);
105-
106139
let address_tree_info = rpc.get_address_tree_v1();
107140

108141
let (address, _) = derive_address(
109-
&[b"deposit", owner.to_bytes().as_ref()],
142+
&[b"deposit", payer.pubkey().to_bytes().as_ref()],
110143
&address_tree_info.tree,
111144
&sdk_token_test::ID,
112145
);
113146

147+
// Get mint from the compressed token account
148+
let mint = ctoken_account.token.mint;
149+
println!(
150+
"ctoken_account.account.hash {:?}",
151+
ctoken_account.account.hash
152+
);
153+
println!("ctoken_account.account {:?}", ctoken_account.account);
154+
// Get validity proof for the compressed token account and new address
114155
let rpc_result = rpc
115156
.get_validity_proof(
116-
vec![],
157+
vec![ctoken_account.account.hash],
117158
vec![AddressWithTree {
118159
address,
119160
tree: address_tree_info.tree,
@@ -123,9 +164,25 @@ async fn create_deposit_compressed_account(
123164
.await?
124165
.value;
125166
let packed_accounts = rpc_result.pack_tree_infos(&mut remaining_accounts);
167+
println!("packed_accounts {:?}", packed_accounts.state_trees);
126168

127-
let (remaining_accounts, _, _) = remaining_accounts.to_account_metas();
169+
// Create token meta from compressed account
170+
let tree_info = packed_accounts
171+
.state_trees
172+
.as_ref()
173+
.unwrap()
174+
.packed_tree_infos[0];
175+
176+
let token_metas = vec![TokenAccountMeta {
177+
amount: ctoken_account.token.amount,
178+
delegate_index: None,
179+
packed_tree_info: tree_info,
180+
lamports: None,
181+
tlv: None,
182+
}];
128183

184+
let (remaining_accounts, _, _) = remaining_accounts.to_account_metas();
185+
println!("remaining_accounts {:?}", remaining_accounts);
129186
let instruction = Instruction {
130187
program_id: sdk_token_test::ID,
131188
accounts: [
@@ -136,8 +193,11 @@ async fn create_deposit_compressed_account(
136193
data: sdk_token_test::instruction::Deposit {
137194
proof: rpc_result.proof,
138195
address_tree_info: packed_accounts.address_trees[0],
139-
output_tree_index,
196+
output_tree_index: packed_accounts.state_trees.unwrap().output_tree_index,
140197
deposit_amount: amount,
198+
token_metas,
199+
mint,
200+
recipient,
141201
}
142202
.data(),
143203
};
@@ -150,7 +210,7 @@ async fn batch_compress_spl_tokens(
150210
rpc: &mut LightProgramTest,
151211
payer: &Keypair,
152212
recipients: Vec<Recipient>,
153-
) -> Result<Signature, RpcError> {
213+
) -> Result<Pubkey, RpcError> {
154214
// Create mint and token account
155215
let mint = create_mint_helper(rpc, payer).await;
156216
println!("Created mint: {}", mint);
@@ -214,5 +274,7 @@ async fn batch_compress_spl_tokens(
214274
};
215275

216276
rpc.create_and_send_transaction(&[instruction], &payer.pubkey(), &[payer])
217-
.await
277+
.await?;
278+
279+
Ok(mint)
218280
}

0 commit comments

Comments
 (0)