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