Skip to content

Commit 57e09f2

Browse files
format
1 parent 0583fc1 commit 57e09f2

7 files changed

Lines changed: 68 additions & 74 deletions

File tree

program-tests/utils/src/actions/legacy/instructions/transfer2.rs

Lines changed: 28 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -169,13 +169,23 @@ pub async fn create_generic_transfer2_instruction<R: Rpc + Indexer>(
169169
payer: Pubkey,
170170
should_filter_zero_outputs: bool,
171171
) -> Result<Instruction, TokenSdkError> {
172-
// // Get a single shared output queue for ALL compress/compress-and-close operations
173-
// // This prevents reordering issues caused by the sort_by_key at the end
174-
// let shared_output_queue = rpc
175-
// .get_random_state_tree_info()
176-
// .unwrap()
177-
// .get_output_pubkey()
178-
// .unwrap();
172+
// Transfer2 supports a single output queue per instruction. Legacy helpers accept
173+
// per-action queues, but normalize them down to one shared queue for the IX.
174+
let mut explicit_output_queue = None;
175+
for action in &actions {
176+
let candidate = match action {
177+
Transfer2InstructionType::Compress(input) => Some(input.output_queue),
178+
Transfer2InstructionType::CompressAndClose(input) => Some(input.output_queue),
179+
Transfer2InstructionType::Decompress(_)
180+
| Transfer2InstructionType::Transfer(_)
181+
| Transfer2InstructionType::Approve(_) => None,
182+
};
183+
if let Some(candidate) = candidate {
184+
if explicit_output_queue.is_none() {
185+
explicit_output_queue = Some(candidate);
186+
}
187+
}
188+
}
179189

180190
let mut hashes = Vec::new();
181191
actions.iter().for_each(|account| match account {
@@ -210,26 +220,16 @@ pub async fn create_generic_transfer2_instruction<R: Rpc + Indexer>(
210220
.value;
211221

212222
let mut packed_tree_accounts = PackedAccounts::default();
213-
// tree infos must be packed before packing the token input accounts
214-
let packed_tree_infos = rpc_proof_result
215-
.pack_tree_infos(&mut packed_tree_accounts)
216-
.unwrap();
217-
218-
// We use a single shared output queue for all compress/compress-and-close operations to avoid ordering failures.
219-
let shared_output_queue = if packed_tree_infos.address_trees.is_empty() {
220-
let shared_output_queue = rpc
221-
.get_random_state_tree_info()
223+
// Pack only input state tree infos. Grouped transfer2 proofs can span multiple output trees.
224+
let packed_tree_infos = rpc_proof_result.pack_state_tree_infos(&mut packed_tree_accounts);
225+
226+
let shared_output_queue = explicit_output_queue.unwrap_or_else(|| {
227+
rpc.get_random_state_tree_info()
222228
.unwrap()
223229
.get_output_pubkey()
224-
.unwrap();
225-
packed_tree_accounts.insert_or_get(shared_output_queue)
226-
} else {
227-
packed_tree_infos
228-
.state_trees
229-
.as_ref()
230230
.unwrap()
231-
.output_tree_index
232-
};
231+
});
232+
let shared_output_queue = packed_tree_accounts.insert_or_get(shared_output_queue);
233233

234234
let mut inputs_offset = 0;
235235
let mut in_lamports = Vec::new();
@@ -245,12 +245,7 @@ pub async fn create_generic_transfer2_instruction<R: Rpc + Indexer>(
245245
let token_data = input_token_account
246246
.iter()
247247
.zip(
248-
packed_tree_infos
249-
.state_trees
250-
.as_ref()
251-
.unwrap()
252-
.packed_tree_infos[inputs_offset..]
253-
.iter(),
248+
packed_tree_infos[inputs_offset..].iter(),
254249
)
255250
.map(|(account, rpc_account)| {
256251
if input.to != account.token.owner {
@@ -393,14 +388,7 @@ pub async fn create_generic_transfer2_instruction<R: Rpc + Indexer>(
393388
let token_data = input
394389
.compressed_token_account
395390
.iter()
396-
.zip(
397-
packed_tree_infos
398-
.state_trees
399-
.as_ref()
400-
.unwrap()
401-
.packed_tree_infos[inputs_offset..]
402-
.iter(),
403-
)
391+
.zip(packed_tree_infos[inputs_offset..].iter())
404392
.map(|(account, rpc_account)| {
405393
pack_input_token_account(
406394
account,
@@ -462,14 +450,7 @@ pub async fn create_generic_transfer2_instruction<R: Rpc + Indexer>(
462450
let token_data = input
463451
.compressed_token_account
464452
.iter()
465-
.zip(
466-
packed_tree_infos
467-
.state_trees
468-
.as_ref()
469-
.unwrap()
470-
.packed_tree_infos[inputs_offset..]
471-
.iter(),
472-
)
453+
.zip(packed_tree_infos[inputs_offset..].iter())
473454
.map(|(account, rpc_account)| {
474455
pack_input_token_account(
475456
account,
@@ -544,14 +525,7 @@ pub async fn create_generic_transfer2_instruction<R: Rpc + Indexer>(
544525
let token_data = input
545526
.compressed_token_account
546527
.iter()
547-
.zip(
548-
packed_tree_infos
549-
.state_trees
550-
.as_ref()
551-
.unwrap()
552-
.packed_tree_infos[inputs_offset..]
553-
.iter(),
554-
)
528+
.zip(packed_tree_infos[inputs_offset..].iter())
555529
.map(|(account, rpc_account)| {
556530
pack_input_token_account(
557531
account,

sdk-libs/client/src/interface/instructions.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,10 @@ where
242242
// Process PDAs first, then tokens, to match on-chain split_at(token_accounts_offset).
243243
for &i in pda_indices.iter().chain(token_indices.iter()) {
244244
let (acc, data) = &cold_accounts[i];
245-
let proof_tree_info = tree_infos.get(i).copied().ok_or("tree info index out of bounds")?;
245+
let proof_tree_info = tree_infos
246+
.get(i)
247+
.copied()
248+
.ok_or("tree info index out of bounds")?;
246249
let queue_index = remaining_accounts.insert_or_get(acc.tree_info.queue);
247250
let tree_info = PackedStateTreeInfo {
248251
queue_pubkey_index: queue_index,

sdk-libs/client/src/interface/load_accounts.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -432,10 +432,12 @@ fn build_transfer2(
432432

433433
for (i, ctx) in contexts.iter().enumerate() {
434434
let token = &ctx.compressed.token;
435-
let tree = tree_infos.get(i).ok_or(LoadAccountsError::TreeInfoIndexOutOfBounds {
436-
index: i,
437-
len: tree_infos.len(),
438-
})?;
435+
let tree = tree_infos
436+
.get(i)
437+
.ok_or(LoadAccountsError::TreeInfoIndexOutOfBounds {
438+
index: i,
439+
len: tree_infos.len(),
440+
})?;
439441

440442
let owner_idx = packed.insert_or_get_config(ctx.wallet_owner, true, false);
441443
let ata_idx = packed.insert_or_get(derive_token_ata(&ctx.wallet_owner, &ctx.mint));

sdk-tests/sdk-pinocchio-v2-test/tests/test.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ pub async fn create_pda(
111111
.value;
112112

113113
let output_merkle_tree_index = accounts.insert_or_get(*merkle_tree_pubkey);
114-
let packed_address_tree_info = rpc_result.pack_tree_infos(&mut accounts).address_trees[0];
114+
let packed_tree_infos = rpc_result.pack_tree_infos(&mut accounts)?;
115+
let packed_address_tree_info = packed_tree_infos.address_trees[0];
115116
let (accounts, system_accounts_offset, tree_accounts_offset) = accounts.to_account_metas();
116117
let instruction_data = CreatePdaInstructionData {
117118
proof: rpc_result.proof,
@@ -154,7 +155,7 @@ pub async fn update_pda(
154155
.value;
155156

156157
let packed_accounts = rpc_result
157-
.pack_tree_infos(&mut accounts)
158+
.pack_tree_infos(&mut accounts)?
158159
.state_trees
159160
.unwrap();
160161

sdk-tests/sdk-token-test/tests/test_4_invocations.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ fn pack_selected_output_tree_index(
4747
.next_tree_info
4848
.map(|next| next.pack_output_tree_index(remaining_accounts))
4949
.unwrap_or_else(|| tree_info.pack_output_tree_index(remaining_accounts))
50-
.map_err(|error| RpcError::CustomError(format!("Failed to pack output tree index: {error}")))
50+
.map_err(|error| {
51+
RpcError::CustomError(format!("Failed to pack output tree index: {error}"))
52+
})
5153
}
5254

5355
#[ignore = "fix cpi context usage"]
@@ -525,8 +527,10 @@ async fn test_four_invokes_instruction(
525527
)
526528
.await?
527529
.value;
528-
let output_tree_index =
529-
pack_selected_output_tree_index(mint2_token_account.account.tree_info, &mut remaining_accounts)?;
530+
let output_tree_index = pack_selected_output_tree_index(
531+
mint2_token_account.account.tree_info,
532+
&mut remaining_accounts,
533+
)?;
530534
let packed_tree_infos = pack_input_state_tree_infos(&rpc_result, &mut remaining_accounts);
531535

532536
// Create token metas from compressed accounts - each uses its respective tree info index

sdk-tests/sdk-token-test/tests/test_4_transfer2.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ fn pack_selected_output_tree_index(
5252
.next_tree_info
5353
.map(|next| next.pack_output_tree_index(remaining_accounts))
5454
.unwrap_or_else(|| tree_info.pack_output_tree_index(remaining_accounts))
55-
.map_err(|error| RpcError::CustomError(format!("Failed to pack output tree index: {error}")))
55+
.map_err(|error| {
56+
RpcError::CustomError(format!("Failed to pack output tree index: {error}"))
57+
})
5658
}
5759

5860
#[tokio::test]
@@ -465,8 +467,10 @@ async fn test_four_transfer2_instruction(
465467
)
466468
.await?
467469
.value;
468-
let output_tree_index =
469-
pack_selected_output_tree_index(mint2_token_account.account.tree_info, &mut remaining_accounts)?;
470+
let output_tree_index = pack_selected_output_tree_index(
471+
mint2_token_account.account.tree_info,
472+
&mut remaining_accounts,
473+
)?;
470474
let packed_tree_infos = pack_input_state_tree_infos(&rpc_result, &mut remaining_accounts);
471475

472476
// Create token metas from compressed accounts - each uses its respective tree info index

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

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,20 @@ fn pack_selected_output_tree_context(
5151
(
5252
next.tree,
5353
next.queue,
54-
next.pack_output_tree_index(remaining_accounts).map_err(|error| {
55-
RpcError::CustomError(format!("Failed to pack output tree index: {error}"))
56-
})?,
54+
next.pack_output_tree_index(remaining_accounts)
55+
.map_err(|error| {
56+
RpcError::CustomError(format!("Failed to pack output tree index: {error}"))
57+
})?,
5758
)
5859
} else {
5960
(
6061
tree_info.tree,
6162
tree_info.queue,
62-
tree_info.pack_output_tree_index(remaining_accounts).map_err(|error| {
63-
RpcError::CustomError(format!("Failed to pack output tree index: {error}"))
64-
})?,
63+
tree_info
64+
.pack_output_tree_index(remaining_accounts)
65+
.map_err(|error| {
66+
RpcError::CustomError(format!("Failed to pack output tree index: {error}"))
67+
})?,
6568
)
6669
};
6770

@@ -354,7 +357,10 @@ async fn update_deposit_compressed_account(
354357
rpc_result.accounts[0].tree_info.queue.to_bytes()
355358
);
356359
let (output_tree_index, output_tree_queue_index, output_state_tree_index) =
357-
pack_selected_output_tree_context(rpc_result.accounts[0].tree_info, &mut remaining_accounts)?;
360+
pack_selected_output_tree_context(
361+
rpc_result.accounts[0].tree_info,
362+
&mut remaining_accounts,
363+
)?;
358364
println!("output_tree_index {}", output_tree_index);
359365
println!("output_tree_queue_index {}", output_tree_queue_index);
360366
println!("output_state_tree_index {}", output_state_tree_index);

0 commit comments

Comments
 (0)