cdk_mintd/env_vars/
mod.rs1#![allow(missing_docs)]
2mod common;
8mod database;
9mod info;
10mod limits;
11mod mint_info;
12mod onchain;
13mod payment_backend;
14mod signatory;
15
16mod auth;
17#[cfg(feature = "bdk")]
18mod bdk;
19#[cfg(feature = "cln")]
20mod cln;
21#[cfg(feature = "fakewallet")]
22mod fake_wallet;
23#[cfg(feature = "grpc-processor")]
24mod grpc_processor;
25#[cfg(feature = "ldk-node")]
26mod ldk_node;
27#[cfg(feature = "lnd")]
28mod lnd;
29#[cfg(feature = "management-rpc")]
30mod management_rpc;
31#[cfg(feature = "prometheus")]
32mod prometheus;
33
34use std::env;
35use std::str::FromStr;
36
37use anyhow::{anyhow, bail, Result};
38pub use auth::*;
39#[cfg(feature = "bdk")]
40pub use bdk::*;
41#[cfg(feature = "cln")]
42pub use cln::*;
43pub use common::*;
44pub use database::*;
45#[cfg(feature = "fakewallet")]
46pub use fake_wallet::*;
47#[cfg(feature = "grpc-processor")]
48pub use grpc_processor::*;
49#[cfg(feature = "ldk-node")]
50pub use ldk_node::*;
51pub use limits::*;
52#[cfg(feature = "lnd")]
53pub use lnd::*;
54#[cfg(feature = "management-rpc")]
55pub use management_rpc::*;
56pub use mint_info::*;
57pub use onchain::*;
58pub use payment_backend::*;
59#[cfg(feature = "prometheus")]
60pub use prometheus::*;
61
62use crate::config::{DatabaseEngine, OnchainBackend, PaymentBackend, PaymentBackendType, Settings};
63
64impl Settings {
65 pub fn from_env(&mut self) -> Result<Self> {
66 if let Ok(database) = env::var(DATABASE_ENV_VAR) {
67 let engine = DatabaseEngine::from_str(&database).map_err(|err| anyhow!(err))?;
68 self.database.engine = engine;
69 }
70
71 if self.database.engine == DatabaseEngine::Postgres {
73 self.database.postgres = Some(
74 self.database
75 .postgres
76 .clone()
77 .unwrap_or_default()
78 .from_env(),
79 );
80 }
81
82 self.auth_database = Some(crate::config::AuthDatabase {
84 postgres: Some(
85 self.auth_database
86 .clone()
87 .unwrap_or_default()
88 .postgres
89 .unwrap_or_default()
90 .from_env(),
91 ),
92 });
93
94 self.info = self.info.clone().from_env();
95 self.signatory = Some(self.signatory.clone().unwrap_or_default().from_env());
96
97 self.mint_info = self.mint_info.clone().from_env();
98 match self.payment_backend.len() {
103 0 => {
104 let backend = PaymentBackend::default().from_env();
105 if backend.backend != PaymentBackendType::None {
106 self.payment_backend.push(backend);
107 }
108 }
109 1 => {
110 self.payment_backend[0] = self.payment_backend[0].clone().from_env();
111 }
112 _ => {
113 tracing::warn!(
114 "CDK_MINTD_PAYMENT_BACKEND_* environment variables ignored: multiple [[payment_backend]] entries configured"
115 );
116 }
117 }
118 self.onchain = Some(self.onchain.clone().unwrap_or_default().from_env());
119 self.limits = self.limits.clone().from_env();
120
121 {
122 let auth = self.auth.clone().unwrap_or_default().from_env();
124
125 if auth.auth_enabled {
127 self.auth = Some(auth);
128 } else {
129 self.auth = None;
130 }
131 }
132
133 #[cfg(feature = "management-rpc")]
134 {
135 self.mint_management_rpc = Some(
136 self.mint_management_rpc
137 .clone()
138 .unwrap_or_default()
139 .from_env(),
140 );
141 }
142
143 #[cfg(feature = "prometheus")]
144 {
145 self.prometheus = Some(self.prometheus.clone().unwrap_or_default().from_env());
146 }
147
148 #[cfg(feature = "cln")]
149 {
150 let cln = self.cln.clone().unwrap_or_default().from_env();
151 if cln.rpc_path.as_os_str().is_empty() {
152 self.cln = None;
153 } else {
154 self.cln = Some(cln);
155 }
156 }
157
158 #[cfg(feature = "fakewallet")]
159 {
160 let fake_wallet_supported_units_from_env =
162 env::var(ENV_FAKE_WALLET_SUPPORTED_UNITS).is_ok();
163 let fake_wallet = self.fake_wallet.clone().unwrap_or_default().from_env();
164 let supported_units_configured =
165 fake_wallet.supported_units != vec![cdk::nuts::CurrencyUnit::Sat];
166
167 if fake_wallet_supported_units_from_env || supported_units_configured {
168 self.expand_single_fake_wallet_backend_entry(&fake_wallet);
169 }
170
171 self.fake_wallet = Some(fake_wallet);
172 }
173
174 #[cfg(feature = "lnd")]
175 {
176 let lnd = self.lnd.clone().unwrap_or_default().from_env()?;
177 if lnd.address.is_empty() {
178 self.lnd = None;
179 } else {
180 self.lnd = Some(lnd);
181 }
182 }
183
184 #[cfg(feature = "ldk-node")]
185 {
186 let ldk_node = self.ldk_node.clone().unwrap_or_default().from_env();
187 if ldk_node.bitcoin_network.is_none()
188 && ldk_node.esplora_url.is_none()
189 && ldk_node.electrum_url.is_none()
190 {
191 self.ldk_node = None;
192 } else {
193 self.ldk_node = Some(ldk_node);
194 }
195 }
196
197 #[cfg(feature = "grpc-processor")]
198 {
199 let grpc_processor = self.grpc_processor.clone().unwrap_or_default().from_env();
200 let grpc_processor_configured = self
201 .payment_backend
202 .iter()
203 .any(|backend| backend.backend == PaymentBackendType::GrpcProcessor);
204 if grpc_processor.supported_units.is_empty() && !grpc_processor_configured {
205 self.grpc_processor = None;
206 } else {
207 self.grpc_processor = Some(grpc_processor);
208 }
209 }
210
211 #[cfg(feature = "bdk")]
212 {
213 let bdk = self.bdk.clone().unwrap_or_default().from_env();
214 if bdk.network.is_none() && bdk.mnemonic.is_none() {
215 self.bdk = None;
216 } else {
217 self.bdk = Some(bdk);
218 }
219 }
220
221 for payment_backend in &self.payment_backend {
222 match payment_backend.backend {
223 #[cfg(feature = "cln")]
224 PaymentBackendType::Cln => {}
225 #[cfg(feature = "fakewallet")]
226 PaymentBackendType::FakeWallet => {}
227 #[cfg(feature = "lnd")]
228 PaymentBackendType::Lnd => {}
229 #[cfg(feature = "ldk-node")]
230 PaymentBackendType::LdkNode => {}
231 #[cfg(feature = "grpc-processor")]
232 PaymentBackendType::GrpcProcessor => {}
233 PaymentBackendType::None => {}
234 #[allow(unreachable_patterns)]
235 _ => bail!("Selected payment backend is not enabled in this build"),
236 }
237 }
238
239 let has_payment_backend = self
240 .payment_backend
241 .iter()
242 .any(|backend| backend.backend != PaymentBackendType::None);
243 let has_onchain_backend = self
244 .onchain
245 .as_ref()
246 .map(|onchain| onchain.onchain_backend != OnchainBackend::None)
247 .unwrap_or(false);
248 if !has_payment_backend && !has_onchain_backend {
249 bail!("At least one payment backend must be set");
250 }
251
252 self.validate_backend_pairing()
253 .map_err(|err| anyhow!(err))?;
254
255 Ok(self.clone())
256 }
257
258 #[cfg(feature = "fakewallet")]
259 fn expand_single_fake_wallet_backend_entry(&mut self, fake_wallet: &crate::config::FakeWallet) {
260 let fake_wallet_backend_index = self
261 .payment_backend
262 .iter()
263 .enumerate()
264 .filter_map(|(index, backend)| {
265 (backend.backend == PaymentBackendType::FakeWallet).then_some(index)
266 })
267 .collect::<Vec<_>>();
268
269 if fake_wallet_backend_index.len() != 1 {
270 return;
271 }
272
273 let mut units = Vec::new();
274 for unit in &fake_wallet.supported_units {
275 if !units.contains(unit) {
276 units.push(unit.clone());
277 }
278 }
279
280 if units.is_empty() {
281 return;
282 }
283
284 let index = fake_wallet_backend_index[0];
285 let base_backend = self.payment_backend[index].clone();
286 let expanded_backends = units.into_iter().map(|unit| PaymentBackend {
287 unit,
288 ..base_backend.clone()
289 });
290
291 self.payment_backend
292 .splice(index..=index, expanded_backends);
293 }
294}