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