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 CLI query connection end #405

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions crates/cli/cli-components/src/impls/commands/queries/connection.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use crate::impls::commands::queries::connection_end::QueryConnectionEndArgs;
use crate::traits::command::{CanRunCommand, CommandRunner};

pub struct RunQueryConnectionSubCommand;

#[derive(Debug, clap::Subcommand)]
pub enum QueryConnectionSubCommand {
/// Query the connection end
End(QueryConnectionEndArgs),
}

impl<App> CommandRunner<App, QueryConnectionSubCommand> for RunQueryConnectionSubCommand
where
App: CanRunCommand<QueryConnectionEndArgs>,
{
async fn run_command(
app: &App,
subcommand: &QueryConnectionSubCommand,
) -> Result<App::Output, App::Error> {
match subcommand {
QueryConnectionSubCommand::End(args) => app.run_command(args).await,
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
use core::marker::PhantomData;

use cgp_core::prelude::*;
use hermes_relayer_components::build::traits::builders::chain_builder::CanBuildChain;
use hermes_relayer_components::chain::traits::queries::chain_status::CanQueryChainHeight;
use hermes_relayer_components::chain::traits::queries::connection_end::CanQueryConnectionEnd;
use hermes_relayer_components::chain::traits::types::chain_id::HasChainId;
use hermes_relayer_components::chain::traits::types::connection::HasConnectionEndType;
use hermes_relayer_components::chain::traits::types::height::HasHeightType;
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;
use crate::traits::parse::CanParseArg;

pub struct RunQueryConnectionEndCommand;

#[derive(Debug, clap::Parser, HasField)]
pub struct QueryConnectionEndArgs {
#[clap(
long = "chain",
required = true,
value_name = "CHAIN_ID",
help_heading = "REQUIRED",
help = "Identifier of the chain to query"
)]
chain_id: String,

#[clap(
long = "connection",
visible_alias = "conn",
required = true,
value_name = "CONNECTION_ID",
help_heading = "REQUIRED",
help = "Identifier of the connection to query"
)]
connection_id: String,

#[clap(
long = "height",
value_name = "HEIGHT",
help = "Height of the state to query. Leave unspecified for latest height."
)]
height: Option<String>,
}

impl<App, Args, Build, Chain, Counterparty> CommandRunner<App, Args>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The following constraints should be added to CanUseHermesApp to check that the HermesApp context indeed implements CommandRunner for the corresponding command args:

    + CanRunCommand<QueryConnectionSubCommand>
    + CanRunCommand<QueryConnectionEndArgs>

for RunQueryConnectionEndCommand
where
App: CanLoadBuilder<Builder = Build>
+ CanProduceOutput<Counterparty::ConnectionEnd>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The connection end returned from CanQueryConnectionEnd is of type Chain::ConnectionEnd. So you need to use that to produce the CLI output.

+ CanParseArg<Args, symbol!("chain_id"), Parsed = Chain::ChainId>
+ CanParseArg<Args, symbol!("connection_id"), Parsed = Chain::ConnectionId>
+ CanParseArg<Args, symbol!("height"), Parsed = Option<Chain::Height>>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to add the following wiring to HermesParserComponents to enable the parsing of the given fields.

        (QueryConnectionEndArgs, symbol!("chain_id")): ParseFromString<ChainId>,
        (QueryConnectionEndArgs, symbol!("connection_id")): ParseFromString<ConnectionId>,
        (QueryConnectionEndArgs, symbol!("height")): ParseFromOptionalString<Height>,

+ CanRaiseError<Build::Error>
+ CanRaiseError<Chain::Error>
+ CanRaiseError<String>,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We didn't raise any string error in this implementation. So the constraint can be removed.

Build: CanBuildChain<0, Chain = Chain> + HasChainTypeAt<1, Chain = Counterparty>,
Chain: CanQueryChainHeight + CanQueryConnectionEnd<Counterparty>,
Counterparty: HasHeightType + HasChainId + HasConnectionEndType<Chain>,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the constraints for Counterparty are not really needed, thus can be removed.

Args: Async,
{
async fn run_command(app: &App, args: &Args) -> Result<App::Output, App::Error> {
let chain_id = app.parse_arg(args, PhantomData::<symbol!("chain_id")>)?;
let connection_id = app.parse_arg(args, PhantomData::<symbol!("connection_id")>)?;
let m_query_height = app.parse_arg(args, PhantomData::<symbol!("height")>)?;

let builder = app.load_builder().await?;

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

let query_height = match m_query_height {
Some(query_height) => query_height,
None => chain.query_chain_height().await.map_err(App::raise_error)?,
};

let connection_end = chain
.query_connection_end(&connection_id, &query_height)
.await
.map_err(App::raise_error)?;

Ok(app.produce_output(connection_end))
}
}
2 changes: 2 additions & 0 deletions crates/cli/cli-components/src/impls/commands/queries/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
pub mod client;
pub mod client_state;
pub mod client_status;
pub mod connection;
pub mod connection_end;
pub mod consensus_state;
7 changes: 2 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 connection;
pub use connection::QueryConnection;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The corresponding files at commands/query/connection should be removed.


mod clients;
pub use clients::QueryClients;

Expand Down Expand Up @@ -41,7 +38,7 @@ pub enum QueryCommands {

/// Query connection information
#[clap(subcommand)]
Connection(QueryConnection),
Connection(QueryConnectionSubCommand),

/// Query channel information
#[clap(subcommand)]
Expand All @@ -57,7 +54,7 @@ impl CommandRunner<HermesApp> for QueryCommands {
match self {
Self::Client(cmd) => app.run_command(cmd).await,
Self::Clients(cmd) => cmd.run(app).await,
Self::Connection(cmd) => cmd.run(app).await,
Self::Connection(cmd) => app.run_command(cmd).await,
Self::Connections(cmd) => cmd.run(app).await,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to add the following wiring to HermesCommandRunnerComponents to forward the subcommand to the corresponding runners:

        QueryConnectionSubCommand: RunQueryConnectionSubCommand,
        QueryConnectionEndArgs: RunQueryConnectionEndCommand,

Self::Channels(cmd) => cmd.run(app).await,
Self::Channel(cmd) => cmd.run(app).await,
Expand Down
Loading