1extern crate self as light_instruction_decoder;
15
16use borsh::BorshDeserialize;
17use light_compressed_account::instruction_data::{
18 data::InstructionDataInvoke, invoke_cpi::InstructionDataInvokeCpi,
19 with_account_info::InstructionDataInvokeCpiWithAccountInfo,
20 with_readonly::InstructionDataInvokeCpiWithReadOnly,
21};
22use light_instruction_decoder_derive::InstructionDecoder;
23use solana_instruction::AccountMeta;
24use solana_pubkey::Pubkey;
25
26const SYSTEM_PROGRAM_ID: &str = "11111111111111111111111111111111";
28
29#[cfg(not(target_os = "solana"))]
38fn format_input_accounts_section(
39 output: &mut String,
40 accounts: &[light_compressed_account::compressed_account::PackedCompressedAccountWithMerkleContext],
41 instruction_accounts: &[AccountMeta],
42) {
43 use std::fmt::Write;
44
45 if accounts.is_empty() {
46 return;
47 }
48
49 let _ = writeln!(output, "Input Accounts ({}):", accounts.len());
50 for (i, acc) in accounts.iter().enumerate() {
51 let _ = writeln!(output, " [{}]", i);
52 let _ = writeln!(
53 output,
54 " owner: {}",
55 Pubkey::new_from_array(acc.compressed_account.owner.to_bytes())
56 );
57 if let Some(addr) = acc.compressed_account.address {
58 let _ = writeln!(output, " address: {:?}", addr);
59 }
60 let _ = writeln!(
61 output,
62 " lamports: {}",
63 acc.compressed_account.lamports
64 );
65 if let Some(ref acc_data) = acc.compressed_account.data {
66 let _ = writeln!(output, " data_hash: {:?}", acc_data.data_hash);
67 let _ = writeln!(output, " discriminator: {:?}", acc_data.discriminator);
68 }
69 let tree_idx = Some(acc.merkle_context.merkle_tree_pubkey_index);
70 let queue_idx = Some(acc.merkle_context.queue_pubkey_index);
71 let (tree_pubkey, _queue_pubkey) =
72 resolve_tree_and_queue_pubkeys(instruction_accounts, tree_idx, queue_idx);
73 if let Some(tp) = tree_pubkey {
74 let _ = writeln!(
75 output,
76 " merkle_tree_pubkey (index {}): {}",
77 acc.merkle_context.merkle_tree_pubkey_index, tp
78 );
79 }
80 let _ = writeln!(
81 output,
82 " leaf_index: {}",
83 acc.merkle_context.leaf_index
84 );
85 let _ = writeln!(output, " root_index: {}", acc.root_index);
86 }
87}
88
89#[cfg(not(target_os = "solana"))]
93fn format_readonly_input_accounts_section(
94 output: &mut String,
95 accounts: &[light_compressed_account::instruction_data::with_readonly::InAccount],
96 invoking_program_id: &light_compressed_account::pubkey::Pubkey,
97 instruction_accounts: &[AccountMeta],
98) {
99 use std::fmt::Write;
100
101 if accounts.is_empty() {
102 return;
103 }
104
105 let _ = writeln!(output, "Input Accounts ({}):", accounts.len());
106 for (i, acc) in accounts.iter().enumerate() {
107 let _ = writeln!(output, " [{}]", i);
108 let _ = writeln!(
109 output,
110 " owner: {}",
111 Pubkey::new_from_array(invoking_program_id.to_bytes())
112 );
113 if let Some(addr) = acc.address {
114 let _ = writeln!(output, " address: {:?}", addr);
115 }
116 let _ = writeln!(output, " lamports: {}", acc.lamports);
117 let _ = writeln!(output, " data_hash: {:?}", acc.data_hash);
118 let _ = writeln!(output, " discriminator: {:?}", acc.discriminator);
119 let tree_idx = Some(acc.merkle_context.merkle_tree_pubkey_index);
120 let queue_idx = Some(acc.merkle_context.queue_pubkey_index);
121 let (tree_pubkey, _queue_pubkey) =
122 resolve_tree_and_queue_pubkeys(instruction_accounts, tree_idx, queue_idx);
123 if let Some(tp) = tree_pubkey {
124 let _ = writeln!(
125 output,
126 " merkle_tree_pubkey (index {}): {}",
127 acc.merkle_context.merkle_tree_pubkey_index, tp
128 );
129 }
130 let _ = writeln!(
131 output,
132 " leaf_index: {}",
133 acc.merkle_context.leaf_index
134 );
135 let _ = writeln!(output, " root_index: {}", acc.root_index);
136 }
137}
138
139#[cfg(not(target_os = "solana"))]
144fn format_output_accounts_section(
145 output: &mut String,
146 accounts: &[light_compressed_account::instruction_data::data::OutputCompressedAccountWithPackedContext],
147 instruction_accounts: &[AccountMeta],
148) {
149 use std::fmt::Write;
150
151 if accounts.is_empty() {
152 return;
153 }
154
155 let _ = writeln!(output, "Output Accounts ({}):", accounts.len());
156 for (i, acc) in accounts.iter().enumerate() {
157 let _ = writeln!(output, " [{}]", i);
158 let _ = writeln!(
159 output,
160 " owner: {}",
161 Pubkey::new_from_array(acc.compressed_account.owner.to_bytes())
162 );
163 if let Some(addr) = acc.compressed_account.address {
164 let _ = writeln!(output, " address: {:?}", addr);
165 }
166 let _ = writeln!(
167 output,
168 " lamports: {}",
169 acc.compressed_account.lamports
170 );
171 if let Some(ref acc_data) = acc.compressed_account.data {
172 let _ = writeln!(output, " data_hash: {:?}", acc_data.data_hash);
173 let _ = writeln!(output, " discriminator: {:?}", acc_data.discriminator);
174 let _ = writeln!(
175 output,
176 " data ({} bytes): {:?}",
177 acc_data.data.len(),
178 acc_data.data
179 );
180 }
181 let tree_idx = Some(acc.merkle_tree_index);
182 let (tree_pubkey, _) = resolve_tree_and_queue_pubkeys(instruction_accounts, tree_idx, None);
183 if let Some(tp) = tree_pubkey {
184 let _ = writeln!(
185 output,
186 " merkle_tree_pubkey (index {}): {}",
187 acc.merkle_tree_index, tp
188 );
189 }
190 }
191}
192
193#[cfg(not(target_os = "solana"))]
197fn format_readonly_output_accounts_section(
198 output: &mut String,
199 accounts: &[light_compressed_account::instruction_data::data::OutputCompressedAccountWithPackedContext],
200 invoking_program_id: &light_compressed_account::pubkey::Pubkey,
201 instruction_accounts: &[AccountMeta],
202) {
203 use std::fmt::Write;
204
205 if accounts.is_empty() {
206 return;
207 }
208
209 let _ = writeln!(output, "Output Accounts ({}):", accounts.len());
210 for (i, acc) in accounts.iter().enumerate() {
211 let _ = writeln!(output, " [{}]", i);
212 let _ = writeln!(
213 output,
214 " owner: {}",
215 Pubkey::new_from_array(invoking_program_id.to_bytes())
216 );
217 if let Some(addr) = acc.compressed_account.address {
218 let _ = writeln!(output, " address: {:?}", addr);
219 }
220 let _ = writeln!(
221 output,
222 " lamports: {}",
223 acc.compressed_account.lamports
224 );
225 if let Some(ref acc_data) = acc.compressed_account.data {
226 let _ = writeln!(output, " data_hash: {:?}", acc_data.data_hash);
227 let _ = writeln!(output, " discriminator: {:?}", acc_data.discriminator);
228 let _ = writeln!(
229 output,
230 " data ({} bytes): {:?}",
231 acc_data.data.len(),
232 acc_data.data
233 );
234 }
235 let tree_idx = Some(acc.merkle_tree_index);
236 let (tree_pubkey, _) = resolve_tree_and_queue_pubkeys(instruction_accounts, tree_idx, None);
237 if let Some(tp) = tree_pubkey {
238 let _ = writeln!(
239 output,
240 " merkle_tree_pubkey (index {}): {}",
241 acc.merkle_tree_index, tp
242 );
243 }
244 }
245}
246
247#[cfg(not(target_os = "solana"))]
251fn format_new_address_params_section(
252 output: &mut String,
253 params: &[light_compressed_account::instruction_data::data::NewAddressParamsPacked],
254 instruction_accounts: &[AccountMeta],
255) {
256 use std::fmt::Write;
257
258 if params.is_empty() {
259 return;
260 }
261
262 let _ = writeln!(output, "New Addresses ({}):", params.len());
263 for (i, param) in params.iter().enumerate() {
264 let _ = writeln!(output, " [{}] seed: {:?}", i, param.seed);
265 let tree_idx = Some(param.address_merkle_tree_account_index);
266 let queue_idx = Some(param.address_queue_account_index);
267 let (tree_pubkey, queue_pubkey) =
268 resolve_tree_and_queue_pubkeys(instruction_accounts, tree_idx, queue_idx);
269 if let Some(qp) = queue_pubkey {
270 let _ = writeln!(
271 output,
272 " queue[{}]: {}",
273 param.address_queue_account_index, qp
274 );
275 }
276 if let Some(tp) = tree_pubkey {
277 let _ = writeln!(
278 output,
279 " tree[{}]: {}",
280 param.address_merkle_tree_account_index, tp
281 );
282 }
283 }
284}
285
286#[cfg(not(target_os = "solana"))]
290fn format_new_address_params_assigned_section(
291 output: &mut String,
292 params: &[light_compressed_account::instruction_data::data::NewAddressParamsAssignedPacked],
293 instruction_accounts: &[AccountMeta],
294) {
295 use std::fmt::Write;
296
297 if params.is_empty() {
298 return;
299 }
300
301 let _ = writeln!(output, "New Addresses ({}):", params.len());
302 for (i, param) in params.iter().enumerate() {
303 let _ = writeln!(output, " [{}] seed: {:?}", i, param.seed);
304 let tree_idx = Some(param.address_merkle_tree_account_index);
305 let queue_idx = Some(param.address_queue_account_index);
306 let (tree_pubkey, queue_pubkey) =
307 resolve_tree_and_queue_pubkeys(instruction_accounts, tree_idx, queue_idx);
308 if let Some(qp) = queue_pubkey {
309 let _ = writeln!(
310 output,
311 " queue[{}]: {}",
312 param.address_queue_account_index, qp
313 );
314 }
315 if let Some(tp) = tree_pubkey {
316 let _ = writeln!(
317 output,
318 " tree[{}]: {}",
319 param.address_merkle_tree_account_index, tp
320 );
321 }
322 let assigned = if param.assigned_to_account {
323 format!("account[{}]", param.assigned_account_index)
324 } else {
325 "None".to_string()
326 };
327 let _ = writeln!(output, " assigned: {}", assigned);
328 }
329}
330
331#[cfg(not(target_os = "solana"))]
335fn format_read_only_addresses_section(
336 output: &mut String,
337 addresses: &[light_compressed_account::instruction_data::data::PackedReadOnlyAddress],
338 instruction_accounts: &[AccountMeta],
339) {
340 use std::fmt::Write;
341
342 if addresses.is_empty() {
343 return;
344 }
345
346 let _ = writeln!(output, "Read-Only Addresses ({}):", addresses.len());
347 for (i, addr) in addresses.iter().enumerate() {
348 let _ = writeln!(output, " [{}] address: {:?}", i, addr.address);
349 let tree_idx = Some(addr.address_merkle_tree_account_index);
350 let (tree_pubkey, _) = resolve_tree_and_queue_pubkeys(instruction_accounts, tree_idx, None);
351 if let Some(tp) = tree_pubkey {
352 let _ = writeln!(
353 output,
354 " tree[{}]: {}",
355 addr.address_merkle_tree_account_index, tp
356 );
357 }
358 }
359}
360
361#[cfg(not(target_os = "solana"))]
363fn format_fee_section(
364 output: &mut String,
365 compress_or_decompress_lamports: Option<u64>,
366 is_compress: bool,
367 relay_fee: Option<u64>,
368) {
369 use std::fmt::Write;
370
371 if let Some(lamports) = compress_or_decompress_lamports {
372 let _ = writeln!(
373 output,
374 "Compress/Decompress: {} lamports (is_compress: {})",
375 lamports, is_compress
376 );
377 }
378
379 if let Some(fee) = relay_fee {
380 let _ = writeln!(output, "Relay fee: {} lamports", fee);
381 }
382}
383
384#[cfg(not(target_os = "solana"))]
388fn format_compress_decompress_section(
389 output: &mut String,
390 compress_or_decompress_lamports: u64,
391 is_compress: bool,
392) {
393 use std::fmt::Write;
394
395 if compress_or_decompress_lamports > 0 {
396 let _ = writeln!(
397 output,
398 "Compress/Decompress: {} lamports (is_compress: {})",
399 compress_or_decompress_lamports, is_compress
400 );
401 }
402}
403
404#[cfg(not(target_os = "solana"))]
408fn format_account_infos_section(
409 output: &mut String,
410 account_infos: &[light_compressed_account::instruction_data::with_account_info::CompressedAccountInfo],
411 instruction_accounts: &[AccountMeta],
412) {
413 use std::fmt::Write;
414
415 if account_infos.is_empty() {
416 return;
417 }
418
419 let _ = writeln!(output, "Account Infos ({}):", account_infos.len());
420 for (i, account_info) in account_infos.iter().enumerate() {
421 let _ = writeln!(output, " [{}]", i);
422 if let Some(addr) = account_info.address {
423 let _ = writeln!(output, " address: {:?}", addr);
424 }
425
426 if let Some(ref input) = account_info.input {
427 let _ = writeln!(output, " Input:");
428 let _ = writeln!(output, " lamports: {}", input.lamports);
429 let _ = writeln!(output, " data_hash: {:?}", input.data_hash);
430 let _ = writeln!(output, " discriminator: {:?}", input.discriminator);
431 let _ = writeln!(
432 output,
433 " leaf_index: {}",
434 input.merkle_context.leaf_index
435 );
436 let _ = writeln!(output, " root_index: {}", input.root_index);
437 }
438
439 if let Some(ref out) = account_info.output {
440 let _ = writeln!(output, " Output:");
441 let _ = writeln!(output, " lamports: {}", out.lamports);
442 let _ = writeln!(output, " data_hash: {:?}", out.data_hash);
443 let _ = writeln!(output, " discriminator: {:?}", out.discriminator);
444 if !out.data.is_empty() {
445 let _ = writeln!(
446 output,
447 " data ({} bytes): {:?}",
448 out.data.len(),
449 out.data
450 );
451 }
452 let tree_idx = Some(out.output_merkle_tree_index);
453 let (tree_pubkey, _) =
454 resolve_tree_and_queue_pubkeys(instruction_accounts, tree_idx, None);
455 if let Some(tp) = tree_pubkey {
456 let _ = writeln!(
457 output,
458 " merkle_tree_pubkey (index {}): {}",
459 out.output_merkle_tree_index, tp
460 );
461 }
462 }
463 }
464}
465
466fn resolve_tree_and_queue_pubkeys(
469 accounts: &[AccountMeta],
470 merkle_tree_index: Option<u8>,
471 nullifier_queue_index: Option<u8>,
472) -> (Option<Pubkey>, Option<Pubkey>) {
473 let mut tree_pubkey = None;
474 let mut queue_pubkey = None;
475
476 let mut system_program_pos = None;
478 for (i, account) in accounts.iter().enumerate() {
479 if account.pubkey.to_string() == SYSTEM_PROGRAM_ID {
480 system_program_pos = Some(i);
481 break;
482 }
483 }
484
485 if let Some(system_pos) = system_program_pos {
486 let tree_accounts_start = system_pos + 2;
488
489 if let Some(tree_idx) = merkle_tree_index {
490 let tree_account_pos = tree_accounts_start + tree_idx as usize;
491 if tree_account_pos < accounts.len() {
492 tree_pubkey = Some(accounts[tree_account_pos].pubkey);
493 }
494 }
495
496 if let Some(queue_idx) = nullifier_queue_index {
497 let queue_account_pos = tree_accounts_start + queue_idx as usize;
498 if queue_account_pos < accounts.len() {
499 queue_pubkey = Some(accounts[queue_account_pos].pubkey);
500 }
501 }
502 }
503
504 (tree_pubkey, queue_pubkey)
505}
506
507#[cfg(not(target_os = "solana"))]
511pub fn format_invoke_cpi_readonly(
512 data: &InstructionDataInvokeCpiWithReadOnly,
513 accounts: &[AccountMeta],
514) -> String {
515 use std::fmt::Write;
516 let mut output = String::new();
517
518 let _ = writeln!(
519 output,
520 "Accounts: in: {}, out: {}",
521 data.input_compressed_accounts.len(),
522 data.output_compressed_accounts.len()
523 );
524 let _ = writeln!(output, "Proof: Validity proof");
525
526 format_readonly_input_accounts_section(
527 &mut output,
528 &data.input_compressed_accounts,
529 &data.invoking_program_id,
530 accounts,
531 );
532 format_readonly_output_accounts_section(
533 &mut output,
534 &data.output_compressed_accounts,
535 &data.invoking_program_id,
536 accounts,
537 );
538 format_new_address_params_assigned_section(&mut output, &data.new_address_params, accounts);
539 format_read_only_addresses_section(&mut output, &data.read_only_addresses, accounts);
540 format_compress_decompress_section(
541 &mut output,
542 data.compress_or_decompress_lamports,
543 data.is_compress,
544 );
545
546 output
547}
548
549#[cfg(not(target_os = "solana"))]
562pub fn resolve_invoke_cpi_readonly_account_names(
563 data: &InstructionDataInvokeCpiWithReadOnly,
564 accounts: &[AccountMeta],
565) -> Vec<String> {
566 use std::collections::HashMap;
567
568 let mut names = Vec::with_capacity(accounts.len());
569 let mut idx = 0;
570 let mut known_pubkeys: HashMap<[u8; 32], String> = HashMap::new();
571
572 let mut add_name = |name: &str,
573 accounts: &[AccountMeta],
574 idx: &mut usize,
575 known: &mut HashMap<[u8; 32], String>| {
576 if *idx < accounts.len() {
577 names.push(name.to_string());
578 known.insert(accounts[*idx].pubkey.to_bytes(), name.to_string());
579 *idx += 1;
580 true
581 } else {
582 false
583 }
584 };
585
586 let cpi_context_write_mode = data.cpi_context.set_context || data.cpi_context.first_set_context;
588
589 if cpi_context_write_mode {
590 add_name("fee_payer", accounts, &mut idx, &mut known_pubkeys);
592 add_name("cpi_authority_pda", accounts, &mut idx, &mut known_pubkeys);
593 add_name("cpi_context", accounts, &mut idx, &mut known_pubkeys);
594 return names;
595 }
596
597 add_name("fee_payer", accounts, &mut idx, &mut known_pubkeys);
599 add_name("authority", accounts, &mut idx, &mut known_pubkeys);
600 add_name(
601 "registered_program_pda",
602 accounts,
603 &mut idx,
604 &mut known_pubkeys,
605 );
606 add_name(
607 "account_compression_authority",
608 accounts,
609 &mut idx,
610 &mut known_pubkeys,
611 );
612 add_name(
613 "account_compression_program",
614 accounts,
615 &mut idx,
616 &mut known_pubkeys,
617 );
618 add_name("system_program", accounts, &mut idx, &mut known_pubkeys);
619
620 names
623}
624
625#[cfg(not(target_os = "solana"))]
629pub fn format_invoke_cpi_account_info(
630 data: &InstructionDataInvokeCpiWithAccountInfo,
631 accounts: &[AccountMeta],
632) -> String {
633 use std::fmt::Write;
634 let mut output = String::new();
635
636 let input_count = data
637 .account_infos
638 .iter()
639 .filter(|a| a.input.is_some())
640 .count();
641 let output_count = data
642 .account_infos
643 .iter()
644 .filter(|a| a.output.is_some())
645 .count();
646
647 let _ = writeln!(
648 output,
649 "Accounts: in: {}, out: {}",
650 input_count, output_count
651 );
652 let _ = writeln!(output, "Proof: Validity proof");
653
654 format_account_infos_section(&mut output, &data.account_infos, accounts);
656
657 format_new_address_params_assigned_section(&mut output, &data.new_address_params, accounts);
658 format_read_only_addresses_section(&mut output, &data.read_only_addresses, accounts);
659 format_compress_decompress_section(
660 &mut output,
661 data.compress_or_decompress_lamports,
662 data.is_compress,
663 );
664
665 output
666}
667
668#[cfg(not(target_os = "solana"))]
681pub fn resolve_invoke_cpi_account_info_account_names(
682 data: &InstructionDataInvokeCpiWithAccountInfo,
683 accounts: &[AccountMeta],
684) -> Vec<String> {
685 use std::collections::HashMap;
686
687 let mut names = Vec::with_capacity(accounts.len());
688 let mut idx = 0;
689 let mut known_pubkeys: HashMap<[u8; 32], String> = HashMap::new();
690
691 let mut add_name = |name: &str,
692 accounts: &[AccountMeta],
693 idx: &mut usize,
694 known: &mut HashMap<[u8; 32], String>| {
695 if *idx < accounts.len() {
696 names.push(name.to_string());
697 known.insert(accounts[*idx].pubkey.to_bytes(), name.to_string());
698 *idx += 1;
699 true
700 } else {
701 false
702 }
703 };
704
705 let cpi_context_write_mode = data.cpi_context.set_context || data.cpi_context.first_set_context;
707
708 if cpi_context_write_mode {
709 add_name("fee_payer", accounts, &mut idx, &mut known_pubkeys);
711 add_name("cpi_authority_pda", accounts, &mut idx, &mut known_pubkeys);
712 add_name("cpi_context", accounts, &mut idx, &mut known_pubkeys);
713 return names;
714 }
715
716 add_name("fee_payer", accounts, &mut idx, &mut known_pubkeys);
718 add_name("authority", accounts, &mut idx, &mut known_pubkeys);
719 add_name(
720 "registered_program_pda",
721 accounts,
722 &mut idx,
723 &mut known_pubkeys,
724 );
725 add_name(
726 "account_compression_authority",
727 accounts,
728 &mut idx,
729 &mut known_pubkeys,
730 );
731 add_name(
732 "account_compression_program",
733 accounts,
734 &mut idx,
735 &mut known_pubkeys,
736 );
737 add_name("system_program", accounts, &mut idx, &mut known_pubkeys);
738
739 names
742}
743
744#[derive(Debug)]
750pub struct InvokeWrapper(pub InstructionDataInvoke);
751
752impl BorshDeserialize for InvokeWrapper {
753 fn deserialize_reader<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
754 let mut prefix = [0u8; 4];
756 reader.read_exact(&mut prefix)?;
757 let inner = InstructionDataInvoke::deserialize_reader(reader)?;
759 Ok(InvokeWrapper(inner))
760 }
761}
762
763#[derive(Debug)]
765pub struct InvokeCpiWrapper(pub InstructionDataInvokeCpi);
766
767impl BorshDeserialize for InvokeCpiWrapper {
768 fn deserialize_reader<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
769 let mut prefix = [0u8; 4];
771 reader.read_exact(&mut prefix)?;
772 let inner = InstructionDataInvokeCpi::deserialize_reader(reader)?;
774 Ok(InvokeCpiWrapper(inner))
775 }
776}
777
778#[cfg(not(target_os = "solana"))]
780pub fn format_invoke_wrapper(data: &InvokeWrapper, accounts: &[AccountMeta]) -> String {
781 format_invoke_inner(&data.0, accounts)
783}
784
785#[cfg(not(target_os = "solana"))]
787pub fn format_invoke_cpi_wrapper(data: &InvokeCpiWrapper, accounts: &[AccountMeta]) -> String {
788 format_invoke_cpi_inner(&data.0, accounts)
790}
791
792#[cfg(not(target_os = "solana"))]
794fn format_invoke_inner(data: &InstructionDataInvoke, accounts: &[AccountMeta]) -> String {
795 use std::fmt::Write;
796 let mut output = String::new();
797
798 let _ = writeln!(
799 output,
800 "Accounts: in: {}, out: {}",
801 data.input_compressed_accounts_with_merkle_context.len(),
802 data.output_compressed_accounts.len()
803 );
804
805 if data.proof.is_some() {
806 let _ = writeln!(output, "Proof: Validity proof");
807 }
808
809 format_input_accounts_section(
810 &mut output,
811 &data.input_compressed_accounts_with_merkle_context,
812 accounts,
813 );
814 format_output_accounts_section(&mut output, &data.output_compressed_accounts, accounts);
815 format_new_address_params_section(&mut output, &data.new_address_params, accounts);
816 format_fee_section(
817 &mut output,
818 data.compress_or_decompress_lamports,
819 data.is_compress,
820 data.relay_fee,
821 );
822
823 output
824}
825
826#[cfg(not(target_os = "solana"))]
828fn format_invoke_cpi_inner(data: &InstructionDataInvokeCpi, accounts: &[AccountMeta]) -> String {
829 use std::fmt::Write;
830 let mut output = String::new();
831
832 let _ = writeln!(
833 output,
834 "Accounts: in: {}, out: {}",
835 data.input_compressed_accounts_with_merkle_context.len(),
836 data.output_compressed_accounts.len()
837 );
838
839 if data.proof.is_some() {
840 let _ = writeln!(output, "Proof: Validity proof");
841 }
842
843 format_input_accounts_section(
844 &mut output,
845 &data.input_compressed_accounts_with_merkle_context,
846 accounts,
847 );
848 format_output_accounts_section(&mut output, &data.output_compressed_accounts, accounts);
849 format_new_address_params_section(&mut output, &data.new_address_params, accounts);
850 format_fee_section(
851 &mut output,
852 data.compress_or_decompress_lamports,
853 data.is_compress,
854 data.relay_fee,
855 );
856
857 output
858}
859
860#[derive(InstructionDecoder)]
865#[instruction_decoder(
866 program_id = "SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7",
867 program_name = "Light System Program",
868 discriminator_size = 8
869)]
870pub enum LightSystemInstruction {
871 #[discriminator(26, 16, 169, 7, 21, 202, 242, 25)]
874 #[instruction_decoder(
875 account_names = ["fee_payer", "authority", "registered_program_pda", "log_program", "account_compression_authority", "account_compression_program", "self_program"],
876 params = InvokeWrapper,
877 pretty_formatter = crate::programs::light_system::format_invoke_wrapper
878 )]
879 Invoke,
880
881 #[discriminator(49, 212, 191, 129, 39, 194, 43, 196)]
884 #[instruction_decoder(
885 account_names = ["fee_payer", "authority", "registered_program_pda", "log_program", "account_compression_authority", "account_compression_program", "invoking_program", "cpi_signer"],
886 params = InvokeCpiWrapper,
887 pretty_formatter = crate::programs::light_system::format_invoke_cpi_wrapper
888 )]
889 InvokeCpi,
890
891 #[discriminator(86, 47, 163, 166, 21, 223, 92, 8)]
895 #[instruction_decoder(
896 params = InstructionDataInvokeCpiWithReadOnly,
897 account_names_resolver_from_params = crate::programs::light_system::resolve_invoke_cpi_readonly_account_names,
898 pretty_formatter = crate::programs::light_system::format_invoke_cpi_readonly
899 )]
900 InvokeCpiWithReadOnly,
901
902 #[discriminator(228, 34, 128, 84, 47, 139, 86, 240)]
906 #[instruction_decoder(
907 params = InstructionDataInvokeCpiWithAccountInfo,
908 account_names_resolver_from_params = crate::programs::light_system::resolve_invoke_cpi_account_info_account_names,
909 pretty_formatter = crate::programs::light_system::format_invoke_cpi_account_info
910 )]
911 InvokeCpiWithAccountInfo,
912}