Skip to main content

ic_query/
lib.rs

1mod cache_file;
2mod cli;
3mod duration;
4mod hex;
5mod ic_registry;
6mod icrc;
7mod nns;
8mod output;
9mod progress;
10mod project;
11mod runtime;
12pub(crate) mod snapshot_cache;
13mod sns;
14pub mod subnet_catalog;
15mod table;
16mod text_search;
17mod token_amount;
18mod token_metadata_text;
19
20#[cfg(test)]
21mod test_support;
22
23use crate::cli::{
24    clap::{parse_matches_or_usage, passthrough_args, string_option},
25    globals::{apply_global_network, command_local_global_option, top_level_dispatch_command},
26    help::{collect_args_or_print_help, usage},
27};
28use std::ffi::OsString;
29use thiserror::Error as ThisError;
30
31const VERSION_TEXT: &str = concat!("icq ", env!("CARGO_PKG_VERSION"));
32
33///
34/// IcQueryError
35///
36#[derive(Debug, ThisError)]
37pub enum IcQueryError {
38    #[error("{0}")]
39    Usage(String),
40
41    #[error("nns: {0}")]
42    Nns(String),
43
44    #[error("icrc: {0}")]
45    Icrc(String),
46
47    #[error("sns: {0}")]
48    Sns(String),
49}
50
51/// Run the CLI from process arguments.
52pub fn run_from_env() -> Result<(), IcQueryError> {
53    run(std::env::args_os().skip(1))
54}
55
56/// Run the CLI from an argument iterator.
57pub fn run<I>(args: I) -> Result<(), IcQueryError>
58where
59    I: IntoIterator<Item = OsString>,
60{
61    let Some(args) = collect_args_or_print_help(args, usage) else {
62        return Ok(());
63    };
64    if let Some(option) = command_local_global_option(&args) {
65        return Err(IcQueryError::Usage(format!(
66            "{option} is a top-level option; put it before the command\n\n{}",
67            usage()
68        )));
69    }
70
71    let matches = parse_matches_or_usage(top_level_dispatch_command(), args, usage)
72        .map_err(IcQueryError::Usage)?;
73    if matches.get_flag("version") {
74        println!("{}", version_text());
75        return Ok(());
76    }
77    let global_network = string_option(&matches, "network");
78
79    let Some((command, subcommand_matches)) = matches.subcommand() else {
80        return Err(IcQueryError::Usage(usage()));
81    };
82    let mut tail = passthrough_args(subcommand_matches);
83    apply_global_network(command, &mut tail, global_network);
84    let tail = tail.into_iter();
85
86    match command {
87        "icrc" => icrc::run(tail).map_err(|err| IcQueryError::Icrc(err.to_string())),
88        "nns" => nns::run(tail).map_err(|err| IcQueryError::Nns(err.to_string())),
89        "sns" => sns::run(tail).map_err(|err| IcQueryError::Sns(err.to_string())),
90        _ => unreachable!("top-level dispatch command only defines known commands"),
91    }
92}
93
94#[must_use]
95pub const fn version_text() -> &'static str {
96    VERSION_TEXT
97}
98
99#[cfg(test)]
100mod tests;