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