hermes_cli/contexts/
app.rs

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 {}