gateway_cli/
main.rs

1#![deny(clippy::pedantic, clippy::nursery)]
2
3mod config_commands;
4mod ecash_commands;
5mod general_commands;
6mod lightning_commands;
7mod onchain_commands;
8
9use clap::{CommandFactory, Parser, Subcommand};
10use config_commands::ConfigCommands;
11use ecash_commands::EcashCommands;
12use fedimint_core::envs::FM_IROH_DNS_ENV;
13use fedimint_core::util::SafeUrl;
14use fedimint_gateway_client::GatewayRpcClient;
15use fedimint_logging::TracingSetup;
16use general_commands::GeneralCommands;
17use lightning_commands::LightningCommands;
18use onchain_commands::OnchainCommands;
19use serde::Serialize;
20
21#[derive(Parser)]
22#[command(version)]
23struct Cli {
24    /// The address of the gateway webserver
25    #[clap(long, short, default_value = "http://127.0.0.1:80")]
26    address: SafeUrl,
27
28    /// The command to execute
29    #[command(subcommand)]
30    command: Commands,
31
32    /// Password for authenticated requests to the gateway
33    #[clap(long)]
34    rpcpassword: Option<String>,
35
36    /// Optional URL of the Iroh DNS server
37    #[arg(long, env = FM_IROH_DNS_ENV)]
38    iroh_dns: Option<SafeUrl>,
39
40    /// Optional override URL for directly connecting to an Iroh endpoint
41    #[arg(long)]
42    connection_override: Option<SafeUrl>,
43}
44
45#[derive(Subcommand)]
46enum Commands {
47    #[command(flatten)]
48    General(GeneralCommands),
49    #[command(subcommand)]
50    Lightning(LightningCommands),
51    #[command(subcommand)]
52    Ecash(EcashCommands),
53    #[command(subcommand)]
54    Onchain(OnchainCommands),
55    #[command(subcommand)]
56    Cfg(ConfigCommands),
57    Completion {
58        shell: clap_complete::Shell,
59    },
60}
61
62#[tokio::main]
63async fn main() {
64    if let Err(err) = TracingSetup::default().init() {
65        eprintln!("Failed to initialize logging: {err}");
66        std::process::exit(1);
67    }
68
69    if let Err(err) = run().await {
70        eprintln!("Error: {err}");
71        let mut source = err.source();
72        eprintln!("Caused by");
73        while let Some(err) = source {
74            eprintln!("    {err}");
75            source = err.source();
76        }
77        std::process::exit(1);
78    }
79}
80
81async fn run() -> anyhow::Result<()> {
82    let cli = Cli::parse();
83    let client = GatewayRpcClient::new(
84        cli.address,
85        cli.rpcpassword,
86        cli.iroh_dns,
87        cli.connection_override,
88    )
89    .await?;
90    // TODO: Need to call with_connection_override
91
92    match cli.command {
93        Commands::General(general_command) => general_command.handle(&client).await?,
94        Commands::Lightning(lightning_command) => lightning_command.handle(&client).await?,
95        Commands::Ecash(ecash_command) => ecash_command.handle(&client).await?,
96        Commands::Onchain(onchain_command) => onchain_command.handle(&client).await?,
97        Commands::Cfg(config_commands) => config_commands.handle(&client).await?,
98        Commands::Completion { shell } => {
99            clap_complete::generate(
100                shell,
101                &mut Cli::command(),
102                "gateway-cli",
103                &mut std::io::stdout(),
104            );
105        }
106    }
107
108    Ok(())
109}
110
111fn print_response<T: Serialize>(val: T) {
112    println!(
113        "{}",
114        serde_json::to_string_pretty(&val).expect("Cannot serialize")
115    );
116}