use alloc::collections::btree_map::BTreeMap as HashMap;
use core::fmt::Write;
use abscissa_core::clap::Parser;
use abscissa_core::{Command, Runnable};
use crate::conclude::Output;
use crate::{application::app_config, conclude::json};
use ibc_relayer::config::{ChainConfig, Config};
use ibc_relayer_types::core::ics24_host::identifier::ChainId;
#[derive(Clone, Command, Debug, Parser, PartialEq, Eq)]
pub struct KeysListCmd {
#[clap(
long = "chain",
required = true,
value_name = "CHAIN_ID",
help_heading = "REQUIRED",
help = "Identifier of the chain"
)]
chain_id: ChainId,
}
impl KeysListCmd {
fn options(&self, config: &Config) -> Result<KeysListOptions, String> {
let chain_config = config
.find_chain(&self.chain_id)
.ok_or_else(|| format!("chain '{}' not found in configuration file", self.chain_id))?;
Ok(KeysListOptions {
chain_config: chain_config.clone(),
})
}
}
impl Runnable for KeysListCmd {
fn run(&self) {
let config = app_config();
let opts = match self.options(&config) {
Err(err) => Output::error(err).exit(),
Ok(result) => result,
};
match opts.chain_config.list_keys() {
Ok(keys) if json() => {
let keys = keys.into_iter().collect::<HashMap<_, _>>();
Output::success(keys).exit()
}
Ok(keys) => {
let mut msg = String::new();
for (name, key) in keys {
let _ = write!(msg, "\n- {} ({})", name, key.account());
}
Output::success_msg(msg).exit()
}
Err(e) => Output::error(e).exit(),
}
}
}
#[derive(Clone, Debug)]
pub struct KeysListOptions {
pub chain_config: ChainConfig,
}
#[cfg(test)]
mod tests {
use super::KeysListCmd;
use abscissa_core::clap::Parser;
use ibc_relayer_types::core::ics24_host::identifier::ChainId;
#[test]
fn test_keys_list() {
assert_eq!(
KeysListCmd {
chain_id: ChainId::from_string("chain_id")
},
KeysListCmd::parse_from(["test", "--chain", "chain_id"])
)
}
#[test]
fn test_keys_list_no_chain() {
assert!(KeysListCmd::try_parse_from(["test"]).is_err())
}
}