use clap::{Arg, ArgMatches, Command}; use clap_complete::{generate, Shell}; use detee_cli::config::Config; use detee_cli::*; use std::io; use utils::block_on; const ABOUT: &str = r#"The DeTEE Admin CLI got created for the testnet. It allows you to: - airdrop tokens to other accounts - list all accounts - list all contracts The admin pubkeys are hardcoded in the brain."#; shadow_rs::shadow!(build); fn main() { let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); let log_level = match std::env::var("LOG_LEVEL") { Ok(val) => match val.as_str() { "DEBUG" => log::LevelFilter::Debug, "INFO" => log::LevelFilter::Info, _ => log::LevelFilter::Error, }, _ => log::LevelFilter::Warn, }; env_logger::builder().filter_level(log_level).format_timestamp(None).init(); let cmd = Command::new("super-detee-cli") .version(build::CLAP_LONG_VERSION) .author("https://detee.ltd") .about(ABOUT) .subcommand( Command::new("completion").about("generates shell completion scripts").arg( Arg::new("shell") .help("The shell to generate the script for") .value_parser(["bash", "zsh", "fish"]) .required(true), ), ) .subcommand(Command::new("contract").about("list all vm contracts")) .subcommand( Command::new("airdrop") .about("give an airdrop to a user") .arg(Arg::new("wallet").help("pubkey of the wallet").long("wallet").required(true)) .arg( Arg::new("amount") .help("the amount of token you want to airdrop") .long("amount") .value_parser(clap::value_parser!(u64).range(0..1_000_000)) .required(true), ), ) .subcommand( Command::new("slash") .about("forcefully slash a user") .arg( Arg::new("wallet") .help("pubkey of the wallet you are slashing") .long("wallet") .required(true), ) .arg( Arg::new("amount") .help("the amount of tokens you are slashing") .long("amount") .value_parser(clap::value_parser!(u64).range(0..1_000_000)) .required(true), ), ) .subcommand( Command::new("account") .about("account and security data for this CLI") .subcommand(Command::new("list").about("list all accounts that exist in the brain")) .subcommand( Command::new("show").about("show account data associated with this CLI"), ) .subcommand( Command::new("network") .about("specify if you connect to testnet or staging") .arg( Arg::new("name") .help("name of the network you are connecting to") .required(true), ), ), ); let matches = cmd.clone().get_matches(); match matches.subcommand() { Some(("completion", subcom_args)) => handle_completion(subcom_args, cmd), Some(("contract", subcom_args)) => handle_contracts(subcom_args), Some(("airdrop", subcom_args)) => handle_airdrop(subcom_args), Some(("slash", subcom_args)) => handle_slash(subcom_args), Some(("account", subcom_args)) => handle_account(subcom_args), _ => println!("No valid subcommand provided. Use --help for more information."), } } fn handle_completion(matches: &ArgMatches, mut cmd: Command) { if let Some(shell) = matches.get_one::("shell") { let shell: Shell = shell.parse().expect("Invalid shell type"); generate(shell, &mut cmd, "super-detee-cli", &mut io::stdout()); } } fn handle_account(matches: &ArgMatches) { match matches.subcommand() { Some(("show", _)) => cli_print(Ok(config::Config::get_account_data())), Some(("list", _)) => match block_on(general::grpc::admin_list_accounts()) { Ok(accounts) => { for a in accounts { println!("{} {} {}", a.pubkey, a.balance, a.tmp_locked); } } Err(e) => println!("Could not get contracts due to error: {e:?}"), }, Some(("network", path_subcommand)) => { let name: String = path_subcommand.get_one::("name").unwrap().clone(); Config::set_network(&name); } _ => cli_print(Ok(config::Config::get_account_data())), } } fn handle_contracts(_matches: &ArgMatches) { match block_on(general::grpc::admin_list_contracts()) { Ok(contracts) => { for c in contracts { println!( "{} {} {} {} {}", c.admin_pubkey, c.created_at, c.hostname, c.nano_per_minute, c.locked_nano ) } } Err(e) => println!("Could not get contracts due to error: {e:?}"), } } fn handle_airdrop(matches: &ArgMatches) { let wallet: String = matches.get_one::("wallet").unwrap().clone(); let tokens = *matches.get_one::("amount").unwrap(); match block_on(general::grpc::admin_airdrop(wallet, tokens)) { Ok(()) => println!("Success."), Err(e) => println!("Could not give airdrop due to error: {e:?}"), } } fn handle_slash(matches: &ArgMatches) { let wallet: String = matches.get_one::("wallet").unwrap().clone(); let tokens = *matches.get_one::("amount").unwrap(); match block_on(general::grpc::admin_slash(wallet, tokens)) { Ok(()) => println!("Success."), Err(e) => println!("Could not slash wallet due to error: {e:?}"), } }