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