1use crate::cli::{commands::*, context::*, helpers::*};
18use clap::Parser;
19use leo_errors::Result;
20use std::{path::PathBuf, process::exit};
21
22#[derive(Parser, Debug)]
24#[clap(name = "leo", author = "The Leo Team <leo@provable.com>", version)]
25pub struct CLI {
26 #[clap(short, global = true, help = "Print additional information for debugging")]
27 debug: bool,
28
29 #[clap(short, global = true, help = "Suppress CLI output")]
30 quiet: bool,
31
32 #[clap(long, global = true, help = "Disable Leo's daily check for version updates")]
33 disable_update_check: bool,
34
35 #[clap(subcommand)]
36 command: Commands,
37
38 #[clap(long, global = true, help = "Path to Leo program root folder")]
39 path: Option<PathBuf>,
40
41 #[clap(long, global = true, help = "Path to aleo program registry")]
42 pub home: Option<PathBuf>,
43}
44
45#[derive(Parser, Debug)]
47enum Commands {
48 #[clap(about = "Create a new Aleo account, sign and verify messages")]
49 Account {
50 #[clap(subcommand)]
51 command: Account,
52 },
53 #[clap(about = "Create a new Leo package in a new directory")]
54 New {
55 #[clap(flatten)]
56 command: LeoNew,
57 },
58 #[clap(about = "Run a program with input variables", visible_alias = "r")]
59 Run {
60 #[clap(flatten)]
61 command: LeoRun,
62 },
63 #[clap(about = "Test a Leo program", visible_alias = "t")]
64 Test {
65 #[clap(flatten)]
66 command: LeoTest,
67 },
68 #[clap(about = "Execute a program with input variables")]
69 Execute {
70 #[clap(flatten)]
71 command: LeoExecute,
72 },
73 #[clap(about = "Deploy a program")]
74 Deploy {
75 #[clap(flatten)]
76 command: LeoDeploy,
77 },
78 #[clap(about = "Run a local devnet")]
79 Devnet {
80 #[clap(flatten)]
81 command: LeoDevnet,
82 },
83 #[clap(about = "Query live data from the Aleo network")]
84 Query {
85 #[clap(flatten)]
86 command: LeoQuery,
87 },
88 #[clap(about = "Compile the current package as a program", visible_alias = "b")]
89 Build {
90 #[clap(flatten)]
91 command: LeoBuild,
92 },
93 #[clap(about = "Debug the current package via the interpreter")]
94 Debug {
95 #[clap(flatten)]
96 command: LeoDebug,
97 },
98 #[clap(about = "Add a new on-chain or local dependency to the current package.")]
99 Add {
100 #[clap(flatten)]
101 command: LeoAdd,
102 },
103 #[clap(about = "Remove a dependency from the current package.")]
104 Remove {
105 #[clap(flatten)]
106 command: LeoRemove,
107 },
108 #[clap(about = "Clean the output directory")]
109 Clean {
110 #[clap(flatten)]
111 command: LeoClean,
112 },
113 #[clap(about = "Synthesize individual keys")]
114 Synthesize {
115 #[clap(flatten)]
116 command: LeoSynthesize,
117 },
118 #[clap(about = "Update the Leo CLI")]
119 Update {
120 #[clap(flatten)]
121 command: LeoUpdate,
122 },
123 #[clap(about = "Upgrade the program on a network")]
124 Upgrade {
125 #[clap(flatten)]
126 command: LeoUpgrade,
127 },
128}
129
130pub fn handle_error<T>(res: Result<T>) -> T {
131 match res {
132 Ok(t) => t,
133 Err(err) => {
134 eprintln!("{err}");
135 exit(err.exit_code());
136 }
137 }
138}
139
140pub fn run_with_args(cli: CLI) -> Result<()> {
142 if let Ok(vars) = dotenvy::dotenv_iter().map(|v| v.flatten().collect::<Vec<_>>()) {
144 if !vars.is_empty() {
145 println!("📢 Loading environment variables from a `.env` file in the directory tree.");
146 }
147 for (k, v) in vars {
148 println!(" - {k}={v}");
149 }
150 }
151 dotenvy::dotenv().ok();
153
154 if !cli.quiet {
155 logger::init_logger("leo", match cli.debug {
157 false => 1,
158 true => 2,
159 })?;
160 }
161
162 if !cli.disable_update_check
164 && let Ok(true) = updater::Updater::check_for_updates(false)
165 {
166 let _ = updater::Updater::print_cli();
167 }
168
169 let context = handle_error(Context::new(cli.path, cli.home, false));
172
173 match cli.command {
174 Commands::Add { command } => command.try_execute(context),
175 Commands::Account { command } => command.try_execute(context),
176 Commands::New { command } => command.try_execute(context),
177 Commands::Build { command } => command.try_execute(context),
178 Commands::Debug { command } => command.try_execute(context),
179 Commands::Query { command } => command.try_execute(context),
180 Commands::Clean { command } => command.try_execute(context),
181 Commands::Deploy { command } => command.try_execute(context),
182 Commands::Devnet { command } => command.try_execute(context),
183 Commands::Run { command } => command.try_execute(context),
184 Commands::Test { command } => command.try_execute(context),
185 Commands::Execute { command } => command.try_execute(context),
186 Commands::Remove { command } => command.try_execute(context),
187 Commands::Synthesize { command } => command.try_execute(context),
188 Commands::Update { command } => command.try_execute(context),
189 Commands::Upgrade { command } => command.try_execute(context),
190 }
191}
192
193#[cfg(test)]
194mod tests {
195 use crate::cli::{
196 CLI,
197 cli::{Commands, test_helpers},
198 run_with_args,
199 };
200 use leo_ast::NetworkName;
201 use leo_span::create_session_if_not_set_then;
202 use serial_test::serial;
203 use std::env::temp_dir;
204
205 #[test]
206 #[serial]
207 fn nested_network_dependency_run_test() {
208 let temp_dir = temp_dir();
210 let project_directory = temp_dir.join("nested");
211
212 test_helpers::sample_nested_package(&temp_dir);
214
215 let env_override = crate::cli::commands::EnvOptions {
217 network: Some(NetworkName::TestnetV0),
218 endpoint: Some("http://localhost:3030".to_string()),
219 ..Default::default()
220 };
221
222 let run = CLI {
224 debug: false,
225 quiet: false,
226 disable_update_check: false,
227 command: Commands::Run {
228 command: crate::cli::commands::LeoRun {
229 name: "example".to_string(),
230 inputs: vec!["1u32".to_string(), "2u32".to_string()],
231 env_override,
232 build_options: Default::default(),
233 },
234 },
235 path: Some(project_directory.clone()),
236 home: Some(temp_dir.join(".aleo")),
237 };
238
239 create_session_if_not_set_then(|_| {
240 run_with_args(run).expect("Failed to execute `leo run`");
241 });
242
243 }
248
249 #[test]
250 #[serial]
251 fn nested_local_dependency_run_test() {
252 let temp_dir = temp_dir();
254 let project_name = "grandparent";
255 let project_directory = temp_dir.join(project_name);
256
257 if project_directory.exists() {
259 std::fs::remove_dir_all(project_directory.clone()).unwrap();
260 }
261
262 test_helpers::sample_grandparent_package(&temp_dir);
264
265 let run = CLI {
267 debug: false,
268 quiet: false,
269 disable_update_check: false,
270 command: Commands::Run {
271 command: crate::cli::commands::LeoRun {
272 name: "double_wrapper_mint".to_string(),
273 inputs: vec![
274 "aleo13tngrq7506zwdxj0cxjtvp28pk937jejhne0rt4zp0z370uezuysjz2prs".to_string(),
275 "2u32".to_string(),
276 ],
277 env_override: Default::default(),
278 build_options: Default::default(),
279 },
280 },
281 path: Some(project_directory.clone()),
282 home: None,
283 };
284
285 create_session_if_not_set_then(|_| {
286 run_with_args(run).expect("Failed to execute `leo run`");
287 });
288
289 }
292
293 #[test]
294 #[serial]
295 fn relaxed_shadowing_run_test() {
296 let temp_dir = temp_dir();
298 let project_name = "outer";
299 let project_directory = temp_dir.join(project_name);
300
301 if project_directory.exists() {
303 std::fs::remove_dir_all(project_directory.clone()).unwrap();
304 }
305
306 test_helpers::sample_shadowing_package(&temp_dir);
308
309 let run = CLI {
311 debug: false,
312 quiet: false,
313 disable_update_check: false,
314 command: Commands::Run {
315 command: crate::cli::commands::LeoRun {
316 name: "inner_1_main".to_string(),
317 inputs: vec!["1u32".to_string(), "2u32".to_string()],
318 build_options: Default::default(),
319 env_override: Default::default(),
320 },
321 },
322 path: Some(project_directory.clone()),
323 home: None,
324 };
325
326 create_session_if_not_set_then(|_| {
327 run_with_args(run).expect("Failed to execute `leo run`");
328 });
329 }
330
331 #[test]
332 #[serial]
333 fn relaxed_struct_shadowing_run_test() {
334 let temp_dir = temp_dir();
336 let project_name = "outer_2";
337 let project_directory = temp_dir.join(project_name);
338
339 if project_directory.exists() {
341 std::fs::remove_dir_all(project_directory.clone()).unwrap();
342 }
343
344 test_helpers::sample_struct_shadowing_package(&temp_dir);
346
347 let run = CLI {
349 debug: false,
350 quiet: false,
351 disable_update_check: false,
352 command: Commands::Run {
353 command: crate::cli::commands::LeoRun {
354 name: "main".to_string(),
355 inputs: vec!["1u32".to_string(), "2u32".to_string()],
356 env_override: Default::default(),
357 build_options: Default::default(),
358 },
359 },
360 path: Some(project_directory.clone()),
361 home: None,
362 };
363
364 create_session_if_not_set_then(|_| {
365 run_with_args(run).expect("Failed to execute `leo run`");
366 });
367 }
368}
369
370#[cfg(test)]
371mod test_helpers {
372 use crate::cli::{CLI, DependencySource, LeoAdd, LeoNew, cli::Commands, run_with_args};
373 use leo_span::create_session_if_not_set_then;
374 use std::path::Path;
375
376 const NETWORK: &str = "testnet";
377 const ENDPOINT: &str = "https://api.explorer.provable.com/v1";
378
379 pub(crate) fn sample_nested_package(temp_dir: &Path) {
380 let name = "nested";
381
382 let project_directory = temp_dir.join(name);
384 if project_directory.exists() {
385 std::fs::remove_dir_all(project_directory.clone()).unwrap();
386 }
387
388 let new = CLI {
390 debug: false,
391 quiet: false,
392 disable_update_check: false,
393 command: Commands::New {
394 command: LeoNew {
395 name: name.to_string(),
396 network: NETWORK.to_string(),
397 endpoint: ENDPOINT.to_string(),
398 },
399 },
400 path: Some(project_directory.clone()),
401 home: None,
402 };
403
404 create_session_if_not_set_then(|_| {
405 run_with_args(new).expect("Failed to execute `leo run`");
406 });
407
408 let program_str = "
410import nested_example_layer_0.aleo;
411program nested.aleo {
412 transition example(public a: u32, b: u32) -> u32 {
413 let c: u32 = nested_example_layer_0.aleo/main(a, b);
414 return c;
415 }
416
417 @noupgrade
418 async constructor() {}
419}
420";
421 let nested_example_layer_0 = "
423import nested_example_layer_2.aleo;
424import nested_example_layer_1.aleo;
425
426program nested_example_layer_0.aleo;
427
428function main:
429 input r0 as u32.public;
430 input r1 as u32.private;
431 call nested_example_layer_1.aleo/external_function r0 r1 into r2;
432 output r2 as u32.private;
433";
434
435 let nested_example_layer_1 = "
437import nested_example_layer_2.aleo;
438
439program nested_example_layer_1.aleo;
440
441function external_function:
442 input r0 as u32.public;
443 input r1 as u32.private;
444 call nested_example_layer_2.aleo/external_nested_function r0 r1 into r2;
445 output r2 as u32.private;
446";
447
448 let nested_example_layer_2 = "
450program nested_example_layer_2.aleo;
451
452function external_nested_function:
453 input r0 as u32.public;
454 input r1 as u32.private;
455 add r0 r1 into r2;
456 output r2 as u32.private;
457";
458
459 std::fs::write(project_directory.join("src").join("main.leo"), program_str).unwrap();
461
462 let add = CLI {
464 debug: false,
465 quiet: false,
466 disable_update_check: false,
467 command: Commands::Add {
468 command: LeoAdd {
469 name: "nested_example_layer_0".to_string(),
470 source: DependencySource { local: None, network: true, edition: Some(0) },
471 clear: false,
472 dev: false,
473 },
474 },
475 path: Some(project_directory.clone()),
476 home: None,
477 };
478
479 create_session_if_not_set_then(|_| {
480 run_with_args(add).expect("Failed to execute `leo add`");
481 });
482
483 let registry = temp_dir.join(".aleo").join("registry").join("testnet");
485 std::fs::create_dir_all(®istry).unwrap();
486
487 let dir = registry.join("nested_example_layer_0").join("0");
488 std::fs::create_dir_all(&dir).unwrap();
489 std::fs::write(dir.join("nested_example_layer_0.aleo"), nested_example_layer_0).unwrap();
490
491 let dir = registry.join("nested_example_layer_1").join("0");
492 std::fs::create_dir_all(&dir).unwrap();
493 std::fs::write(dir.join("nested_example_layer_1.aleo"), nested_example_layer_1).unwrap();
494
495 let dir = registry.join("nested_example_layer_2").join("0");
496 std::fs::create_dir_all(&dir).unwrap();
497 std::fs::write(dir.join("nested_example_layer_2.aleo"), nested_example_layer_2).unwrap();
498 }
499
500 pub(crate) fn sample_grandparent_package(temp_dir: &Path) {
501 let grandparent_directory = temp_dir.join("grandparent");
502 let parent_directory = grandparent_directory.join("parent");
503 let child_directory = parent_directory.join("child");
504
505 if grandparent_directory.exists() {
506 std::fs::remove_dir_all(grandparent_directory.clone()).unwrap();
507 }
508
509 let create_grandparent_project = CLI {
511 debug: false,
512 quiet: false,
513 disable_update_check: false,
514 command: Commands::New {
515 command: LeoNew {
516 name: "grandparent".to_string(),
517 network: NETWORK.to_string(),
518 endpoint: ENDPOINT.to_string(),
519 },
520 },
521 path: Some(grandparent_directory.clone()),
522 home: None,
523 };
524
525 let create_parent_project = CLI {
526 debug: false,
527 quiet: false,
528 disable_update_check: false,
529 command: Commands::New {
530 command: LeoNew {
531 name: "parent".to_string(),
532 network: NETWORK.to_string(),
533 endpoint: ENDPOINT.to_string(),
534 },
535 },
536 path: Some(parent_directory.clone()),
537 home: None,
538 };
539
540 let create_child_project = CLI {
541 debug: false,
542 quiet: false,
543 disable_update_check: false,
544 command: Commands::New {
545 command: LeoNew {
546 name: "child".to_string(),
547 network: NETWORK.to_string(),
548 endpoint: ENDPOINT.to_string(),
549 },
550 },
551 path: Some(child_directory.clone()),
552 home: None,
553 };
554
555 let grandparent_program = "
557import child.aleo;
558import parent.aleo;
559program grandparent.aleo {
560 transition double_wrapper_mint(owner: address, val: u32) -> child.aleo/A {
561 return parent.aleo/wrapper_mint(owner, val);
562 }
563
564 @noupgrade
565 async constructor() {}
566}
567";
568 let parent_program = "
569import child.aleo;
570program parent.aleo {
571 transition wrapper_mint(owner: address, val: u32) -> child.aleo/A {
572 return child.aleo/mint(owner, val);
573 }
574
575 @noupgrade
576 async constructor() {}
577}
578";
579
580 let child_program = "
581// The 'a' program.
582program child.aleo {
583 record A {
584 owner: address,
585 val: u32,
586 }
587 transition mint(owner: address, val: u32) -> A {
588 return A {owner: owner, val: val};
589 }
590
591 @noupgrade
592 async constructor() {}
593}
594";
595
596 let add_grandparent_dependency_1 = CLI {
598 debug: false,
599 quiet: false,
600 disable_update_check: false,
601 command: Commands::Add {
602 command: LeoAdd {
603 name: "parent".to_string(),
604 source: DependencySource { local: Some(parent_directory.clone()), network: false, edition: None },
605 clear: false,
606 dev: false,
607 },
608 },
609 path: Some(grandparent_directory.clone()),
610 home: None,
611 };
612
613 let add_grandparent_dependency_2 = CLI {
614 debug: false,
615 quiet: false,
616 disable_update_check: false,
617 command: Commands::Add {
618 command: LeoAdd {
619 name: "child".to_string(),
620 source: DependencySource { local: Some(child_directory.clone()), network: false, edition: None },
621 clear: false,
622 dev: false,
623 },
624 },
625 path: Some(grandparent_directory.clone()),
626 home: None,
627 };
628
629 let add_parent_dependency = CLI {
630 debug: false,
631 quiet: false,
632 disable_update_check: false,
633 command: Commands::Add {
634 command: LeoAdd {
635 name: "child".to_string(),
636 source: DependencySource { local: Some(child_directory.clone()), network: false, edition: None },
637 clear: false,
638 dev: false,
639 },
640 },
641 path: Some(parent_directory.clone()),
642 home: None,
643 };
644
645 create_session_if_not_set_then(|_| {
647 run_with_args(create_grandparent_project).unwrap();
649 run_with_args(create_parent_project).unwrap();
650 run_with_args(create_child_project).unwrap();
651
652 std::fs::write(grandparent_directory.join("src").join("main.leo"), grandparent_program).unwrap();
654 std::fs::write(parent_directory.join("src").join("main.leo"), parent_program).unwrap();
655 std::fs::write(child_directory.join("src").join("main.leo"), child_program).unwrap();
656
657 run_with_args(add_grandparent_dependency_1).unwrap();
659 run_with_args(add_grandparent_dependency_2).unwrap();
660 run_with_args(add_parent_dependency).unwrap();
661 });
662 }
663
664 pub(crate) fn sample_shadowing_package(temp_dir: &Path) {
665 let outer_directory = temp_dir.join("outer");
666 let inner_1_directory = outer_directory.join("inner_1");
667 let inner_2_directory = outer_directory.join("inner_2");
668
669 if outer_directory.exists() {
670 std::fs::remove_dir_all(outer_directory.clone()).unwrap();
671 }
672
673 let create_outer_project = CLI {
675 debug: false,
676 quiet: false,
677 disable_update_check: false,
678 command: Commands::New {
679 command: LeoNew {
680 name: "outer".to_string(),
681 network: NETWORK.to_string(),
682 endpoint: ENDPOINT.to_string(),
683 },
684 },
685 path: Some(outer_directory.clone()),
686 home: None,
687 };
688
689 let create_inner_1_project = CLI {
690 debug: false,
691 quiet: false,
692 disable_update_check: false,
693 command: Commands::New {
694 command: LeoNew {
695 name: "inner_1".to_string(),
696 network: NETWORK.to_string(),
697 endpoint: ENDPOINT.to_string(),
698 },
699 },
700 path: Some(inner_1_directory.clone()),
701 home: None,
702 };
703
704 let create_inner_2_project = CLI {
705 debug: false,
706 quiet: false,
707 disable_update_check: false,
708 command: Commands::New {
709 command: LeoNew {
710 name: "inner_2".to_string(),
711 network: NETWORK.to_string(),
712 endpoint: ENDPOINT.to_string(),
713 },
714 },
715 path: Some(inner_2_directory.clone()),
716 home: None,
717 };
718
719 let outer_program = "import inner_1.aleo;
721import inner_2.aleo;
722program outer.aleo {
723
724 struct ex_struct {
725 arg1: u32,
726 arg2: u32,
727 }
728
729 record inner_1_record {
730 owner: address,
731 arg1: u32,
732 arg2: u32,
733 arg3: u32,
734 }
735
736 transition inner_1_main(public a: u32, b: u32) -> (inner_1.aleo/inner_1_record, inner_2.aleo/inner_1_record, inner_1_record) {
737 let c: ex_struct = ex_struct {arg1: 1u32, arg2: 1u32};
738 let rec_1:inner_1.aleo/inner_1_record = inner_1.aleo/inner_1_main(1u32,1u32, c);
739 let rec_2:inner_2.aleo/inner_1_record = inner_2.aleo/inner_1_main(1u32,1u32);
740 return (rec_1, rec_2, inner_1_record {owner: aleo14tnetva3xfvemqyg5ujzvr0qfcaxdanmgjx2wsuh2xrpvc03uc9s623ps7, arg1: 1u32, arg2: 1u32, arg3: 1u32});
741 }
742
743 @noupgrade
744 async constructor() {}
745}";
746 let inner_1_program = "program inner_1.aleo {
747 mapping inner_1_mapping: u32 => u32;
748 record inner_1_record {
749 owner: address,
750 val: u32,
751 }
752 struct ex_struct {
753 arg1: u32,
754 arg2: u32,
755 }
756 transition inner_1_main(public a: u32, b: u32, c: ex_struct) -> inner_1_record {
757 return inner_1_record {
758 owner: self.caller,
759 val: c.arg1,
760 };
761 }
762
763 @noupgrade
764 async constructor() {}
765}";
766 let inner_2_program = "program inner_2.aleo {
767 mapping inner_2_mapping: u32 => u32;
768 record inner_1_record {
769 owner: address,
770 val: u32,
771 }
772 transition inner_1_main(public a: u32, b: u32) -> inner_1_record {
773 let c: u32 = a + b;
774 return inner_1_record {
775 owner: self.caller,
776 val: a,
777 };
778 }
779
780 @noupgrade
781 async constructor() {}
782}";
783 let add_outer_dependency_1 = CLI {
785 debug: false,
786 quiet: false,
787 disable_update_check: false,
788 command: Commands::Add {
789 command: LeoAdd {
790 name: "inner_1".to_string(),
791 source: DependencySource { local: Some(inner_1_directory.clone()), network: false, edition: None },
792 clear: false,
793 dev: false,
794 },
795 },
796 path: Some(outer_directory.clone()),
797 home: None,
798 };
799
800 let add_outer_dependency_2 = CLI {
801 debug: false,
802 quiet: false,
803 disable_update_check: false,
804 command: Commands::Add {
805 command: LeoAdd {
806 name: "inner_2".to_string(),
807 source: DependencySource { local: Some(inner_2_directory.clone()), network: false, edition: None },
808 clear: false,
809 dev: false,
810 },
811 },
812 path: Some(outer_directory.clone()),
813 home: None,
814 };
815
816 create_session_if_not_set_then(|_| {
818 run_with_args(create_outer_project).unwrap();
820 run_with_args(create_inner_1_project).unwrap();
821 run_with_args(create_inner_2_project).unwrap();
822
823 std::fs::write(outer_directory.join("src").join("main.leo"), outer_program).unwrap();
825 std::fs::write(inner_1_directory.join("src").join("main.leo"), inner_1_program).unwrap();
826 std::fs::write(inner_2_directory.join("src").join("main.leo"), inner_2_program).unwrap();
827
828 run_with_args(add_outer_dependency_1).unwrap();
830 run_with_args(add_outer_dependency_2).unwrap();
831 });
832 }
833
834 pub(crate) fn sample_struct_shadowing_package(temp_dir: &Path) {
835 let outer_directory = temp_dir.join("outer_2");
836 let inner_1_directory = outer_directory.join("inner_1");
837 let inner_2_directory = outer_directory.join("inner_2");
838
839 if outer_directory.exists() {
840 std::fs::remove_dir_all(outer_directory.clone()).unwrap();
841 }
842
843 let create_outer_project = CLI {
845 debug: false,
846 quiet: false,
847 disable_update_check: false,
848 command: Commands::New {
849 command: LeoNew {
850 name: "outer_2".to_string(),
851 network: NETWORK.to_string(),
852 endpoint: ENDPOINT.to_string(),
853 },
854 },
855 path: Some(outer_directory.clone()),
856 home: None,
857 };
858
859 let create_inner_1_project = CLI {
860 debug: false,
861 quiet: false,
862 disable_update_check: false,
863 command: Commands::New {
864 command: LeoNew {
865 name: "inner_1".to_string(),
866 network: NETWORK.to_string(),
867 endpoint: ENDPOINT.to_string(),
868 },
869 },
870 path: Some(inner_1_directory.clone()),
871 home: None,
872 };
873
874 let create_inner_2_project = CLI {
875 debug: false,
876 quiet: false,
877 disable_update_check: false,
878 command: Commands::New {
879 command: LeoNew {
880 name: "inner_2".to_string(),
881 network: NETWORK.to_string(),
882 endpoint: ENDPOINT.to_string(),
883 },
884 },
885 path: Some(inner_2_directory.clone()),
886 home: None,
887 };
888
889 let outer_program = "
891import inner_1.aleo;
892import inner_2.aleo;
893program outer_2.aleo {
894 struct Foo {
895 a: u32,
896 b: u32,
897 c: Boo,
898 }
899 struct Boo {
900 a: u32,
901 b: u32,
902 }
903 struct Goo {
904 a: u32,
905 b: u32,
906 c: u32,
907 }
908 record Hello {
909 owner: address,
910 a: u32,
911 }
912 transition main(public a: u32, b: u32) -> (inner_2.aleo/Yoo, Hello) {
913 let d: Foo = inner_1.aleo/main(1u32,1u32);
914 let e: u32 = inner_1.aleo/main_2(Foo {a: a, b: b, c: Boo {a:1u32, b:1u32}});
915 let f: Boo = Boo {a:1u32, b:1u32};
916 let g: Foo = inner_2.aleo/main(1u32, 1u32);
917 inner_2.aleo/Yo_Consumer(inner_2.aleo/Yo());
918 let h: inner_2.aleo/Yoo = inner_2.aleo/Yo();
919 let i: Goo = inner_2.aleo/Goo_creator();
920 let j: Hello = Hello {owner: self.signer, a:1u32};
921
922 return (h, j);
923 }
924
925 @noupgrade
926 async constructor() {}
927}
928";
929 let inner_1_program = "program inner_1.aleo {
930 struct Foo {
931 a: u32,
932 b: u32,
933 c: Boo,
934 }
935 struct Boo {
936 a: u32,
937 b: u32,
938 }
939 transition main(public a: u32, b: u32) -> Foo {
940 return Foo {a: a, b: b, c: Boo {a:1u32, b:1u32}};
941 }
942 transition main_2(a:Foo)->u32{
943 return a.a;
944 }
945
946 @noupgrade
947 async constructor() {}
948}";
949 let inner_2_program = "program inner_2.aleo {
950 struct Foo {
951 a: u32,
952 b: u32,
953 c: Boo,
954 }
955 struct Boo {
956 a: u32,
957 b: u32,
958 }
959 record Yoo {
960 owner: address,
961 a: u32,
962 }
963 struct Goo {
964 a: u32,
965 b: u32,
966 c: u32,
967 }
968 transition main(public a: u32, b: u32) -> Foo {
969 return Foo {a: a, b: b, c: Boo {a:1u32, b:1u32}};
970 }
971 transition Yo()-> Yoo {
972 return Yoo {owner: self.signer, a:1u32};
973 }
974 transition Yo_Consumer(a: Yoo)->u32 {
975 return a.a;
976 }
977 transition Goo_creator() -> Goo {
978 return Goo {a:100u32, b:1u32, c:1u32};
979 }
980
981 @noupgrade
982 async constructor() {}
983}";
984 let add_outer_dependency_1 = CLI {
986 debug: false,
987 quiet: false,
988 disable_update_check: false,
989 command: Commands::Add {
990 command: LeoAdd {
991 name: "inner_1".to_string(),
992 source: DependencySource { local: Some(inner_1_directory.clone()), network: false, edition: None },
993 clear: false,
994 dev: false,
995 },
996 },
997 path: Some(outer_directory.clone()),
998 home: None,
999 };
1000
1001 let add_outer_dependency_2 = CLI {
1002 debug: false,
1003 quiet: false,
1004 disable_update_check: false,
1005 command: Commands::Add {
1006 command: LeoAdd {
1007 name: "inner_2".to_string(),
1008 source: DependencySource { local: Some(inner_2_directory.clone()), network: false, edition: None },
1009 clear: false,
1010 dev: false,
1011 },
1012 },
1013 path: Some(outer_directory.clone()),
1014 home: None,
1015 };
1016
1017 create_session_if_not_set_then(|_| {
1019 run_with_args(create_outer_project).unwrap();
1021 run_with_args(create_inner_1_project).unwrap();
1022 run_with_args(create_inner_2_project).unwrap();
1023
1024 std::fs::write(outer_directory.join("src").join("main.leo"), outer_program).unwrap();
1026 std::fs::write(inner_1_directory.join("src").join("main.leo"), inner_1_program).unwrap();
1027 std::fs::write(inner_2_directory.join("src").join("main.leo"), inner_2_program).unwrap();
1028
1029 run_with_args(add_outer_dependency_1).unwrap();
1031 run_with_args(add_outer_dependency_2).unwrap();
1032 });
1033 }
1034}