leo_lang/cli/commands/query/
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
17use 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///  Query live data from the Aleo network.
47#[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        // Parse the network.
71        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
77// A helper function to handle the `query` command.
78fn 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            // Check if querying for program source code.
90            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    // Make GET request to retrieve on-chain state.
115    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    // Verify that the source file parses into a valid Aleo program.
123    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}