gateway_cli/
general_commands.rs1use std::time::{Duration, UNIX_EPOCH};
2
3use clap::Subcommand;
4use fedimint_connectors::error::ServerError;
5use fedimint_core::config::FederationId;
6use fedimint_core::fedimint_build_code_version_env;
7use fedimint_core::time::now;
8use fedimint_core::util::SafeUrl;
9use fedimint_eventlog::{EventKind, EventLogId};
10use fedimint_gateway_client::{
11 connect_federation, get_balances, get_info, get_invite_codes, get_mnemonic, leave_federation,
12 payment_log, payment_summary, stop,
13};
14use fedimint_gateway_common::{
15 ConnectFedPayload, LeaveFedPayload, PaymentLogPayload, PaymentSummaryPayload,
16};
17use fedimint_ln_common::client::GatewayApi;
18
19use crate::{CliOutput, CliOutputResult};
20
21#[derive(Subcommand)]
24pub enum GeneralCommands {
25 VersionHash,
27 Info,
29 GetBalances,
31 ConnectFed {
33 invite_code: String,
35 #[cfg(feature = "tor")]
38 use_tor: Option<bool>,
39 #[clap(long)]
41 recover: Option<bool>,
42 },
43 LeaveFed {
45 #[clap(long)]
46 federation_id: FederationId,
47 },
48 Seed,
50 Stop,
52 PaymentLog {
54 #[clap(long)]
55 end_position: Option<EventLogId>,
56
57 #[clap(long, default_value_t = 25)]
58 pagination_size: usize,
59
60 #[clap(long)]
61 federation_id: FederationId,
62
63 #[clap(long)]
64 event_kinds: Vec<EventKind>,
65 },
66 CreatePasswordHash {
68 password: String,
69
70 #[clap(long)]
72 cost: Option<u32>,
73 },
74 PaymentSummary {
76 #[clap(long)]
77 start: Option<u64>,
78
79 #[clap(long)]
80 end: Option<u64>,
81 },
82 InviteCodes,
84}
85
86impl GeneralCommands {
87 #[allow(clippy::too_many_lines)]
88 pub async fn handle(self, client: &GatewayApi, base_url: &SafeUrl) -> CliOutputResult {
89 match self {
90 Self::VersionHash => {
91 println!("{}", fedimint_build_code_version_env!());
93 Ok(CliOutput::Empty)
94 }
95 Self::Info => {
96 let response = get_info(client, base_url).await?;
97 Ok(CliOutput::Info(response))
98 }
99 Self::GetBalances => {
100 let response = get_balances(client, base_url).await?;
101 Ok(CliOutput::Balances(response))
102 }
103 Self::ConnectFed {
104 invite_code,
105 #[cfg(feature = "tor")]
106 use_tor,
107 recover,
108 } => {
109 let response = connect_federation(
110 client,
111 base_url,
112 ConnectFedPayload {
113 invite_code,
114 #[cfg(feature = "tor")]
115 use_tor,
116 #[cfg(not(feature = "tor"))]
117 use_tor: None,
118 recover,
119 },
120 )
121 .await?;
122
123 Ok(CliOutput::Federation(response))
124 }
125 Self::LeaveFed { federation_id } => {
126 let response =
127 leave_federation(client, base_url, LeaveFedPayload { federation_id }).await?;
128 Ok(CliOutput::Federation(response))
129 }
130 Self::Seed => {
131 let response = get_mnemonic(client, base_url).await?;
132 Ok(CliOutput::Mnemonic(response))
133 }
134 Self::Stop => {
135 stop(client, base_url).await?;
136 Ok(CliOutput::Empty)
137 }
138 Self::PaymentLog {
139 end_position,
140 pagination_size,
141 federation_id,
142 event_kinds,
143 } => {
144 let payment_log = payment_log(
145 client,
146 base_url,
147 PaymentLogPayload {
148 end_position,
149 pagination_size,
150 federation_id,
151 event_kinds,
152 },
153 )
154 .await?;
155 Ok(CliOutput::PaymentLog(payment_log))
156 }
157 Self::CreatePasswordHash { password, cost } => {
158 let hash = bcrypt::hash(password, cost.unwrap_or(bcrypt::DEFAULT_COST))
159 .expect("Unable to create bcrypt hash");
160 Ok(CliOutput::PasswordHash(hash))
161 }
162 Self::PaymentSummary { start, end } => {
163 let now = now();
164 let now_millis: u64 = now
165 .duration_since(UNIX_EPOCH)
166 .expect("Before unix epoch")
167 .as_millis()
168 .try_into()
169 .map_err(|e| ServerError::InternalClientError(anyhow::anyhow!("{e}")))?;
170 let one_day_ago = now
171 .checked_sub(Duration::from_hours(24))
172 .expect("Before unix epoch");
173 let one_day_ago_millis: u64 = one_day_ago
174 .duration_since(UNIX_EPOCH)
175 .expect("Before unix epoch")
176 .as_millis()
177 .try_into()
178 .map_err(|e| ServerError::InternalClientError(anyhow::anyhow!("{e}")))?;
179 let end_millis = end.unwrap_or(now_millis);
180 let start_millis = start.unwrap_or(one_day_ago_millis);
181 let payment_summary = payment_summary(
182 client,
183 base_url,
184 PaymentSummaryPayload {
185 start_millis,
186 end_millis,
187 },
188 )
189 .await?;
190 Ok(CliOutput::PaymentSummary(payment_summary))
191 }
192 Self::InviteCodes => {
193 let invite_codes = get_invite_codes(client, base_url).await?;
194 Ok(CliOutput::InviteCodes(invite_codes))
195 }
196 }
197 }
198}