hermes_cli/commands/connection/
create.rs

1use std::time::Duration;
2
3use hermes_cli_components::traits::build::CanLoadBuilder;
4use hermes_cli_framework::command::CommandRunner;
5use hermes_cli_framework::output::Output;
6use hermes_cosmos_chain_components::types::connection::CosmosInitConnectionOptions;
7use hermes_relayer_components::build::traits::builders::relay_builder::CanBuildRelay;
8use hermes_relayer_components::multi::types::index::Twindex;
9use hermes_relayer_components::relay::impls::connection::bootstrap::CanBootstrapConnection;
10use ibc_relayer_types::core::ics03_connection::version::Version;
11use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ClientId};
12use oneline_eyre::eyre::eyre;
13use tracing::info;
14
15use crate::contexts::app::HermesApp;
16use crate::Result;
17
18#[derive(Debug, clap::Parser)]
19pub struct ConnectionCreate {
20    /// Identifier of chain A
21    #[clap(
22        long = "chain-a",
23        required = true,
24        value_name = "CHAIN_ID_A",
25        help_heading = "REQUIRED"
26    )]
27    chain_id_a: ChainId,
28
29    /// Identifier of client A
30    #[clap(
31        long = "client-a",
32        required = true,
33        value_name = "CLIENT_ID_A",
34        help_heading = "REQUIRED"
35    )]
36    client_id_a: ClientId,
37
38    /// Identifier of chain B
39    #[clap(
40        long = "chain-b",
41        required = true,
42        value_name = "CHAIN_ID_B",
43        help_heading = "REQUIRED"
44    )]
45    chain_id_b: ChainId,
46
47    /// Identifier of client B
48    #[clap(
49        long = "client-b",
50        required = true,
51        value_name = "CLIENT_ID_B",
52        help_heading = "REQUIRED"
53    )]
54    client_id_b: ClientId,
55}
56
57impl CommandRunner<HermesApp> for ConnectionCreate {
58    async fn run(&self, app: &HermesApp) -> Result<Output> {
59        let builder = app.load_builder().await?;
60
61        let relay = builder
62            .build_relay(
63                Twindex::<0, 1>,
64                &self.chain_id_a,
65                &self.chain_id_b,
66                &self.client_id_a,
67                &self.client_id_b,
68            )
69            .await
70            .map_err(|e| eyre!("Failed to build relay: {e}"))?;
71
72        let options = CosmosInitConnectionOptions {
73            delay_period: Duration::from_secs(0),
74            connection_version: Version::default(),
75        };
76
77        info!(
78            ?options,
79            "Creating connection between {}:{} and {}:{}...",
80            self.chain_id_a,
81            self.client_id_a,
82            self.chain_id_b,
83            self.client_id_b
84        );
85
86        let (connection_id_a, connection_id_b) = relay
87            .bootstrap_connection(&options)
88            .await
89            .map_err(|e| eyre!("Failed to create connection: connection handshake failed: {e}"))?;
90
91        info!(
92            %connection_id_a, %connection_id_b,
93            "Connection successfully created between {}:{} and {}:{}",
94            self.chain_id_a, self.client_id_a, self.chain_id_b, self.client_id_b
95        );
96
97        Ok(Output::success_msg("Done"))
98    }
99}