Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement generic query clients CLI #519

Merged
merged 14 commits into from
Jan 14, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,8 @@ where

let elapsed = Self::duration_since(&latest_consensus_state_timestamp, current_network_time);

let has_expired = elapsed.map_or(false, |elapsed| {
Counterparty::client_state_has_expired(&client_state, elapsed)
});
let has_expired = elapsed
.is_some_and(|elapsed| Counterparty::client_state_has_expired(&client_state, elapsed));

if has_expired {
Ok(ClientStatus::Expired)
Expand Down
105 changes: 105 additions & 0 deletions crates/cli/cli-components/src/impls/commands/queries/clients.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
use core::fmt::Display;
use core::marker::PhantomData;

use cgp::prelude::*;
use hermes_logging_components::traits::has_logger::HasLogger;
use hermes_logging_components::traits::logger::CanLog;
use hermes_logging_components::types::level::LevelInfo;
use hermes_relayer_components::build::traits::builders::chain_builder::CanBuildChain;
use hermes_relayer_components::chain::traits::queries::client_state::CanQueryAllClientStatesWithLatestHeight;
use hermes_relayer_components::chain::traits::types::chain_id::HasChainIdType;
use hermes_relayer_components::chain::traits::types::client_state::HasClientStateFields;
use hermes_relayer_components::chain::traits::types::ibc::HasClientIdType;
use hermes_relayer_components::multi::traits::chain_at::HasChainTypeAt;
use hermes_relayer_components::multi::types::index::Index;

use crate::traits::build::CanLoadBuilder;
use crate::traits::command::CommandRunner;
use crate::traits::output::{CanProduceOutput, HasOutputType};
use crate::traits::parse::CanParseArg;

pub struct RunQueryClientsCommand;

#[derive(Debug, clap::Parser, HasField)]
pub struct QueryClientsArgs {
#[clap(
long = "host-chain",
required = true,
value_name = "HOST_CHAIN_ID",
help_heading = "REQUIRED",
help = "Identifier of the host chain to query"
)]
host_chain_id: String,

#[clap(
long = "reference-chain",
value_name = "REFERENCE_CHAIN_ID",
help = "Only show clients that reference this chain"
)]
reference_chain_id: Option<String>,
}

impl<App, Args, Build, Chain, Counterparty> CommandRunner<App, Args> for RunQueryClientsCommand
where
App: CanLoadBuilder<Builder = Build>
+ HasLogger
+ HasOutputType
+ CanProduceOutput<Vec<(Chain::ClientId, Counterparty::ClientState)>>
+ CanParseArg<Args, symbol!("host_chain_id"), Parsed = Chain::ChainId>
+ CanParseArg<Args, symbol!("reference_chain_id"), Parsed = Option<Counterparty::ChainId>>
+ CanRaiseError<Build::Error>
+ CanRaiseError<Chain::Error>,
Build: CanBuildChain<Index<0>, Chain = Chain> + HasChainTypeAt<Index<1>, Chain = Counterparty>,
Chain: HasChainIdType
+ HasClientIdType<Counterparty>
+ CanQueryAllClientStatesWithLatestHeight<Counterparty>,
Counterparty: HasClientIdType<Counterparty> + HasClientStateFields<Chain>,
Args: Async,
Chain::ClientId: Display,
App::Logger: CanLog<LevelInfo>,
Counterparty::ChainId: Eq,
{
async fn run_command(app: &App, args: &Args) -> Result<App::Output, App::Error> {
let builder = app.load_builder().await?;
let logger = app.logger();

let host_chain_id = app.parse_arg(args, PhantomData::<symbol!("host_chain_id")>)?;
let reference_chain_id =
app.parse_arg(args, PhantomData::<symbol!("reference_chain_id")>)?;

let chain = builder
.build_chain(PhantomData::<Index<0>>, &host_chain_id)
.await
.map_err(App::raise_error)?;

let all_client_states = chain
.query_all_client_states_with_latest_height()
.await
.map_err(App::raise_error)?
.into_iter()
.collect::<Vec<_>>();

let mut result_client_states = Vec::new();

for (client_id, client_state) in all_client_states.into_iter() {
let chain_id = Counterparty::client_state_chain_id(&client_state);

if let Some(reference_chain_id) = &reference_chain_id {
if reference_chain_id == &chain_id {
continue;
}
}

logger
.log(
&format!("- {}: {} -> {}", client_id, &host_chain_id, chain_id,),
&LevelInfo,
)
.await;

result_client_states.push((client_id, client_state));
}

Ok(app.produce_output(result_client_states))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod channel_end;
pub mod client;
pub mod client_state;
pub mod client_status;
pub mod clients;
pub mod connection;
pub mod connection_end;
pub mod consensus_state;
Expand Down
186 changes: 0 additions & 186 deletions crates/cli/cli/src/commands/query/clients.rs

This file was deleted.

8 changes: 3 additions & 5 deletions crates/cli/cli/src/commands/query/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
mod clients;
pub use clients::QueryClients;

mod connections;
pub use connections::QueryConnections;

Expand All @@ -13,6 +10,7 @@ pub use channels::QueryChannels;
mod packet;
use hermes_cli_components::impls::commands::queries::chain::QueryChainSubCommand;
use hermes_cli_components::impls::commands::queries::client::QueryClientSubCommand;
use hermes_cli_components::impls::commands::queries::clients::QueryClientsArgs;
use hermes_cli_components::impls::commands::queries::connection::QueryConnectionSubCommand;
use hermes_cli_components::impls::commands::queries::wallet::QueryWalletSubCommand;
use hermes_cli_components::traits::command::CanRunCommand;
Expand All @@ -27,7 +25,7 @@ use crate::Result;
#[derive(Debug, clap::Subcommand)]
pub enum QueryCommands {
/// Query all clients
Clients(QueryClients),
Clients(QueryClientsArgs),

/// Query all connections
Connections(QueryConnections),
Expand Down Expand Up @@ -66,7 +64,7 @@ impl CommandRunner<HermesApp> for QueryCommands {
Self::Wallet(cmd) => app.run_command(cmd).await,
Self::Chain(cmd) => app.run_command(cmd).await,
Self::Client(cmd) => app.run_command(cmd).await,
Self::Clients(cmd) => cmd.run(app).await,
Self::Clients(cmd) => app.run_command(cmd).await,
Self::Connection(cmd) => app.run_command(cmd).await,
Self::Connections(cmd) => cmd.run(app).await,
Self::Channels(cmd) => cmd.run(app).await,
Expand Down
Loading
Loading