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}