/ adl / cli / commands / mod.rs
mod.rs
  1  // Copyright (C) 2019-2025 Alpha-Delta Network Inc.
  2  // This file is part of the ADL library.
  3  
  4  // The ADL 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 ADL 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 ADL library. If not, see <https://www.gnu.org/licenses/>.
 16  
 17  mod add;
 18  pub use add::{AdlAdd, DependencySource};
 19  
 20  mod account;
 21  pub use account::Account;
 22  
 23  mod build;
 24  pub use build::AdlBuild;
 25  
 26  mod clean;
 27  pub use clean::AdlClean;
 28  
 29  mod common;
 30  pub use common::*;
 31  
 32  mod debug;
 33  pub use debug::AdlDebug;
 34  
 35  mod deploy;
 36  pub use deploy::AdlDeploy;
 37  use deploy::{Task, print_deployment_plan, print_deployment_stats};
 38  
 39  mod devnet;
 40  pub use devnet::AdlDevnet;
 41  
 42  mod execute;
 43  pub use execute::AdlExecute;
 44  
 45  pub mod query;
 46  pub use query::AdlQuery;
 47  
 48  mod new;
 49  pub use new::AdlNew;
 50  
 51  mod remove;
 52  pub use remove::AdlRemove;
 53  
 54  mod run;
 55  pub use run::AdlRun;
 56  
 57  mod synthesize;
 58  pub use synthesize::AdlSynthesize;
 59  
 60  mod test;
 61  pub use test::AdlTest;
 62  
 63  mod update;
 64  pub use update::AdlUpdate;
 65  
 66  pub mod upgrade;
 67  pub use upgrade::AdlUpgrade;
 68  
 69  use super::*;
 70  use crate::cli::{helpers::context::*, query::QueryCommands};
 71  
 72  use adl_errors::{CliError, Handler, PackageError, Result};
 73  use alphavm::{
 74      console::network::Network,
 75      prelude::{Address, Ciphertext, Plaintext, PrivateKey, Record, Value, ViewKey, block::Transaction},
 76  };
 77  
 78  use clap::{Args, Parser};
 79  use colored::Colorize;
 80  use dialoguer::{Confirm, theme::ColorfulTheme};
 81  use std::{iter, str::FromStr};
 82  use tracing::span::Span;
 83  use ureq::http::Uri;
 84  
 85  /// Base trait for the Adl CLI, see methods and their documentation for details.
 86  pub trait Command {
 87      /// If the current command requires running another command beforehand
 88      /// and needs its output result, this is where the result type is defined.
 89      /// Example: type Input: <CommandA as Command>::Out
 90      type Input;
 91  
 92      /// Defines the output of this command, which may be used as `Input` for another
 93      /// command. If this command is not used as a prelude for another command,
 94      /// this field may be left empty.
 95      type Output;
 96  
 97      /// Adds a span to the logger via `tracing::span`.
 98      /// Because of the specifics of the macro implementation, it is not possible
 99      /// to set the span name with a non-literal i.e. a dynamic variable even if this
100      /// variable is a &'static str.
101      fn log_span(&self) -> Span {
102          tracing::span!(tracing::Level::INFO, "Adl")
103      }
104  
105      /// Runs the prelude and returns the Input of the current command.
106      fn prelude(&self, context: Context) -> Result<Self::Input>
107      where
108          Self: std::marker::Sized;
109  
110      /// Runs the main operation of this command. This function is run within
111      /// context of 'execute' function, which sets logging and timers.
112      fn apply(self, context: Context, input: Self::Input) -> Result<Self::Output>
113      where
114          Self: std::marker::Sized;
115  
116      /// A wrapper around the `apply` method.
117      /// This function sets up tracing, timing, and the context.
118      fn execute(self, context: Context) -> Result<Self::Output>
119      where
120          Self: std::marker::Sized,
121      {
122          let input = self.prelude(context.clone())?;
123  
124          // Create the span for this command.
125          let span = self.log_span();
126          let span = span.enter();
127  
128          // Calculate the execution time for this command.
129          let out = self.apply(context, input);
130  
131          drop(span);
132  
133          out
134      }
135  
136      /// Executes command but empty the result. Comes in handy where there's a
137      /// need to make match arms compatible while keeping implementation-specific
138      /// output possible. Errors however are all of the type Error
139      fn try_execute(self, context: Context) -> Result<()>
140      where
141          Self: std::marker::Sized,
142      {
143          self.execute(context).map(|_| Ok(()))?
144      }
145  }
146  
147  /// A helper function to parse an input string into a `Value`, handling record ciphertexts as well.
148  pub fn parse_input<N: Network>(input: &str, private_key: &PrivateKey<N>) -> Result<Value<N>> {
149      // Trim whitespace from the input.
150      let input = input.trim();
151      // Check if the input is a record ciphertext.
152      if input.starts_with("record1") {
153          // Get the view key from the private key.
154          let view_key = ViewKey::<N>::try_from(private_key)
155              .map_err(|e| CliError::custom(format!("Failed to view key from the private key: {e}")))?;
156          // Parse the input as a record.
157          Record::<N, Ciphertext<N>>::from_str(input)
158              .and_then(|ciphertext| ciphertext.decrypt(&view_key))
159              .map(Value::Record)
160              .map_err(|e| CliError::custom(format!("Failed to parse input as record: {e}")).into())
161      } else {
162          Value::from_str(input).map_err(|e| CliError::custom(format!("Failed to parse input: {e}")).into())
163      }
164  }