1use std::fmt::Display;
2use std::net::SocketAddr;
3use std::path::PathBuf;
4use std::str::FromStr;
5
6use bitcoin::Network;
7use clap::{Parser, Subcommand};
8use fedimint_core::util::SafeUrl;
9use serde::{Deserialize, Serialize};
10
11use super::envs;
12use super::rpc::V1_API_ENDPOINT;
13use crate::envs::{
14 FM_LDK_BITCOIND_RPC_URL, FM_LDK_ESPLORA_SERVER_URL, FM_LDK_NETWORK, FM_LND_MACAROON_ENV,
15 FM_LND_RPC_ADDR_ENV, FM_LND_TLS_CERT_ENV, FM_PORT_LDK,
16};
17
18#[derive(Debug, Clone, Subcommand, Serialize, Deserialize, Eq, PartialEq)]
19pub enum LightningMode {
20 #[clap(name = "lnd")]
21 Lnd {
22 #[arg(long = "lnd-rpc-host", env = FM_LND_RPC_ADDR_ENV)]
24 lnd_rpc_addr: String,
25
26 #[arg(long = "lnd-tls-cert", env = FM_LND_TLS_CERT_ENV)]
28 lnd_tls_cert: String,
29
30 #[arg(long = "lnd-macaroon", env = FM_LND_MACAROON_ENV)]
32 lnd_macaroon: String,
33 },
34 #[clap(name = "ldk")]
35 Ldk {
36 #[arg(long = "ldk-esplora-server-url", env = FM_LDK_ESPLORA_SERVER_URL)]
38 esplora_server_url: Option<String>,
39
40 #[arg(long = "ldk-bitcoind-rpc-url", env = FM_LDK_BITCOIND_RPC_URL)]
42 bitcoind_rpc_url: Option<String>,
43
44 #[arg(long = "ldk-network", env = FM_LDK_NETWORK, default_value = "regtest")]
46 network: Network,
47
48 #[arg(long = "ldk-lightning-port", env = FM_PORT_LDK)]
50 lightning_port: u16,
51 },
52}
53
54#[derive(Parser)]
57#[command(version)]
58pub struct GatewayOpts {
59 #[clap(subcommand)]
60 pub mode: LightningMode,
61
62 #[arg(long = "data-dir", env = envs::FM_GATEWAY_DATA_DIR_ENV)]
64 pub data_dir: PathBuf,
65
66 #[arg(long = "listen", env = envs::FM_GATEWAY_LISTEN_ADDR_ENV)]
68 listen: SocketAddr,
69
70 #[arg(long = "api-addr", env = envs::FM_GATEWAY_API_ADDR_ENV)]
72 api_addr: SafeUrl,
73
74 #[arg(long = "bcrypt-password-hash", env = envs::FM_GATEWAY_BCRYPT_PASSWORD_HASH_ENV)]
76 bcrypt_password_hash: String,
77
78 #[arg(long = "network", env = envs::FM_GATEWAY_NETWORK_ENV)]
80 network: Network,
81
82 #[arg(
84 long = "num-route-hints",
85 env = envs::FM_NUMBER_OF_ROUTE_HINTS_ENV,
86 default_value_t = super::DEFAULT_NUM_ROUTE_HINTS
87 )]
88 num_route_hints: u32,
89
90 #[arg(long = "lightning-module-mode", env = envs::FM_GATEWAY_LIGHTNING_MODULE_MODE_ENV, default_value_t = LightningModuleMode::LNv1)]
92 lightning_module_mode: LightningModuleMode,
93}
94
95impl GatewayOpts {
96 pub fn to_gateway_parameters(&self) -> anyhow::Result<GatewayParameters> {
99 let versioned_api = self.api_addr.join(V1_API_ENDPOINT).map_err(|e| {
100 anyhow::anyhow!(
101 "Failed to version gateway API address: {api_addr:?}, error: {e:?}",
102 api_addr = self.api_addr,
103 )
104 })?;
105
106 let bcrypt_password_hash = bcrypt::HashParts::from_str(&self.bcrypt_password_hash)?;
107
108 Ok(GatewayParameters {
109 listen: self.listen,
110 versioned_api,
111 bcrypt_password_hash,
112 network: self.network,
113 num_route_hints: self.num_route_hints,
114 lightning_module_mode: self.lightning_module_mode,
115 })
116 }
117}
118
119#[derive(Debug)]
126pub struct GatewayParameters {
127 pub listen: SocketAddr,
128 pub versioned_api: SafeUrl,
129 pub bcrypt_password_hash: bcrypt::HashParts,
130 pub network: Network,
131 pub num_route_hints: u32,
132 pub lightning_module_mode: LightningModuleMode,
133}
134
135#[derive(Debug, Clone, Copy, Eq, PartialEq)]
136pub enum LightningModuleMode {
137 LNv1,
138 LNv2,
139 All,
140}
141
142impl Display for LightningModuleMode {
143 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
144 match self {
145 LightningModuleMode::LNv1 => write!(f, "LNv1"),
146 LightningModuleMode::LNv2 => write!(f, "LNv2"),
147 LightningModuleMode::All => write!(f, "All"),
148 }
149 }
150}
151
152impl FromStr for LightningModuleMode {
153 type Err = anyhow::Error;
154
155 fn from_str(s: &str) -> Result<Self, Self::Err> {
156 let mode = match s {
157 "LNv1" => LightningModuleMode::LNv1,
158 "LNv2" => LightningModuleMode::LNv2,
159 _ => LightningModuleMode::All,
160 };
161
162 Ok(mode)
163 }
164}