/ adl / cli / commands / query / 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  use adl_ast::NetworkName;
 18  use adl_errors::UtilError;
 19  use adl_package::{fetch_from_network, verify_valid_program};
 20  
 21  use super::*;
 22  
 23  mod block;
 24  pub use block::AdlBlock;
 25  
 26  mod program;
 27  pub use program::AdlProgram;
 28  
 29  mod state_root;
 30  pub use state_root::StateRoot;
 31  
 32  mod committee;
 33  pub use committee::AdlCommittee;
 34  
 35  mod mempool;
 36  pub use mempool::AdlMempool;
 37  
 38  mod peers;
 39  pub use peers::AdlPeers;
 40  
 41  mod transaction;
 42  pub use transaction::AdlTransaction;
 43  
 44  mod utils;
 45  use utils::*;
 46  
 47  ///  Query live data from the Alpha network.
 48  #[derive(Parser, Debug)]
 49  pub struct AdlQuery {
 50      #[clap(flatten)]
 51      pub(crate) env_override: EnvOptions,
 52      #[clap(subcommand)]
 53      pub command: QueryCommands,
 54  }
 55  
 56  impl Command for AdlQuery {
 57      type Input = ();
 58      type Output = String;
 59  
 60      fn log_span(&self) -> Span {
 61          tracing::span!(tracing::Level::INFO, "Adl")
 62      }
 63  
 64      fn prelude(&self, _context: Context) -> Result<Self::Input> {
 65          Ok(())
 66      }
 67  
 68      fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
 69          // Parse the network.
 70          let network: NetworkName = get_network(&self.env_override.network)?;
 71          let endpoint = get_endpoint(&self.env_override.endpoint)?;
 72          handle_query(self, context, network, &endpoint)
 73      }
 74  }
 75  
 76  // A helper function to handle the `query` command.
 77  fn handle_query(
 78      query: AdlQuery,
 79      context: Context,
 80      network: NetworkName,
 81      endpoint: &str,
 82  ) -> Result<<AdlQuery as Command>::Output> {
 83      let recursive = context.recursive;
 84      let (program, output) = match query.command {
 85          QueryCommands::Block { command } => (None, command.apply(context, ())?),
 86          QueryCommands::Transaction { command } => (None, command.apply(context, ())?),
 87          QueryCommands::Program { command } => {
 88              // Check if querying for program source code.
 89              let program =
 90                  if command.mappings || command.mapping_value.is_some() { None } else { Some(command.name.clone()) };
 91              (program, command.apply(context, ())?)
 92          }
 93          QueryCommands::Stateroot { command } => (None, command.apply(context, ())?),
 94          QueryCommands::Committee { command } => (None, command.apply(context, ())?),
 95          QueryCommands::Mempool { command } => {
 96              if endpoint == "https://api.explorer.provable.com/v1" {
 97                  tracing::warn!(
 98                      "⚠️  `adl query mempool` is only valid when using a custom endpoint. Specify one using `--endpoint`."
 99                  );
100              }
101              (None, command.apply(context, ())?)
102          }
103          QueryCommands::Peers { command } => {
104              if endpoint == "https://api.explorer.provable.com/v1" {
105                  tracing::warn!(
106                      "⚠️  `adl query peers` is only valid when using a custom endpoint. Specify one using `--endpoint`."
107                  );
108              }
109              (None, command.apply(context, ())?)
110          }
111      };
112  
113      // Make GET request to retrieve on-chain state.
114      let url = format!("{endpoint}/{network}/{output}");
115      let result = fetch_from_network(&url)?;
116      if !recursive {
117          tracing::info!("✅ Successfully retrieved data from '{url}'.\n");
118          println!("{result}\n");
119      }
120  
121      // Verify that the source file parses into a valid Alpha program.
122      if let Some(name) = program {
123          verify_valid_program(&name, &result)?;
124      }
125  
126      Ok(result)
127  }
128  
129  #[derive(Parser, Debug)]
130  pub enum QueryCommands {
131      #[clap(about = "Query block information")]
132      Block {
133          #[clap(flatten)]
134          command: AdlBlock,
135      },
136      #[clap(about = "Query transaction information")]
137      Transaction {
138          #[clap(flatten)]
139          command: AdlTransaction,
140      },
141      #[clap(about = "Query program source code and live mapping values")]
142      Program {
143          #[clap(flatten)]
144          command: AdlProgram,
145      },
146      #[clap(about = "Query the latest stateroot")]
147      Stateroot {
148          #[clap(flatten)]
149          command: StateRoot,
150      },
151      #[clap(about = "Query the current committee")]
152      Committee {
153          #[clap(flatten)]
154          command: AdlCommittee,
155      },
156      #[clap(about = "Query transactions and transmissions from the memory pool")]
157      Mempool {
158          #[clap(flatten)]
159          command: AdlMempool,
160      },
161      #[clap(about = "Query peer information")]
162      Peers {
163          #[clap(flatten)]
164          command: AdlPeers,
165      },
166  }