hermes_cli_components/impls/commands/
start.rs1use 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 #[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 #[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 #[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 #[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}