1use core::fmt::Debug;
2use std::path::PathBuf;
3
4use cgp::core::error::{ErrorRaiserComponent, ErrorTypeComponent};
5use cgp::prelude::*;
6use hermes_any_counterparty::contexts::any_counterparty::AnyCounterparty;
7use hermes_cli_components::impls::commands::bootstrap::chain::RunBootstrapChainCommand;
8use hermes_cli_components::impls::commands::client::create::{
9 CreateClientOptionsParser, RunCreateClientCommand,
10};
11use hermes_cli_components::impls::commands::delegate::DelegateCommandRunner;
12use hermes_cli_components::impls::commands::queries::client::{
13 QueryClientSubCommand, RunQueryClientSubCommand,
14};
15use hermes_cli_components::impls::commands::queries::client_state::{
16 QueryClientStateArgs, RunQueryClientStateCommand,
17};
18use hermes_cli_components::impls::commands::queries::client_status::{
19 QueryClientStatusArgs, RunQueryClientStatusCommand,
20};
21use hermes_cli_components::impls::commands::queries::consensus_state::{
22 QueryConsensusStateArgs, RunQueryConsensusStateCommand,
23};
24use hermes_cli_components::impls::commands::start::{RunStartRelayerCommand, StartRelayerArgs};
25use hermes_cli_components::impls::config::get_config_path::GetDefaultConfigField;
26use hermes_cli_components::impls::config::load_toml_config::LoadTomlConfig;
27use hermes_cli_components::impls::config::save_toml_config::WriteTomlConfig;
28use hermes_cli_components::impls::parse::delegate::DelegateArgParsers;
29use hermes_cli_components::impls::parse::string::{ParseFromOptionalString, ParseFromString};
30use hermes_cli_components::traits::any_counterparty::ProvideAnyCounterparty;
31use hermes_cli_components::traits::bootstrap::{BootstrapLoaderComponent, ProvideBootstrapType};
32use hermes_cli_components::traits::build::{
33 BuilderLoaderComponent, CanLoadBuilder, ProvideBuilderType,
34};
35use hermes_cli_components::traits::command::{CanRunCommand, CommandRunnerComponent};
36use hermes_cli_components::traits::config::config_path::ConfigPathGetterComponent;
37use hermes_cli_components::traits::config::load_config::{CanLoadConfig, ConfigLoaderComponent};
38use hermes_cli_components::traits::config::write_config::{CanWriteConfig, ConfigWriterComponent};
39use hermes_cli_components::traits::output::{
40 CanProduceOutput, HasOutputType, OutputProducer, ProvideOutputType,
41};
42use hermes_cli_components::traits::parse::ArgParserComponent;
43use hermes_cli_components::traits::types::config::ProvideConfigType;
44use hermes_cli_framework::output::Output;
45use hermes_cosmos_integration_tests::contexts::bootstrap::CosmosBootstrap;
46use hermes_cosmos_relayer::contexts::build::CosmosBuilder;
47use hermes_cosmos_relayer::contexts::chain::CosmosChain;
48use hermes_error::traits::wrap::WrapError;
49use hermes_error::types::{Error, HermesError};
50use hermes_logger::ProvideHermesLogger;
51use hermes_logging_components::traits::has_logger::{
52 GlobalLoggerGetterComponent, LoggerGetterComponent, LoggerTypeComponent,
53};
54use hermes_relayer_components::error::traits::retry::RetryableErrorComponent;
55use hermes_runtime::types::runtime::HermesRuntime;
56use hermes_runtime_components::traits::runtime::{
57 ProvideDefaultRuntimeField, RuntimeGetterComponent, RuntimeTypeComponent,
58};
59use ibc_relayer::chain::cosmos::client::Settings;
60use ibc_relayer::config::Config;
61use ibc_relayer::foreign_client::CreateOptions;
62use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ClientId};
63use ibc_relayer_types::Height;
64use serde::Serialize;
65
66use crate::commands::bootstrap::chain::{BootstrapChainArgs, LoadCosmosBootstrap};
67use crate::commands::bootstrap::subcommand::{BootstrapSubCommand, RunBootstrapSubCommand};
68use crate::commands::client::create::CreateClientArgs;
69use crate::impls::build::LoadCosmosBuilder;
70use crate::impls::error::ProvideCliError;
71
72#[derive(HasField)]
73pub struct HermesApp {
74 pub config_path: PathBuf,
75 pub runtime: HermesRuntime,
76}
77
78pub struct HermesAppComponents;
79
80pub struct HermesParserComponents;
81
82pub struct HermesCommandRunnerComponents;
83
84impl HasComponents for HermesApp {
85 type Components = HermesAppComponents;
86}
87
88delegate_components! {
89 HermesAppComponents {
90 [
91 ErrorTypeComponent,
92 ErrorRaiserComponent,
93 RetryableErrorComponent,
94 ]:
95 ProvideCliError,
96 [
97 RuntimeTypeComponent,
98 RuntimeGetterComponent,
99 ]:
100 ProvideDefaultRuntimeField,
101 [
102 LoggerTypeComponent,
103 LoggerGetterComponent,
104 GlobalLoggerGetterComponent,
105 ]:
106 ProvideHermesLogger,
107 ConfigPathGetterComponent:
108 GetDefaultConfigField,
109 ConfigLoaderComponent:
110 LoadTomlConfig,
111 ConfigWriterComponent:
112 WriteTomlConfig,
113 BuilderLoaderComponent:
114 LoadCosmosBuilder,
115 BootstrapLoaderComponent:
116 LoadCosmosBootstrap,
117 ArgParserComponent:
118 DelegateArgParsers<HermesParserComponents>,
119 CommandRunnerComponent:
120 DelegateCommandRunner<HermesCommandRunnerComponents>,
121 }
122}
123
124delegate_components! {
125 HermesParserComponents {
126 (QueryClientStateArgs, symbol!("chain_id")): ParseFromString<ChainId>,
127 (QueryClientStateArgs, symbol!("client_id")): ParseFromString<ClientId>,
128 (QueryClientStateArgs, symbol!("height")): ParseFromOptionalString<Height>,
129
130 (QueryConsensusStateArgs, symbol!("chain_id")): ParseFromString<ChainId>,
131 (QueryConsensusStateArgs, symbol!("client_id")): ParseFromString<ClientId>,
132 (QueryConsensusStateArgs, symbol!("query_height")): ParseFromOptionalString<Height>,
133 (QueryConsensusStateArgs, symbol!("consensus_height")): ParseFromOptionalString<Height>,
134
135 (StartRelayerArgs, symbol!("chain_id_a")): ParseFromString<ChainId>,
136 (StartRelayerArgs, symbol!("client_id_a")): ParseFromString<ClientId>,
137 (StartRelayerArgs, symbol!("chain_id_b")): ParseFromString<ChainId>,
138 (StartRelayerArgs, symbol!("client_id_b")): ParseFromString<ClientId>,
139
140 (QueryClientStatusArgs, symbol!("chain_id")): ParseFromString<ChainId>,
141 (QueryClientStatusArgs, symbol!("client_id")): ParseFromString<ClientId>,
142
143 (CreateClientArgs, symbol!("target_chain_id")): ParseFromString<ChainId>,
144 (CreateClientArgs, symbol!("counterparty_chain_id")): ParseFromString<ChainId>,
145 }
146}
147
148delegate_components! {
149 HermesCommandRunnerComponents {
150 StartRelayerArgs: RunStartRelayerCommand,
151
152 QueryClientSubCommand: RunQueryClientSubCommand,
153 QueryClientStateArgs: RunQueryClientStateCommand,
154 QueryClientStatusArgs: RunQueryClientStatusCommand,
155 QueryConsensusStateArgs: RunQueryConsensusStateCommand,
156
157 CreateClientArgs: RunCreateClientCommand,
158
159 BootstrapSubCommand: RunBootstrapSubCommand,
160 BootstrapChainArgs: RunBootstrapChainCommand,
161 }
162}
163
164impl<App> ProvideBuilderType<App> for HermesAppComponents
165where
166 App: Async,
167{
168 type Builder = CosmosBuilder;
169}
170
171impl<App> ProvideAnyCounterparty<App> for HermesAppComponents
172where
173 App: Async,
174{
175 type AnyCounterparty = AnyCounterparty;
176}
177
178impl<App> ProvideConfigType<App> for HermesAppComponents
179where
180 App: Async,
181{
182 type Config = Config;
183}
184
185impl<App> ProvideOutputType<App> for HermesAppComponents
186where
187 App: Async,
188{
189 type Output = Output;
190}
191
192impl<App> ProvideBootstrapType<App> for HermesAppComponents
193where
194 App: Async,
195{
196 type Bootstrap = CosmosBootstrap;
197}
198
199impl<App, Value> OutputProducer<App, Value> for HermesAppComponents
200where
201 App: HasOutputType<Output = Output>,
202 Value: Serialize + Debug + Async,
203{
204 fn produce_output(_app: &App, value: Value) -> Output {
205 Output::success(value)
206 }
207}
208
209impl CreateClientOptionsParser<HermesApp, CreateClientArgs, 0, 1> for HermesAppComponents {
210 async fn parse_create_client_options(
211 _app: &HermesApp,
212 args: &CreateClientArgs,
213 target_chain: &CosmosChain,
214 counterparty_chain: &CosmosChain,
215 ) -> Result<((), Settings), Error> {
216 let options = CreateOptions {
217 max_clock_drift: args.clock_drift.map(|d| d.into()),
218 trusting_period: args.trusting_period.map(|d| d.into()),
219 trust_threshold: args.trust_threshold,
220 };
221
222 let settings = Settings::for_create_command(
223 options,
224 &target_chain.chain_config.clone(),
225 &counterparty_chain.chain_config.clone(),
226 );
227
228 Ok(((), settings))
229 }
230}
231
232pub trait CanUseHermesApp:
233 CanLoadConfig
234 + CanWriteConfig
235 + CanLoadBuilder
236 + CanRunCommand<StartRelayerArgs>
237 + CanRunCommand<QueryClientSubCommand>
238 + CanRunCommand<QueryClientStateArgs>
239 + CanRunCommand<QueryConsensusStateArgs>
240 + CanRunCommand<QueryClientStatusArgs>
241 + CanRunCommand<CreateClientArgs>
242 + CanRunCommand<BootstrapChainArgs>
243 + CanProduceOutput<&'static str>
244 + CanProduceOutput<ClientId>
245 + CanRaiseError<HermesError>
246 + CanRaiseError<WrapError<&'static str, HermesError>>
247{
248}
249
250impl CanUseHermesApp for HermesApp {}