use hermes_cli_components::traits::build::CanLoadBuilder;
use hermes_cli_framework::command::CommandRunner;
use hermes_cli_framework::output::{json, Output};
use hermes_cosmos_chain_components::traits::chain_handle::HasBlockingChainHandle;
use hermes_cosmos_relayer::contexts::build::CosmosBuilder;
use ibc_relayer::chain::counterparty::{channel_connection_client, unreceived_acknowledgements};
use ibc_relayer::chain::requests::Paginate;
use ibc_relayer::path::PathIdentifiers;
use ibc_relayer_types::core::ics04_channel::packet::Sequence;
use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId};
use ibc_relayer_types::Height;
use oneline_eyre::eyre::eyre;
use super::util::PacketSequences;
use crate::contexts::app::HermesApp;
use crate::impls::error_wrapper::ErrorWrapper;
use crate::Result;
#[derive(Debug, clap::Parser)]
pub struct QueryPendingAcks {
#[clap(
long = "chain",
required = true,
value_name = "CHAIN_ID",
help_heading = "REQUIRED"
)]
chain_id: ChainId,
#[clap(
long = "port",
required = true,
value_name = "PORT_ID",
help_heading = "REQUIRED"
)]
port_id: PortId,
#[clap(
long = "channel",
required = true,
value_name = "CHANNEL_ID",
help_heading = "REQUIRED"
)]
channel_id: ChannelId,
}
impl QueryPendingAcks {
async fn execute(&self, builder: &CosmosBuilder) -> Result<Option<(Vec<Sequence>, Height)>> {
let port_id = self.port_id.clone();
let channel_id = self.channel_id.clone();
let chain = builder.build_chain(&self.chain_id).await?;
let chan_conn_cli = chain
.with_blocking_chain_handle(move |handle| {
let chan_conn_cli = channel_connection_client(&handle, &port_id, &channel_id)
.map_err(|e| eyre!("failed to get channel connection and client: {}", e))?;
Ok(chan_conn_cli)
})
.await?;
let counterparty_chain_id = chan_conn_cli.client.client_state.chain_id();
let counterparty_chain = builder.build_chain(&counterparty_chain_id.clone()).await?;
let channel = chan_conn_cli.channel.clone();
let path_identifiers =
PathIdentifiers::from_channel_end(channel.clone()).ok_or_else(|| {
eyre!(
"failed to get the path identifiers for channel ({}, {})",
channel.channel_id,
channel.port_id
)
})?;
unreceived_acknowledgements(
&chain.handle,
&counterparty_chain.handle,
&path_identifiers,
Paginate::All,
)
.wrap_error("failed to get the unreceived acknowledgments")
}
}
impl CommandRunner<HermesApp> for QueryPendingAcks {
async fn run(&self, app: &HermesApp) -> Result<Output> {
let builder = app.load_builder().await?;
match self.execute(&builder).await {
Err(e) => Ok(Output::error(e)),
Ok(None) => Ok(Output::success_msg("No unreceived acknowledgements")),
Ok(Some((sequences, height))) => {
let packet_sequences = PacketSequences::new(height, sequences);
if json() {
Ok(Output::success(packet_sequences))
} else {
Ok(Output::success(packet_sequences.collated()))
}
}
}
}
}