ln_gateway/
config.rs

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        /// LND RPC address
23        #[arg(long = "lnd-rpc-host", env = FM_LND_RPC_ADDR_ENV)]
24        lnd_rpc_addr: String,
25
26        /// LND TLS cert file path
27        #[arg(long = "lnd-tls-cert", env = FM_LND_TLS_CERT_ENV)]
28        lnd_tls_cert: String,
29
30        /// LND macaroon file path
31        #[arg(long = "lnd-macaroon", env = FM_LND_MACAROON_ENV)]
32        lnd_macaroon: String,
33    },
34    #[clap(name = "ldk")]
35    Ldk {
36        /// LDK esplora server URL
37        #[arg(long = "ldk-esplora-server-url", env = FM_LDK_ESPLORA_SERVER_URL)]
38        esplora_server_url: Option<String>,
39
40        /// LDK bitcoind server URL
41        #[arg(long = "ldk-bitcoind-rpc-url", env = FM_LDK_BITCOIND_RPC_URL)]
42        bitcoind_rpc_url: Option<String>,
43
44        /// LDK network (defaults to regtest if not provided)
45        #[arg(long = "ldk-network", env = FM_LDK_NETWORK, default_value = "regtest")]
46        network: Network,
47
48        /// LDK lightning server port
49        #[arg(long = "ldk-lightning-port", env = FM_PORT_LDK)]
50        lightning_port: u16,
51    },
52}
53
54/// Command line parameters for starting the gateway. `mode`, `data_dir`,
55/// `listen`, and `api_addr` are all required.
56#[derive(Parser)]
57#[command(version)]
58pub struct GatewayOpts {
59    #[clap(subcommand)]
60    pub mode: LightningMode,
61
62    /// Path to folder containing gateway config and data files
63    #[arg(long = "data-dir", env = envs::FM_GATEWAY_DATA_DIR_ENV)]
64    pub data_dir: PathBuf,
65
66    /// Gateway webserver listen address
67    #[arg(long = "listen", env = envs::FM_GATEWAY_LISTEN_ADDR_ENV)]
68    listen: SocketAddr,
69
70    /// Public URL from which the webserver API is reachable
71    #[arg(long = "api-addr", env = envs::FM_GATEWAY_API_ADDR_ENV)]
72    api_addr: SafeUrl,
73
74    /// Gateway webserver authentication bcrypt password hash
75    #[arg(long = "bcrypt-password-hash", env = envs::FM_GATEWAY_BCRYPT_PASSWORD_HASH_ENV)]
76    bcrypt_password_hash: String,
77
78    /// Bitcoin network this gateway will be running on
79    #[arg(long = "network", env = envs::FM_GATEWAY_NETWORK_ENV)]
80    network: Network,
81
82    /// Number of route hints to return in invoices
83    #[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    /// The Lightning module to use: LNv1, LNv2, or both
91    #[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    /// Converts the command line parameters into a helper struct the Gateway
97    /// uses to store runtime parameters.
98    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/// `GatewayParameters` is a helper struct that can be derived from
120/// `GatewayOpts` that holds the CLI or environment variables that are specified
121/// by the user.
122///
123/// If `GatewayConfiguration is set in the database, that takes precedence and
124/// the optional parameters will have no affect.
125#[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}