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