hermes_cli_components/impls/commands/bootstrap/
chain.rs

1use core::marker::PhantomData;
2use std::path::PathBuf;
3
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::chain::traits::types::chain_id::HasChainId;
10use hermes_runtime_components::traits::fs::file_path::HasFilePathType;
11use hermes_runtime_components::traits::os::child_process::CanWaitChildProcess;
12use hermes_runtime_components::traits::runtime::HasRuntime;
13use hermes_test_components::bootstrap::traits::chain::CanBootstrapChain;
14use hermes_test_components::chain_driver::traits::chain_process::CanTakeChainProcess;
15use hermes_test_components::chain_driver::traits::config::CanUpdateConfig;
16use hermes_test_components::chain_driver::traits::types::chain::HasChain;
17
18use crate::traits::bootstrap::CanLoadBootstrap;
19use crate::traits::command::CommandRunner;
20use crate::traits::config::config_path::HasConfigPath;
21use crate::traits::config::load_config::CanLoadConfig;
22use crate::traits::config::write_config::CanWriteConfig;
23use crate::traits::output::CanProduceOutput;
24
25pub struct RunBootstrapChainCommand;
26
27impl<App, Args, Bootstrap, ChainDriver, Chain, Runtime> CommandRunner<App, Args>
28    for RunBootstrapChainCommand
29where
30    App: HasLogger
31        + CanProduceOutput<()>
32        + CanLoadBootstrap<Args, Bootstrap = Bootstrap>
33        + HasConfigPath
34        + CanLoadConfig
35        + CanWriteConfig
36        + CanRaiseError<Bootstrap::Error>
37        + CanRaiseError<Runtime::Error>
38        + CanRaiseError<ChainDriver::Error>
39        + CanWrapError<&'static str>,
40    Bootstrap: CanBootstrapChain<ChainDriver = ChainDriver>,
41    ChainDriver: HasChain<Chain = Chain>
42        + HasRuntime<Runtime = Runtime>
43        + CanTakeChainProcess
44        + CanUpdateConfig<App::Config>,
45    Chain: HasChainId,
46    Runtime: CanWaitChildProcess + HasFilePathType<FilePath = PathBuf>,
47    Args: Async + HasField<symbol!("chain_id"), Field = String>,
48    App::Logger: CanLog<LevelInfo>,
49{
50    async fn run_command(app: &App, args: &Args) -> Result<App::Output, App::Error> {
51        let logger = app.logger();
52        let chain_id = args.get_field(PhantomData);
53
54        let mut config = app.load_config().await?;
55        let bootstrap = app.load_bootstrap(args).await?;
56
57        let chain_driver = bootstrap
58            .bootstrap_chain(chain_id)
59            .await
60            .map_err(App::raise_error)?;
61
62        let chain = chain_driver.chain();
63
64        logger
65            .log(
66                &format!(
67                    "Bootstrapped a new chain with chain ID: {}",
68                    chain.chain_id()
69                ),
70                &LevelInfo,
71            )
72            .await;
73
74        let chain_config = chain_driver
75            .update_config(&mut config)
76            .map_err(App::raise_error)?;
77
78        app.write_config(&config).await?;
79
80        logger
81            .log(
82                &format!(
83                    "Added the following chain config to the main config file:\n{}",
84                    chain_config
85                ),
86                &LevelInfo,
87            )
88            .await;
89
90        let m_chain_process = chain_driver.take_chain_process().await;
91
92        if let Some(chain_process) = m_chain_process {
93            logger.log(&format!("running chain {} running in the background. Press Ctrl+C to stop then chain...", chain.chain_id()), &LevelInfo).await;
94
95            Runtime::wait_child_process(chain_process)
96                .await
97                .map_err(|e| {
98                    App::wrap_error("chain process exited with error", App::raise_error(e))
99                })?;
100
101            logger
102                .log("chain process exited with no error", &LevelInfo)
103                .await;
104        }
105
106        Ok(app.produce_output(()))
107    }
108}