leo_lang/cli/commands/mod.rs
1// Copyright (C) 2019-2025 Provable Inc.
2// This file is part of the Leo library.
3
4// The Leo library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// The Leo library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
16
17mod add;
18pub use add::{DependencySource, LeoAdd};
19
20mod account;
21pub use account::Account;
22
23mod build;
24pub use build::LeoBuild;
25
26mod clean;
27pub use clean::LeoClean;
28
29mod common;
30use common::*;
31
32mod debug;
33pub use debug::LeoDebug;
34
35mod deploy;
36pub use deploy::LeoDeploy;
37
38mod execute;
39pub use execute::LeoExecute;
40
41pub mod query;
42pub use query::LeoQuery;
43
44mod new;
45pub use new::LeoNew;
46
47// mod node;
48// pub use node::Node;
49
50mod remove;
51pub use remove::LeoRemove;
52
53mod run;
54pub use run::LeoRun;
55
56mod test;
57pub use test::LeoTest;
58
59mod update;
60pub use update::LeoUpdate;
61
62use super::*;
63use crate::cli::helpers::context::*;
64use leo_errors::{CliError, Handler, PackageError, Result};
65use snarkvm::prelude::{Address, Ciphertext, Plaintext, PrivateKey, Record, ViewKey, block::Transaction};
66
67use clap::{Args, Parser};
68use colored::Colorize;
69use dialoguer::{Confirm, theme::ColorfulTheme};
70use std::{iter, str::FromStr};
71use tracing::span::Span;
72
73use crate::cli::query::QueryCommands;
74use snarkvm::console::network::Network;
75
76/// Base trait for the Leo CLI, see methods and their documentation for details.
77pub trait Command {
78 /// If the current command requires running another command beforehand
79 /// and needs its output result, this is where the result type is defined.
80 /// Example: type Input: <CommandA as Command>::Out
81 type Input;
82
83 /// Defines the output of this command, which may be used as `Input` for another
84 /// command. If this command is not used as a prelude for another command,
85 /// this field may be left empty.
86 type Output;
87
88 /// Adds a span to the logger via `tracing::span`.
89 /// Because of the specifics of the macro implementation, it is not possible
90 /// to set the span name with a non-literal i.e. a dynamic variable even if this
91 /// variable is a &'static str.
92 fn log_span(&self) -> Span {
93 tracing::span!(tracing::Level::INFO, "Leo")
94 }
95
96 /// Runs the prelude and returns the Input of the current command.
97 fn prelude(&self, context: Context) -> Result<Self::Input>
98 where
99 Self: std::marker::Sized;
100
101 /// Runs the main operation of this command. This function is run within
102 /// context of 'execute' function, which sets logging and timers.
103 fn apply(self, context: Context, input: Self::Input) -> Result<Self::Output>
104 where
105 Self: std::marker::Sized;
106
107 /// A wrapper around the `apply` method.
108 /// This function sets up tracing, timing, and the context.
109 fn execute(self, context: Context) -> Result<Self::Output>
110 where
111 Self: std::marker::Sized,
112 {
113 let input = self.prelude(context.clone())?;
114
115 // Create the span for this command.
116 let span = self.log_span();
117 let span = span.enter();
118
119 // Calculate the execution time for this command.
120 let out = self.apply(context, input);
121
122 drop(span);
123
124 out
125 }
126
127 /// Executes command but empty the result. Comes in handy where there's a
128 /// need to make match arms compatible while keeping implementation-specific
129 /// output possible. Errors however are all of the type Error
130 fn try_execute(self, context: Context) -> Result<()>
131 where
132 Self: std::marker::Sized,
133 {
134 self.execute(context).map(|_| Ok(()))?
135 }
136}