hermes_cli_components/impls/commands/
start.rs

1use std::marker::PhantomData;
2
3use cgp::extra::run::CanRun;
4use cgp::prelude::*;
5use hermes_error::traits::wrap::CanWrapError;
6use hermes_logging_components::traits::has_logger::HasLogger;
7use hermes_logging_components::traits::logger::CanLog;
8use hermes_logging_components::types::level::LevelInfo;
9use hermes_relayer_components::build::traits::builders::birelay_builder::CanBuildBiRelay;
10use hermes_relayer_components::chain::traits::types::ibc::HasIbcChainTypes;
11use hermes_relayer_components::multi::traits::chain_at::HasChainTypeAt;
12
13use crate::traits::build::CanLoadBuilder;
14use crate::traits::command::CommandRunner;
15use crate::traits::output::CanProduceOutput;
16use crate::traits::parse::CanParseArg;
17
18pub struct RunStartRelayerCommand;
19
20#[derive(Debug, clap::Parser, HasField)]
21pub struct StartRelayerArgs {
22    /// Identifier of chain A
23    #[clap(
24        long = "chain-a",
25        required = true,
26        value_name = "CHAIN_ID_A",
27        help_heading = "REQUIRED"
28    )]
29    chain_id_a: String,
30
31    /// Identifier of client A
32    #[clap(
33        long = "client-a",
34        required = true,
35        value_name = "CLIENT_ID_A",
36        help_heading = "REQUIRED"
37    )]
38    client_id_a: String,
39
40    /// Identifier of chain B
41    #[clap(
42        long = "chain-b",
43        required = true,
44        value_name = "CHAIN_ID_B",
45        help_heading = "REQUIRED"
46    )]
47    chain_id_b: String,
48
49    /// Identifier of client B
50    #[clap(
51        long = "client-b",
52        required = true,
53        value_name = "CLIENT_ID_B",
54        help_heading = "REQUIRED"
55    )]
56    client_id_b: String,
57}
58
59impl<App, Args, Build, BiRelay, ChainA, ChainB> CommandRunner<App, Args> for RunStartRelayerCommand
60where
61    App: CanLoadBuilder<Builder = Build>
62        + HasLogger
63        + CanProduceOutput<&'static str>
64        + CanParseArg<Args, symbol!("chain_id_a"), Parsed = ChainA::ChainId>
65        + CanParseArg<Args, symbol!("client_id_a"), Parsed = ChainA::ClientId>
66        + CanParseArg<Args, symbol!("chain_id_b"), Parsed = ChainB::ChainId>
67        + CanParseArg<Args, symbol!("client_id_b"), Parsed = ChainB::ClientId>
68        + CanRaiseError<Build::Error>
69        + CanRaiseError<BiRelay::Error>
70        + CanWrapError<&'static str>,
71    Args: Async,
72    App::Logger: CanLog<LevelInfo>,
73    Build: CanBuildBiRelay<0, 1, BiRelay = BiRelay>
74        + HasChainTypeAt<0, Chain = ChainA>
75        + HasChainTypeAt<1, Chain = ChainB>,
76    BiRelay: CanRun,
77    ChainA: HasIbcChainTypes<ChainB>,
78    ChainB: HasIbcChainTypes<ChainA>,
79{
80    async fn run_command(app: &App, args: &Args) -> Result<App::Output, App::Error> {
81        let logger = app.logger();
82        let builder = app.load_builder().await?;
83
84        let chain_id_a = app.parse_arg(args, PhantomData::<symbol!("chain_id_a")>)?;
85        let client_id_a = app.parse_arg(args, PhantomData::<symbol!("client_id_a")>)?;
86
87        let chain_id_b = app.parse_arg(args, PhantomData::<symbol!("chain_id_b")>)?;
88        let client_id_b = app.parse_arg(args, PhantomData::<symbol!("client_id_b")>)?;
89
90        let birelay = builder
91            .build_birelay(&chain_id_a, &chain_id_b, &client_id_a, &client_id_b)
92            .await
93            .map_err(App::raise_error)?;
94
95        logger
96            .log(
97                &format!("Relaying between {} and {}...", chain_id_a, chain_id_b,),
98                &LevelInfo,
99            )
100            .await;
101
102        birelay
103            .run()
104            .await
105            .map_err(|e| App::wrap_error("Relayer failed to start", App::raise_error(e)))?;
106
107        Ok(app.produce_output("Relayer exited successfully."))
108    }
109}