gateway_cli/
general_commands.rs

1use std::time::{Duration, UNIX_EPOCH};
2
3use clap::Subcommand;
4use fedimint_core::config::FederationId;
5use fedimint_core::fedimint_build_code_version_env;
6use fedimint_core::time::now;
7use fedimint_core::util::SafeUrl;
8use fedimint_eventlog::{EventKind, EventLogId};
9use fedimint_gateway_client::{
10    connect_federation, get_balances, get_info, get_mnemonic, leave_federation, payment_log,
11    payment_summary, stop,
12};
13use fedimint_gateway_common::{
14    ConnectFedPayload, LeaveFedPayload, PaymentLogPayload, PaymentSummaryPayload,
15};
16use fedimint_ln_common::client::GatewayApi;
17
18use crate::print_response;
19
20#[derive(Subcommand)]
21pub enum GeneralCommands {
22    /// Display the version hash of the CLI.
23    VersionHash,
24    /// Display high-level information about the gateway.
25    Info,
26    /// Get the total on-chain, lightning, and eCash balances of the gateway.
27    GetBalances,
28    /// Register the gateway with a federation.
29    ConnectFed {
30        /// Invite code to connect to the federation
31        invite_code: String,
32        /// Activate usage of Tor (or not) as the connector for the federation
33        /// client
34        #[cfg(feature = "tor")]
35        use_tor: Option<bool>,
36        /// Indicates if the client should be recovered from a mnemonic
37        #[clap(long)]
38        recover: Option<bool>,
39    },
40    /// Leave a federation.
41    LeaveFed {
42        #[clap(long)]
43        federation_id: FederationId,
44    },
45    /// Prints the seed phrase for the gateway
46    Seed,
47    /// Safely stop the gateway
48    Stop,
49    /// List the fedimint transactions that the gateway has processed
50    PaymentLog {
51        #[clap(long)]
52        end_position: Option<EventLogId>,
53
54        #[clap(long, default_value_t = 25)]
55        pagination_size: usize,
56
57        #[clap(long)]
58        federation_id: FederationId,
59
60        #[clap(long)]
61        event_kinds: Vec<EventKind>,
62    },
63    /// Create a bcrypt hash of a password, for use in gateway deployment
64    CreatePasswordHash {
65        password: String,
66
67        /// The bcrypt cost factor to use when hashing the password
68        #[clap(long)]
69        cost: Option<u32>,
70    },
71    /// List a payment summary for the last day
72    PaymentSummary {
73        #[clap(long)]
74        start: Option<u64>,
75
76        #[clap(long)]
77        end: Option<u64>,
78    },
79}
80
81impl GeneralCommands {
82    #[allow(clippy::too_many_lines)]
83    pub async fn handle(self, client: &GatewayApi, base_url: &SafeUrl) -> anyhow::Result<()> {
84        match self {
85            Self::VersionHash => {
86                println!("{}", fedimint_build_code_version_env!());
87            }
88            Self::Info => {
89                let response = get_info(client, base_url).await?;
90                print_response(response);
91            }
92            Self::GetBalances => {
93                let response = get_balances(client, base_url).await?;
94                print_response(response);
95            }
96            Self::ConnectFed {
97                invite_code,
98                #[cfg(feature = "tor")]
99                use_tor,
100                recover,
101            } => {
102                let response = connect_federation(
103                    client,
104                    base_url,
105                    ConnectFedPayload {
106                        invite_code,
107                        #[cfg(feature = "tor")]
108                        use_tor,
109                        #[cfg(not(feature = "tor"))]
110                        use_tor: None,
111                        recover,
112                    },
113                )
114                .await?;
115
116                print_response(response);
117            }
118            Self::LeaveFed { federation_id } => {
119                let response =
120                    leave_federation(client, base_url, LeaveFedPayload { federation_id }).await?;
121                print_response(response);
122            }
123            Self::Seed => {
124                let response = get_mnemonic(client, base_url).await?;
125                print_response(response);
126            }
127            Self::Stop => {
128                stop(client, base_url).await?;
129            }
130            Self::PaymentLog {
131                end_position,
132                pagination_size,
133                federation_id,
134                event_kinds,
135            } => {
136                let payment_log = payment_log(
137                    client,
138                    base_url,
139                    PaymentLogPayload {
140                        end_position,
141                        pagination_size,
142                        federation_id,
143                        event_kinds,
144                    },
145                )
146                .await?;
147                print_response(payment_log);
148            }
149            Self::CreatePasswordHash { password, cost } => print_response(
150                bcrypt::hash(password, cost.unwrap_or(bcrypt::DEFAULT_COST))
151                    .expect("Unable to create bcrypt hash"),
152            ),
153            Self::PaymentSummary { start, end } => {
154                let now = now();
155                let now_millis = now
156                    .duration_since(UNIX_EPOCH)
157                    .expect("Before unix epoch")
158                    .as_millis()
159                    .try_into()?;
160                let one_day_ago = now
161                    .checked_sub(Duration::from_secs(60 * 60 * 24))
162                    .expect("Before unix epoch");
163                let one_day_ago_millis = one_day_ago
164                    .duration_since(UNIX_EPOCH)
165                    .expect("Before unix epoch")
166                    .as_millis()
167                    .try_into()?;
168                let end_millis = end.unwrap_or(now_millis);
169                let start_millis = start.unwrap_or(one_day_ago_millis);
170                let payment_summary = payment_summary(
171                    client,
172                    base_url,
173                    PaymentSummaryPayload {
174                        start_millis,
175                        end_millis,
176                    },
177                )
178                .await?;
179                print_response(payment_summary);
180            }
181        }
182
183        Ok(())
184    }
185}