1#[cfg(feature = "fakewallet")]
2use std::collections::HashMap;
3#[cfg(feature = "fakewallet")]
4use std::collections::HashSet;
5#[cfg(feature = "lnbits")]
6use std::sync::Arc;
7
8#[cfg(feature = "cln")]
9use anyhow::anyhow;
10use async_trait::async_trait;
11use axum::Router;
12#[cfg(feature = "fakewallet")]
13use bip39::rand::{thread_rng, Rng};
14use cdk::cdk_payment::MintPayment;
15#[cfg(feature = "lnbits")]
16use cdk::mint_url::MintUrl;
17use cdk::nuts::CurrencyUnit;
18#[cfg(any(
19 feature = "lnbits",
20 feature = "cln",
21 feature = "lnd",
22 feature = "fakewallet"
23))]
24use cdk::types::FeeReserve;
25#[cfg(feature = "lnbits")]
26use tokio::sync::Mutex;
27
28use crate::config::{self, Settings};
29#[cfg(feature = "cln")]
30use crate::expand_path;
31
32#[async_trait]
33pub trait LnBackendSetup {
34 async fn setup(
35 &self,
36 routers: &mut Vec<Router>,
37 settings: &Settings,
38 unit: CurrencyUnit,
39 ) -> anyhow::Result<impl MintPayment>;
40}
41
42#[cfg(feature = "cln")]
43#[async_trait]
44impl LnBackendSetup for config::Cln {
45 async fn setup(
46 &self,
47 _routers: &mut Vec<Router>,
48 _settings: &Settings,
49 _unit: CurrencyUnit,
50 ) -> anyhow::Result<cdk_cln::Cln> {
51 let cln_socket = expand_path(
52 self.rpc_path
53 .to_str()
54 .ok_or(anyhow!("cln socket not defined"))?,
55 )
56 .ok_or(anyhow!("cln socket not defined"))?;
57
58 let fee_reserve = FeeReserve {
59 min_fee_reserve: self.reserve_fee_min,
60 percent_fee_reserve: self.fee_percent,
61 };
62
63 let cln = cdk_cln::Cln::new(cln_socket, fee_reserve).await?;
64
65 Ok(cln)
66 }
67}
68
69#[cfg(feature = "lnbits")]
70#[async_trait]
71impl LnBackendSetup for config::LNbits {
72 async fn setup(
73 &self,
74 routers: &mut Vec<Router>,
75 settings: &Settings,
76 _unit: CurrencyUnit,
77 ) -> anyhow::Result<cdk_lnbits::LNbits> {
78 let admin_api_key = &self.admin_api_key;
79 let invoice_api_key = &self.invoice_api_key;
80
81 let (sender, receiver) = tokio::sync::mpsc::channel(8);
83 let webhook_endpoint = "/webhook/lnbits/sat/invoice";
84
85 let mint_url: MintUrl = settings.info.url.parse()?;
86 let webhook_url = mint_url.join(webhook_endpoint)?;
87
88 let fee_reserve = FeeReserve {
89 min_fee_reserve: self.reserve_fee_min,
90 percent_fee_reserve: self.fee_percent,
91 };
92
93 let lnbits = cdk_lnbits::LNbits::new(
94 admin_api_key.clone(),
95 invoice_api_key.clone(),
96 self.lnbits_api.clone(),
97 fee_reserve,
98 Arc::new(Mutex::new(Some(receiver))),
99 webhook_url.to_string(),
100 )
101 .await?;
102
103 let router = lnbits
104 .create_invoice_webhook_router(webhook_endpoint, sender)
105 .await?;
106
107 routers.push(router);
108
109 Ok(lnbits)
110 }
111}
112
113#[cfg(feature = "lnd")]
114#[async_trait]
115impl LnBackendSetup for config::Lnd {
116 async fn setup(
117 &self,
118 _routers: &mut Vec<Router>,
119 _settings: &Settings,
120 _unit: CurrencyUnit,
121 ) -> anyhow::Result<cdk_lnd::Lnd> {
122 let address = &self.address;
123 let cert_file = &self.cert_file;
124 let macaroon_file = &self.macaroon_file;
125
126 let fee_reserve = FeeReserve {
127 min_fee_reserve: self.reserve_fee_min,
128 percent_fee_reserve: self.fee_percent,
129 };
130
131 let lnd = cdk_lnd::Lnd::new(
132 address.to_string(),
133 cert_file.clone(),
134 macaroon_file.clone(),
135 fee_reserve,
136 )
137 .await?;
138
139 Ok(lnd)
140 }
141}
142
143#[cfg(feature = "fakewallet")]
144#[async_trait]
145impl LnBackendSetup for config::FakeWallet {
146 async fn setup(
147 &self,
148 _router: &mut Vec<Router>,
149 _settings: &Settings,
150 _unit: CurrencyUnit,
151 ) -> anyhow::Result<cdk_fake_wallet::FakeWallet> {
152 let fee_reserve = FeeReserve {
153 min_fee_reserve: self.reserve_fee_min,
154 percent_fee_reserve: self.fee_percent,
155 };
156
157 let mut rng = thread_rng();
159 let delay_time = rng.gen_range(self.min_delay_time..=self.max_delay_time);
160
161 let fake_wallet = cdk_fake_wallet::FakeWallet::new(
162 fee_reserve,
163 HashMap::default(),
164 HashSet::default(),
165 delay_time,
166 );
167
168 Ok(fake_wallet)
169 }
170}
171
172#[cfg(feature = "grpc-processor")]
173#[async_trait]
174impl LnBackendSetup for config::GrpcProcessor {
175 async fn setup(
176 &self,
177 _routers: &mut Vec<Router>,
178 _settings: &Settings,
179 _unit: CurrencyUnit,
180 ) -> anyhow::Result<cdk_payment_processor::PaymentProcessorClient> {
181 let payment_processor = cdk_payment_processor::PaymentProcessorClient::new(
182 &self.addr,
183 self.port,
184 self.tls_dir.clone(),
185 )
186 .await?;
187
188 Ok(payment_processor)
189 }
190}