Skip to main content

forest/cli/subcommands/
mod.rs

1// Copyright 2019-2026 ChainSafe Systems
2// SPDX-License-Identifier: Apache-2.0, MIT
3
4// Due to https://git.wiki.kernel.org/index.php/GitFaq#Why_does_Git_not_.22track.22_renames.3F
5// we cannot rewire the git history of this file.
6// check out the original commit history here:
7// https://github.com/ChainSafe/forest/commits/main/forest/src/cli/mod.rs
8
9mod auth_cmd;
10mod chain_cmd;
11mod config_cmd;
12mod f3_cmd;
13mod healthcheck_cmd;
14mod index_cmd;
15mod info_cmd;
16mod mpool_cmd;
17mod net_cmd;
18mod shutdown_cmd;
19mod snapshot_cmd;
20mod state_cmd;
21mod sync_cmd;
22mod wait_api_cmd;
23
24pub(super) use self::{
25    auth_cmd::AuthCommands, chain_cmd::ChainCommands, config_cmd::ConfigCommands,
26    f3_cmd::F3Commands, healthcheck_cmd::HealthcheckCommand, index_cmd::IndexCommands,
27    mpool_cmd::MpoolCommands, net_cmd::NetCommands, shutdown_cmd::ShutdownCommand,
28    snapshot_cmd::SnapshotCommands, state_cmd::StateCommands, sync_cmd::SyncCommands,
29    wait_api_cmd::WaitApiCommand,
30};
31use crate::cli::subcommands::info_cmd::InfoCommand;
32pub(crate) use crate::cli_shared::cli::Config;
33use crate::cli_shared::cli::HELP_MESSAGE;
34use crate::lotus_json::HasLotusJson;
35use crate::utils::version::FOREST_VERSION_STRING;
36use clap::Parser;
37use spire_enum::prelude::delegated_enum;
38use tracing::error;
39
40/// CLI structure generated when interacting with Forest binary
41#[derive(Parser)]
42#[command(name = env!("CARGO_PKG_NAME"), bin_name = "forest-cli", author = env!("CARGO_PKG_AUTHORS"), version = FOREST_VERSION_STRING.as_str(), about = env!("CARGO_PKG_DESCRIPTION")
43)]
44#[command(help_template(HELP_MESSAGE))]
45pub struct Cli {
46    /// Client JWT token to use for JSON-RPC authentication
47    #[arg(short, long)]
48    pub token: Option<String>,
49    #[command(subcommand)]
50    pub cmd: Subcommand,
51}
52
53/// Forest binary sub-commands available.
54#[delegated_enum]
55#[derive(clap::Subcommand, Debug)]
56pub enum Subcommand {
57    /// Interact with Filecoin blockchain
58    #[command(subcommand)]
59    Chain(ChainCommands),
60
61    /// Manage RPC permissions
62    #[command(subcommand)]
63    Auth(AuthCommands),
64
65    /// Manage P2P network
66    #[command(subcommand)]
67    Net(NetCommands),
68
69    /// Inspect or interact with the chain synchronizer
70    #[command(subcommand)]
71    Sync(SyncCommands),
72
73    /// Interact with the message pool
74    #[command(subcommand)]
75    Mpool(MpoolCommands),
76
77    /// Interact with and query Filecoin chain state
78    #[command(subcommand)]
79    State(StateCommands),
80
81    /// Manage node configuration
82    #[command(subcommand)]
83    Config(ConfigCommands),
84
85    /// Manage snapshots
86    #[command(subcommand)]
87    Snapshot(SnapshotCommands),
88
89    /// Manage the chain index
90    #[command(subcommand)]
91    Index(IndexCommands),
92
93    /// Print node info
94    #[command(subcommand)]
95    Info(InfoCommand),
96
97    /// Shutdown Forest
98    Shutdown(ShutdownCommand),
99
100    /// Print healthcheck info
101    #[command(subcommand)]
102    Healthcheck(HealthcheckCommand),
103
104    /// Manages Filecoin Fast Finality (F3) interactions
105    #[command(subcommand)]
106    F3(F3Commands),
107
108    /// Wait for lotus API to come online
109    WaitApi(WaitApiCommand),
110}
111
112impl Subcommand {
113    pub async fn run(self, client: crate::rpc::Client) -> anyhow::Result<()> {
114        delegate_subcommand!(self.run(client).await)
115    }
116}
117
118/// Print an error message and exit the program with an error code
119/// Used for handling high level errors such as invalid parameters
120pub fn cli_error_and_die(msg: impl AsRef<str>, code: i32) -> ! {
121    error!("Error: {}", msg.as_ref());
122    std::process::exit(code);
123}
124
125/// Prints a pretty HTTP JSON-RPC response result
126pub(super) fn print_pretty_lotus_json<T: HasLotusJson>(obj: T) -> anyhow::Result<()> {
127    println!("{}", obj.into_lotus_json_string_pretty()?);
128    Ok(())
129}
130
131/// Prints a bytes HTTP JSON-RPC response result
132pub(super) fn print_rpc_res_bytes(obj: Vec<u8>) -> anyhow::Result<()> {
133    println!("{}", String::from_utf8(obj)?);
134    Ok(())
135}
136
137/// Require user confirmation. Returns `false` when not connected to a terminal.
138pub fn prompt_confirm() -> bool {
139    let term = dialoguer::console::Term::stderr();
140
141    if !term.is_term() {
142        return false;
143    }
144
145    dialoguer::Confirm::new()
146        .with_prompt("Do you want to continue?")
147        .interact_on(&term)
148        .unwrap_or(false)
149}