fedimint_lnv2_client/
cli.rs1use std::{ffi, iter};
2
3use clap::{Parser, Subcommand};
4use fedimint_core::core::OperationId;
5use fedimint_core::util::SafeUrl;
6use fedimint_core::{Amount, PeerId};
7use lightning_invoice::Bolt11Invoice;
8use serde::Serialize;
9use serde_json::Value;
10
11use crate::api::LightningFederationApi;
12use crate::{Bolt11InvoiceDescription, LightningClientModule};
13
14#[derive(Parser, Serialize)]
15enum Opts {
16 Send {
19 invoice: Bolt11Invoice,
20 #[arg(long)]
21 gateway: Option<SafeUrl>,
22 },
23 AwaitSend { operation_id: OperationId },
25 Receive {
29 amount: Amount,
30 #[arg(long)]
31 gateway: Option<SafeUrl>,
32 },
33 AwaitReceive { operation_id: OperationId },
35 #[command(subcommand)]
37 Gateways(GatewaysOpts),
38}
39
40#[derive(Clone, Subcommand, Serialize)]
41enum GatewaysOpts {
42 Map,
46 Select {
48 #[arg(long)]
49 invoice: Option<Bolt11Invoice>,
50 },
51 List {
53 #[arg(long)]
54 peer: Option<PeerId>,
55 },
56 Add { gateway: SafeUrl },
58 Remove { gateway: SafeUrl },
60}
61
62pub(crate) async fn handle_cli_command(
63 lightning: &LightningClientModule,
64 args: &[ffi::OsString],
65) -> anyhow::Result<serde_json::Value> {
66 let opts = Opts::parse_from(iter::once(&ffi::OsString::from("lnv2")).chain(args.iter()));
67
68 let value = match opts {
69 Opts::Send { gateway, invoice } => {
70 json(lightning.send(invoice, gateway, Value::Null).await?)
71 }
72 Opts::AwaitSend { operation_id } => json(
73 lightning
74 .await_final_send_operation_state(operation_id)
75 .await?,
76 ),
77 Opts::Receive { amount, gateway } => json(
78 lightning
79 .receive(
80 amount,
81 3600,
82 Bolt11InvoiceDescription::Direct(String::new()),
83 gateway,
84 Value::Null,
85 )
86 .await?,
87 ),
88 Opts::AwaitReceive { operation_id } => json(
89 lightning
90 .await_final_receive_operation_state(operation_id)
91 .await?,
92 ),
93 Opts::Gateways(gateway_opts) => match gateway_opts {
94 #[allow(clippy::unit_arg)]
95 GatewaysOpts::Map => json(
96 LightningClientModule::update_gateway_map(
97 &lightning.federation_id,
98 &lightning.client_ctx,
99 &lightning.module_api,
100 &lightning.gateway_conn,
101 )
102 .await,
103 ),
104 GatewaysOpts::Select { invoice } => json(lightning.select_gateway(invoice).await?.0),
105 GatewaysOpts::List { peer } => match peer {
106 Some(peer) => json(lightning.module_api.gateways_from_peer(peer).await?),
107 None => json(lightning.module_api.gateways().await?),
108 },
109 GatewaysOpts::Add { gateway } => {
110 let auth = lightning
111 .admin_auth
112 .clone()
113 .ok_or(anyhow::anyhow!("Admin auth not set"))?;
114
115 json(lightning.module_api.add_gateway(auth, gateway).await?)
116 }
117 GatewaysOpts::Remove { gateway } => {
118 let auth = lightning
119 .admin_auth
120 .clone()
121 .ok_or(anyhow::anyhow!("Admin auth not set"))?;
122
123 json(lightning.module_api.remove_gateway(auth, gateway).await?)
124 }
125 },
126 };
127
128 Ok(value)
129}
130
131fn json<T: Serialize>(value: T) -> Value {
132 serde_json::to_value(value).expect("JSON serialization failed")
133}