1use std::collections::HashMap;
2use std::sync::Arc;
3
4use anyhow::anyhow;
5use axum::extract::{Path, Query, Request};
6use axum::http::{StatusCode, header};
7use axum::middleware::{self, Next};
8use axum::response::IntoResponse;
9use axum::routing::{get, post};
10use axum::{Extension, Json, Router};
11use bitcoin::hashes::sha256;
12use fedimint_core::config::FederationId;
13use fedimint_core::task::TaskGroup;
14use fedimint_core::util::FmtCompact;
15use fedimint_gateway_common::{
16 ADDRESS_ENDPOINT, ADDRESS_RECHECK_ENDPOINT, BACKUP_ENDPOINT, BackupPayload,
17 CLOSE_CHANNELS_WITH_PEER_ENDPOINT, CONFIGURATION_ENDPOINT, CONNECT_FED_ENDPOINT,
18 CONNECT_PEER_ENDPOINT, CREATE_BOLT11_INVOICE_FOR_OPERATOR_ENDPOINT,
19 CREATE_BOLT12_OFFER_FOR_OPERATOR_ENDPOINT, CloseChannelsWithPeerRequest, ConfigPayload,
20 ConnectFedPayload, ConnectPeerRequest, CreateInvoiceForOperatorPayload, CreateOfferPayload,
21 DepositAddressPayload, DepositAddressRecheckPayload, FEDERATION_STATUS_ENDPOINT,
22 FederationStatusRequest, GATEWAY_INFO_ENDPOINT, GET_BALANCES_ENDPOINT, GET_INVOICE_ENDPOINT,
23 GET_LN_ONCHAIN_ADDRESS_ENDPOINT, GetInvoiceRequest, INVITE_CODES_ENDPOINT, LEAVE_FED_ENDPOINT,
24 LIST_CHANNELS_ENDPOINT, LIST_TRANSACTIONS_ENDPOINT, LeaveFedPayload, ListTransactionsPayload,
25 MNEMONIC_ENDPOINT, OPEN_CHANNEL_ENDPOINT, OPEN_CHANNEL_WITH_PUSH_ENDPOINT, OpenChannelRequest,
26 PAY_INVOICE_FOR_OPERATOR_ENDPOINT, PAY_OFFER_FOR_OPERATOR_ENDPOINT, PAYMENT_LOG_ENDPOINT,
27 PAYMENT_SUMMARY_ENDPOINT, PEGIN_FROM_ONCHAIN_ENDPOINT, PayInvoiceForOperatorPayload,
28 PayOfferPayload, PaymentLogPayload, PaymentSummaryPayload, PeginFromOnchainPayload,
29 RECEIVE_ECASH_ENDPOINT, ReceiveEcashPayload, SEND_ONCHAIN_ENDPOINT, SET_CHANNEL_FEES_ENDPOINT,
30 SET_FEES_ENDPOINT, SET_PAYMENT_POLICY_ENDPOINT, SPEND_ECASH_ENDPOINT, STOP_ENDPOINT,
31 SendOnchainRequest, SetChannelFeesRequest, SetFeesPayload, SetMnemonicPayload,
32 SetPaymentPolicyPayload, SpendEcashPayload, V1_API_ENDPOINT, WITHDRAW_ENDPOINT,
33 WITHDRAW_TO_ONCHAIN_ENDPOINT, WithdrawPayload, WithdrawToOnchainPayload,
34};
35use fedimint_gateway_ui::IAdminGateway;
36use fedimint_lightning::ldk::MnemonicSource;
37use fedimint_ln_common::gateway_endpoint_constants::{
38 GET_GATEWAY_ID_ENDPOINT, PAY_INVOICE_ENDPOINT,
39};
40use fedimint_lnurl::LnurlResponse;
41use fedimint_lnv2_common::endpoint_constants::{
42 CREATE_BOLT11_INVOICE_ENDPOINT, ROUTING_INFO_ENDPOINT, SEND_PAYMENT_ENDPOINT,
43};
44use fedimint_lnv2_common::gateway_api::{CreateBolt11InvoicePayload, SendPaymentPayload};
45use fedimint_logging::LOG_GATEWAY;
46use hex::ToHex;
47use serde::de::DeserializeOwned;
48use serde_json::json;
49use tokio::net::TcpListener;
50use tower_http::cors::CorsLayer;
51use tracing::{info, instrument, warn};
52
53use crate::error::{GatewayError, LnurlError, PublicGatewayError};
54use crate::iroh_server::{Handlers, start_iroh_endpoint};
55use crate::{Gateway, GatewayState};
56
57const LIQUIDITY_MANAGER_ROUTES: [&str; 22] = [
60 ADDRESS_ENDPOINT,
61 ADDRESS_RECHECK_ENDPOINT,
62 CLOSE_CHANNELS_WITH_PEER_ENDPOINT,
63 CONFIGURATION_ENDPOINT,
64 CONNECT_PEER_ENDPOINT,
65 CREATE_BOLT11_INVOICE_FOR_OPERATOR_ENDPOINT,
66 CREATE_BOLT12_OFFER_FOR_OPERATOR_ENDPOINT,
67 GATEWAY_INFO_ENDPOINT,
68 GET_BALANCES_ENDPOINT,
69 GET_INVOICE_ENDPOINT,
70 GET_LN_ONCHAIN_ADDRESS_ENDPOINT,
71 INVITE_CODES_ENDPOINT,
72 LIST_CHANNELS_ENDPOINT,
73 LIST_TRANSACTIONS_ENDPOINT,
74 OPEN_CHANNEL_ENDPOINT,
75 PAYMENT_LOG_ENDPOINT,
76 PAYMENT_SUMMARY_ENDPOINT,
77 PEGIN_FROM_ONCHAIN_ENDPOINT,
78 SET_CHANNEL_FEES_ENDPOINT,
79 SET_FEES_ENDPOINT,
80 SET_PAYMENT_POLICY_ENDPOINT,
81 WITHDRAW_TO_ONCHAIN_ENDPOINT,
82];
83
84pub async fn run_webserver(
86 gateway: Arc<Gateway>,
87 mut mnemonic_receiver: tokio::sync::broadcast::Receiver<MnemonicSource>,
88) -> anyhow::Result<()> {
89 let task_group = gateway.task_group.clone();
90 let mut handlers = Handlers::new();
91
92 let routes = routes(gateway.clone(), task_group.clone(), &mut handlers);
93 let ui_routes = fedimint_gateway_ui::router(gateway.clone())
99 .layer(middleware::from_fn(not_configured_middleware))
100 .layer(Extension(gateway.clone()));
101 let api_v1 = Router::new()
102 .nest(&format!("/{V1_API_ENDPOINT}"), routes.clone())
103 .merge(routes)
105 .merge(ui_routes);
106
107 let handle = task_group.make_handle();
108 let shutdown_rx = handle.make_shutdown_rx();
109 let listener = TcpListener::bind(&gateway.listen).await?;
110 let serve = axum::serve(listener, api_v1.into_make_service());
111 task_group.spawn("Gateway Webserver", |_| async {
112 let graceful = serve.with_graceful_shutdown(async {
113 shutdown_rx.await;
114 });
115
116 match graceful.await {
117 Err(err) => {
118 warn!(target: LOG_GATEWAY, err = %err.fmt_compact(), "Error shutting down gatewayd webserver");
119 }
120 _ => {
121 info!(target: LOG_GATEWAY, "Successfully shutdown webserver");
122 }
123 }
124 });
125 info!(target: LOG_GATEWAY, listen = %gateway.listen, "Successfully started webserver");
126
127 if let GatewayState::NotConfigured { .. } = gateway.get_state().await {
130 info!(target: LOG_GATEWAY, "Waiting for the mnemonic to be set before starting iroh loop.");
131 let _ = mnemonic_receiver.recv().await;
132 }
133
134 start_iroh_endpoint(&gateway, task_group, Arc::new(handlers)).await?;
135
136 Ok(())
137}
138
139fn strip_v1_prefix(path: &str) -> &str {
143 match path.strip_prefix(&format!("/{V1_API_ENDPOINT}")) {
144 Some(stripped) if stripped.starts_with('/') => stripped,
145 _ => path,
146 }
147}
148
149fn extract_bearer_token(request: &Request) -> Result<String, StatusCode> {
151 let headers = request.headers();
152 let auth_header = headers.get(header::AUTHORIZATION);
153 if let Some(header_value) = auth_header {
154 let auth_str = header_value
155 .to_str()
156 .map_err(|_| StatusCode::UNAUTHORIZED)?;
157 let token = auth_str.trim_start_matches("Bearer ").to_string();
158 return Ok(token);
159 }
160
161 Err(StatusCode::UNAUTHORIZED)
162}
163
164async fn not_configured_middleware(
165 Extension(gateway): Extension<Arc<Gateway>>,
166 request: Request,
167 next: Next,
168) -> Result<impl IntoResponse, StatusCode> {
169 if matches!(
170 gateway.get_state().await,
171 GatewayState::NotConfigured { .. }
172 ) {
173 let method = request.method().clone();
174 let path = request.uri().path();
175
176 let is_setup_route = fedimint_gateway_ui::is_allowed_setup_route(path);
177
178 if !is_allowed_not_configured_api(&method, path) && !is_setup_route {
179 return Err(StatusCode::NOT_FOUND);
180 }
181 }
182
183 Ok(next.run(request).await)
184}
185
186pub(crate) fn is_allowed_not_configured_api(method: &axum::http::Method, path: &str) -> bool {
187 method == axum::http::Method::POST && strip_v1_prefix(path) == MNEMONIC_ENDPOINT
188}
189
190async fn auth_middleware(
194 Extension(gateway): Extension<Arc<Gateway>>,
195 request: Request,
196 next: Next,
197) -> Result<impl IntoResponse, StatusCode> {
198 let token = extract_bearer_token(&request)?;
199 if bcrypt::verify(token.clone(), &gateway.bcrypt_password_hash)
200 .expect("Bcrypt hash is valid since we just stringified it")
201 {
202 return Ok(next.run(request).await);
203 }
204
205 if let Some(liquidity_manager_password_hash) = &gateway.bcrypt_liquidity_manager_password_hash
207 && bcrypt::verify(token, liquidity_manager_password_hash)
208 .expect("Bcrypt hash is valid since we just stringified it")
209 {
210 let path = strip_v1_prefix(request.uri().path());
211
212 if !LIQUIDITY_MANAGER_ROUTES.contains(&path) {
213 return Err(StatusCode::UNAUTHORIZED);
214 }
215
216 return Ok(next.run(request).await);
217 }
218
219 Err(StatusCode::UNAUTHORIZED)
220}
221
222fn register_get_handler<F, Fut>(
225 handlers: &mut Handlers,
226 route: &str,
227 func: F,
228 is_authenticated: bool,
229 router: Router,
230) -> Router
231where
232 F: Fn(Extension<Arc<Gateway>>) -> Fut + Clone + Send + Sync + 'static,
233 Fut: Future<Output = Result<Json<serde_json::Value>, GatewayError>> + Send + 'static,
234{
235 handlers.add_handler(route, func.clone(), is_authenticated);
236 router.route(route, get(func))
237}
238
239fn register_post_handler<P, F, Fut>(
242 handlers: &mut Handlers,
243 route: &str,
244 func: F,
245 is_authenticated: bool,
246 router: Router,
247) -> Router
248where
249 P: DeserializeOwned + Send + 'static,
250 F: Fn(Extension<Arc<Gateway>>, Json<P>) -> Fut + Clone + Send + Sync + 'static,
251 Fut: Future<Output = Result<Json<serde_json::Value>, GatewayError>> + Send + 'static,
252{
253 handlers.add_handler_with_payload(route, func.clone(), is_authenticated);
254 router.route(route, post(func))
255}
256
257fn lnv1_routes(handlers: &mut Handlers) -> Router {
259 let router = Router::new();
260 let router = register_post_handler(handlers, PAY_INVOICE_ENDPOINT, pay_invoice, false, router);
261 register_get_handler(
262 handlers,
263 GET_GATEWAY_ID_ENDPOINT,
264 get_gateway_id,
265 false,
266 router,
267 )
268}
269
270fn lnv2_routes(handlers: &mut Handlers) -> Router {
272 let router = Router::new();
273 let router = register_post_handler(
274 handlers,
275 ROUTING_INFO_ENDPOINT,
276 routing_info_v2,
277 false,
278 router,
279 );
280 let router = register_post_handler(
281 handlers,
282 SEND_PAYMENT_ENDPOINT,
283 pay_bolt11_invoice_v2,
284 false,
285 router,
286 );
287 let router = register_post_handler(
288 handlers,
289 CREATE_BOLT11_INVOICE_ENDPOINT,
290 create_bolt11_invoice_v2,
291 false,
292 router,
293 );
294 router.route("/verify/{payment_hash}", get(verify_bolt11_preimage_v2_get))
296}
297
298fn public_routes(handlers: &mut Handlers) -> Router {
299 let mut routes = register_post_handler(
300 handlers,
301 RECEIVE_ECASH_ENDPOINT,
302 receive_ecash,
303 false,
304 Router::new(),
305 );
306 routes = routes.merge(lnv1_routes(handlers));
307 routes = routes.merge(lnv2_routes(handlers));
308 register_post_handler(
309 handlers,
310 FEDERATION_STATUS_ENDPOINT,
311 federation_status,
312 false,
313 routes,
314 )
315}
316
317fn routes(gateway: Arc<Gateway>, task_group: TaskGroup, handlers: &mut Handlers) -> Router {
323 let public_routes = public_routes(handlers);
325
326 let is_authenticated = true;
328 let authenticated_routes = Router::new();
329 let authenticated_routes = register_post_handler(
330 handlers,
331 ADDRESS_ENDPOINT,
332 address,
333 is_authenticated,
334 authenticated_routes,
335 );
336 let authenticated_routes = register_post_handler(
337 handlers,
338 WITHDRAW_ENDPOINT,
339 withdraw,
340 is_authenticated,
341 authenticated_routes,
342 );
343 let authenticated_routes = register_post_handler(
344 handlers,
345 WITHDRAW_TO_ONCHAIN_ENDPOINT,
346 withdraw_to_onchain,
347 is_authenticated,
348 authenticated_routes,
349 );
350 let authenticated_routes = register_post_handler(
351 handlers,
352 PEGIN_FROM_ONCHAIN_ENDPOINT,
353 pegin_from_onchain,
354 is_authenticated,
355 authenticated_routes,
356 );
357 let authenticated_routes = register_post_handler(
358 handlers,
359 CONNECT_FED_ENDPOINT,
360 connect_fed,
361 is_authenticated,
362 authenticated_routes,
363 );
364 let authenticated_routes = register_post_handler(
365 handlers,
366 LEAVE_FED_ENDPOINT,
367 leave_fed,
368 is_authenticated,
369 authenticated_routes,
370 );
371 let authenticated_routes = register_post_handler(
372 handlers,
373 BACKUP_ENDPOINT,
374 backup,
375 is_authenticated,
376 authenticated_routes,
377 );
378 let authenticated_routes = register_post_handler(
379 handlers,
380 CREATE_BOLT11_INVOICE_FOR_OPERATOR_ENDPOINT,
381 create_invoice_for_operator,
382 is_authenticated,
383 authenticated_routes,
384 );
385 let authenticated_routes = register_post_handler(
386 handlers,
387 CREATE_BOLT12_OFFER_FOR_OPERATOR_ENDPOINT,
388 create_offer_for_operator,
389 is_authenticated,
390 authenticated_routes,
391 );
392 let authenticated_routes = register_post_handler(
393 handlers,
394 PAY_INVOICE_FOR_OPERATOR_ENDPOINT,
395 pay_invoice_operator,
396 is_authenticated,
397 authenticated_routes,
398 );
399 let authenticated_routes = register_post_handler(
400 handlers,
401 PAY_OFFER_FOR_OPERATOR_ENDPOINT,
402 pay_offer_operator,
403 is_authenticated,
404 authenticated_routes,
405 );
406 let authenticated_routes = register_post_handler(
407 handlers,
408 GET_INVOICE_ENDPOINT,
409 get_invoice,
410 is_authenticated,
411 authenticated_routes,
412 );
413 let authenticated_routes = register_get_handler(
414 handlers,
415 GET_LN_ONCHAIN_ADDRESS_ENDPOINT,
416 get_ln_onchain_address,
417 is_authenticated,
418 authenticated_routes,
419 );
420 let authenticated_routes = register_post_handler(
421 handlers,
422 OPEN_CHANNEL_ENDPOINT,
423 open_channel,
424 is_authenticated,
425 authenticated_routes,
426 );
427 let authenticated_routes = register_post_handler(
428 handlers,
429 CONNECT_PEER_ENDPOINT,
430 connect_peer,
431 is_authenticated,
432 authenticated_routes,
433 );
434 let authenticated_routes = register_post_handler(
435 handlers,
436 OPEN_CHANNEL_WITH_PUSH_ENDPOINT,
437 open_channel_with_push,
438 is_authenticated,
439 authenticated_routes,
440 );
441 let authenticated_routes = register_post_handler(
442 handlers,
443 CLOSE_CHANNELS_WITH_PEER_ENDPOINT,
444 close_channels_with_peer,
445 is_authenticated,
446 authenticated_routes,
447 );
448 let authenticated_routes = register_get_handler(
449 handlers,
450 LIST_CHANNELS_ENDPOINT,
451 list_channels,
452 is_authenticated,
453 authenticated_routes,
454 );
455 let authenticated_routes = register_post_handler(
456 handlers,
457 SET_CHANNEL_FEES_ENDPOINT,
458 set_channel_fees,
459 is_authenticated,
460 authenticated_routes,
461 );
462 let authenticated_routes = register_post_handler(
463 handlers,
464 LIST_TRANSACTIONS_ENDPOINT,
465 list_transactions,
466 is_authenticated,
467 authenticated_routes,
468 );
469 let authenticated_routes = register_post_handler(
470 handlers,
471 SEND_ONCHAIN_ENDPOINT,
472 send_onchain,
473 is_authenticated,
474 authenticated_routes,
475 );
476 let authenticated_routes = register_post_handler(
477 handlers,
478 ADDRESS_RECHECK_ENDPOINT,
479 recheck_address,
480 is_authenticated,
481 authenticated_routes,
482 );
483 let authenticated_routes = register_get_handler(
484 handlers,
485 GET_BALANCES_ENDPOINT,
486 get_balances,
487 is_authenticated,
488 authenticated_routes,
489 );
490 let authenticated_routes = register_post_handler(
491 handlers,
492 SPEND_ECASH_ENDPOINT,
493 spend_ecash,
494 is_authenticated,
495 authenticated_routes,
496 );
497 let authenticated_routes = register_get_handler(
498 handlers,
499 MNEMONIC_ENDPOINT,
500 mnemonic,
501 is_authenticated,
502 authenticated_routes,
503 );
504 let authenticated_routes = authenticated_routes.route(STOP_ENDPOINT, get(stop));
506 let authenticated_routes = register_post_handler(
507 handlers,
508 PAYMENT_LOG_ENDPOINT,
509 payment_log,
510 is_authenticated,
511 authenticated_routes,
512 );
513 let authenticated_routes = register_post_handler(
514 handlers,
515 PAYMENT_SUMMARY_ENDPOINT,
516 payment_summary,
517 is_authenticated,
518 authenticated_routes,
519 );
520 let authenticated_routes = register_post_handler(
521 handlers,
522 SET_FEES_ENDPOINT,
523 set_fees,
524 is_authenticated,
525 authenticated_routes,
526 );
527 let authenticated_routes = register_post_handler(
528 handlers,
529 SET_PAYMENT_POLICY_ENDPOINT,
530 set_payment_policy,
531 is_authenticated,
532 authenticated_routes,
533 );
534 let authenticated_routes = register_post_handler(
535 handlers,
536 CONFIGURATION_ENDPOINT,
537 configuration,
538 is_authenticated,
539 authenticated_routes,
540 );
541 let authenticated_routes = register_get_handler(
542 handlers,
543 GATEWAY_INFO_ENDPOINT,
544 info,
545 is_authenticated,
546 authenticated_routes,
547 );
548 let authenticated_routes = register_post_handler(
549 handlers,
550 MNEMONIC_ENDPOINT,
551 set_mnemonic,
552 is_authenticated,
553 authenticated_routes,
554 );
555 let authenticated_routes = register_get_handler(
556 handlers,
557 INVITE_CODES_ENDPOINT,
558 invite_codes,
559 is_authenticated,
560 authenticated_routes,
561 );
562 let authenticated_routes = authenticated_routes.layer(middleware::from_fn(auth_middleware));
563
564 Router::new()
565 .merge(public_routes)
566 .merge(authenticated_routes)
567 .layer(middleware::from_fn(not_configured_middleware))
568 .layer(Extension(gateway))
569 .layer(Extension(task_group))
570 .layer(CorsLayer::permissive())
571}
572
573#[instrument(target = LOG_GATEWAY, skip_all, err)]
575async fn info(
576 Extension(gateway): Extension<Arc<Gateway>>,
577) -> Result<Json<serde_json::Value>, GatewayError> {
578 let info = gateway.handle_get_info().await?;
579 Ok(Json(json!(info)))
580}
581
582#[instrument(target = LOG_GATEWAY, skip_all, fields(federation_id = %payload.federation_id))]
585async fn federation_status(
586 Extension(gateway): Extension<Arc<Gateway>>,
587 Json(payload): Json<FederationStatusRequest>,
588) -> Result<Json<serde_json::Value>, GatewayError> {
589 let status = gateway
590 .handle_federation_status(payload.federation_id)
591 .await
592 .map_err(PublicGatewayError::Internal)?;
593 Ok(Json(json!(status)))
594}
595
596#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
598async fn configuration(
599 Extension(gateway): Extension<Arc<Gateway>>,
600 Json(payload): Json<ConfigPayload>,
601) -> Result<Json<serde_json::Value>, GatewayError> {
602 let gateway_fed_config = gateway
603 .handle_get_federation_config(payload.federation_id)
604 .await?;
605 Ok(Json(json!(gateway_fed_config)))
606}
607
608#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
610async fn address(
611 Extension(gateway): Extension<Arc<Gateway>>,
612 Json(payload): Json<DepositAddressPayload>,
613) -> Result<Json<serde_json::Value>, GatewayError> {
614 let address = gateway.handle_address_msg(payload).await?;
615 Ok(Json(json!(address)))
616}
617
618#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
620async fn pegin_from_onchain(
621 Extension(gateway): Extension<Arc<Gateway>>,
622 Json(payload): Json<PeginFromOnchainPayload>,
623) -> Result<Json<serde_json::Value>, GatewayError> {
624 let address = gateway.handle_pegin_from_onchain_msg(payload).await?;
625 Ok(Json(json!(address)))
626}
627
628#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
630async fn withdraw(
631 Extension(gateway): Extension<Arc<Gateway>>,
632 Json(payload): Json<WithdrawPayload>,
633) -> Result<Json<serde_json::Value>, GatewayError> {
634 let txid = gateway.handle_withdraw_msg(payload).await?;
635 Ok(Json(json!(txid)))
636}
637
638#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
640async fn withdraw_to_onchain(
641 Extension(gateway): Extension<Arc<Gateway>>,
642 Json(payload): Json<WithdrawToOnchainPayload>,
643) -> Result<Json<serde_json::Value>, GatewayError> {
644 let txid = gateway.handle_withdraw_to_onchain_msg(payload).await?;
645 Ok(Json(json!(txid)))
646}
647
648#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
649async fn create_invoice_for_operator(
650 Extension(gateway): Extension<Arc<Gateway>>,
651 Json(payload): Json<CreateInvoiceForOperatorPayload>,
652) -> Result<Json<serde_json::Value>, GatewayError> {
653 let invoice = gateway
654 .handle_create_invoice_for_operator_msg(payload)
655 .await?;
656 Ok(Json(json!(invoice)))
657}
658
659#[instrument(target = LOG_GATEWAY, skip_all, err)]
660async fn pay_invoice_operator(
661 Extension(gateway): Extension<Arc<Gateway>>,
662 Json(payload): Json<PayInvoiceForOperatorPayload>,
663) -> Result<Json<serde_json::Value>, GatewayError> {
664 let preimage = gateway.handle_pay_invoice_for_operator_msg(payload).await?;
665 Ok(Json(json!(preimage.0.encode_hex::<String>())))
666}
667
668#[instrument(target = LOG_GATEWAY, skip_all, err)]
669async fn pay_invoice(
670 Extension(gateway): Extension<Arc<Gateway>>,
671 Json(payload): Json<fedimint_ln_client::pay::PayInvoicePayload>,
672) -> Result<Json<serde_json::Value>, GatewayError> {
673 let preimage = gateway.handle_pay_invoice_msg(payload).await?;
674 Ok(Json(json!(preimage.0.encode_hex::<String>())))
675}
676
677#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
679async fn connect_fed(
680 Extension(gateway): Extension<Arc<Gateway>>,
681 Json(payload): Json<ConnectFedPayload>,
682) -> Result<Json<serde_json::Value>, GatewayError> {
683 let fed = gateway.handle_connect_federation(payload).await?;
684 Ok(Json(json!(fed)))
685}
686
687#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
689async fn leave_fed(
690 Extension(gateway): Extension<Arc<Gateway>>,
691 Json(payload): Json<LeaveFedPayload>,
692) -> Result<Json<serde_json::Value>, GatewayError> {
693 let fed = gateway.handle_leave_federation(payload).await?;
694 Ok(Json(json!(fed)))
695}
696
697#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
699async fn backup(
700 Extension(gateway): Extension<Arc<Gateway>>,
701 Json(payload): Json<BackupPayload>,
702) -> Result<Json<serde_json::Value>, GatewayError> {
703 gateway.handle_backup_msg(payload).await?;
704 Ok(Json(json!(())))
705}
706
707#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
708async fn set_fees(
709 Extension(gateway): Extension<Arc<Gateway>>,
710 Json(payload): Json<SetFeesPayload>,
711) -> Result<Json<serde_json::Value>, GatewayError> {
712 gateway.handle_set_fees_msg(payload).await?;
713 Ok(Json(json!(())))
714}
715
716#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
717async fn set_payment_policy(
718 Extension(gateway): Extension<Arc<Gateway>>,
719 Json(payload): Json<SetPaymentPolicyPayload>,
720) -> Result<Json<serde_json::Value>, GatewayError> {
721 gateway.handle_set_payment_policy_msg(payload).await?;
722 Ok(Json(json!(())))
723}
724
725#[instrument(target = LOG_GATEWAY, skip_all, err)]
726async fn get_ln_onchain_address(
727 Extension(gateway): Extension<Arc<Gateway>>,
728) -> Result<Json<serde_json::Value>, GatewayError> {
729 let address = gateway.handle_get_ln_onchain_address_msg().await?;
730 Ok(Json(json!(address.to_string())))
731}
732
733#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
734async fn open_channel(
735 Extension(gateway): Extension<Arc<Gateway>>,
736 Json(mut payload): Json<OpenChannelRequest>,
737) -> Result<Json<serde_json::Value>, GatewayError> {
738 payload.push_amount_sats = 0;
739 let funding_txid = gateway.handle_open_channel_msg(payload).await?;
740 Ok(Json(json!(funding_txid)))
741}
742
743#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
744async fn connect_peer(
745 Extension(gateway): Extension<Arc<Gateway>>,
746 Json(payload): Json<ConnectPeerRequest>,
747) -> Result<Json<serde_json::Value>, GatewayError> {
748 gateway.handle_connect_peer_msg(payload).await?;
749 Ok(Json(json!(())))
750}
751
752#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
753async fn open_channel_with_push(
754 Extension(gateway): Extension<Arc<Gateway>>,
755 Json(payload): Json<OpenChannelRequest>,
756) -> Result<Json<serde_json::Value>, GatewayError> {
757 let funding_txid = gateway.handle_open_channel_msg(payload).await?;
758 Ok(Json(json!(funding_txid)))
759}
760
761#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
762async fn close_channels_with_peer(
763 Extension(gateway): Extension<Arc<Gateway>>,
764 Json(payload): Json<CloseChannelsWithPeerRequest>,
765) -> Result<Json<serde_json::Value>, GatewayError> {
766 let response = gateway.handle_close_channels_with_peer_msg(payload).await?;
767 Ok(Json(json!(response)))
768}
769
770#[instrument(target = LOG_GATEWAY, skip_all, err)]
771async fn list_channels(
772 Extension(gateway): Extension<Arc<Gateway>>,
773) -> Result<Json<serde_json::Value>, GatewayError> {
774 let channels = gateway.handle_list_channels_msg().await?;
775 Ok(Json(json!(channels)))
776}
777
778#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
779async fn set_channel_fees(
780 Extension(gateway): Extension<Arc<Gateway>>,
781 Json(payload): Json<SetChannelFeesRequest>,
782) -> Result<Json<serde_json::Value>, GatewayError> {
783 gateway.handle_set_channel_fees_msg(payload).await?;
784 Ok(Json(json!(())))
785}
786
787#[instrument(target = LOG_GATEWAY, skip_all, err)]
788async fn send_onchain(
789 Extension(gateway): Extension<Arc<Gateway>>,
790 Json(payload): Json<SendOnchainRequest>,
791) -> Result<Json<serde_json::Value>, GatewayError> {
792 let txid = gateway.handle_send_onchain_msg(payload).await?;
793 Ok(Json(json!(txid)))
794}
795
796#[instrument(target = LOG_GATEWAY, skip_all, err)]
797async fn recheck_address(
798 Extension(gateway): Extension<Arc<Gateway>>,
799 Json(payload): Json<DepositAddressRecheckPayload>,
800) -> Result<Json<serde_json::Value>, GatewayError> {
801 gateway.handle_recheck_address_msg(payload).await?;
802 Ok(Json(json!({})))
803}
804
805#[instrument(target = LOG_GATEWAY, skip_all, err)]
806async fn get_balances(
807 Extension(gateway): Extension<Arc<Gateway>>,
808) -> Result<Json<serde_json::Value>, GatewayError> {
809 let balances = gateway.handle_get_balances_msg().await?;
810 Ok(Json(json!(balances)))
811}
812
813#[instrument(target = LOG_GATEWAY, skip_all, err)]
814async fn get_gateway_id(
815 Extension(gateway): Extension<Arc<Gateway>>,
816) -> Result<Json<serde_json::Value>, GatewayError> {
817 Ok(Json(json!(gateway.http_gateway_id().await)))
818}
819
820#[instrument(target = LOG_GATEWAY, skip_all, err)]
821async fn routing_info_v2(
822 Extension(gateway): Extension<Arc<Gateway>>,
823 Json(federation_id): Json<FederationId>,
824) -> Result<Json<serde_json::Value>, GatewayError> {
825 let routing_info = gateway.routing_info_v2(&federation_id).await?;
826 Ok(Json(json!(routing_info)))
827}
828
829#[instrument(target = LOG_GATEWAY, skip_all, err)]
830async fn pay_bolt11_invoice_v2(
831 Extension(gateway): Extension<Arc<Gateway>>,
832 Json(payload): Json<SendPaymentPayload>,
833) -> Result<Json<serde_json::Value>, GatewayError> {
834 let payment_result = gateway.send_payment_v2(payload).await?;
835 Ok(Json(json!(payment_result)))
836}
837
838#[instrument(target = LOG_GATEWAY, skip_all, err)]
839async fn create_bolt11_invoice_v2(
840 Extension(gateway): Extension<Arc<Gateway>>,
841 Json(payload): Json<CreateBolt11InvoicePayload>,
842) -> Result<Json<serde_json::Value>, GatewayError> {
843 let invoice = gateway.create_bolt11_invoice_v2(payload).await?;
844 Ok(Json(json!(invoice)))
845}
846
847pub(crate) async fn verify_bolt11_preimage_v2_get(
848 Extension(gateway): Extension<Arc<Gateway>>,
849 Path(payment_hash): Path<sha256::Hash>,
850 Query(query): Query<HashMap<String, String>>,
851) -> Result<Json<serde_json::Value>, GatewayError> {
852 let response = gateway
853 .verify_bolt11_preimage_v2(payment_hash, query.contains_key("wait"))
854 .await
855 .map_err(|e| LnurlError::internal(anyhow!(e)))?;
856
857 Ok(Json(json!(LnurlResponse::Ok(response))))
858}
859
860#[instrument(target = LOG_GATEWAY, skip_all, err)]
861async fn spend_ecash(
862 Extension(gateway): Extension<Arc<Gateway>>,
863 Json(payload): Json<SpendEcashPayload>,
864) -> Result<Json<serde_json::Value>, GatewayError> {
865 Ok(Json(json!(gateway.handle_spend_ecash_msg(payload).await?)))
866}
867
868#[instrument(target = LOG_GATEWAY, skip_all, err)]
869async fn receive_ecash(
870 Extension(gateway): Extension<Arc<Gateway>>,
871 Json(payload): Json<ReceiveEcashPayload>,
872) -> Result<Json<serde_json::Value>, GatewayError> {
873 Ok(Json(json!(
874 gateway.handle_receive_ecash_msg(payload).await?
875 )))
876}
877
878#[instrument(target = LOG_GATEWAY, skip_all, err)]
879async fn mnemonic(
880 Extension(gateway): Extension<Arc<Gateway>>,
881) -> Result<Json<serde_json::Value>, GatewayError> {
882 let words = gateway.handle_mnemonic_msg().await?;
883 Ok(Json(json!(words)))
884}
885
886#[instrument(target = LOG_GATEWAY, skip_all, err)]
887async fn set_mnemonic(
888 Extension(gateway): Extension<Arc<Gateway>>,
889 Json(payload): Json<SetMnemonicPayload>,
890) -> Result<Json<serde_json::Value>, GatewayError> {
891 gateway.handle_set_mnemonic_msg(payload).await?;
892 Ok(Json(json!(())))
893}
894
895#[instrument(target = LOG_GATEWAY, skip_all, err)]
896pub(crate) async fn stop(
897 Extension(task_group): Extension<TaskGroup>,
898 Extension(gateway): Extension<Arc<Gateway>>,
899) -> Result<Json<serde_json::Value>, GatewayError> {
900 gateway.handle_shutdown_msg(task_group).await?;
901 Ok(Json(json!(())))
902}
903
904#[instrument(target = LOG_GATEWAY, skip_all, err)]
911async fn payment_log(
912 Extension(gateway): Extension<Arc<Gateway>>,
913 Json(payload): Json<PaymentLogPayload>,
914) -> Result<Json<serde_json::Value>, GatewayError> {
915 let payment_log = gateway.handle_payment_log_msg(payload).await?;
916 Ok(Json(json!(payment_log)))
917}
918
919#[instrument(target = LOG_GATEWAY, skip_all, err)]
920async fn payment_summary(
921 Extension(gateway): Extension<Arc<Gateway>>,
922 Json(payload): Json<PaymentSummaryPayload>,
923) -> Result<Json<serde_json::Value>, GatewayError> {
924 let payment_summary = gateway.handle_payment_summary_msg(payload).await?;
925 Ok(Json(json!(payment_summary)))
926}
927
928#[instrument(target = LOG_GATEWAY, skip_all, err)]
929async fn get_invoice(
930 Extension(gateway): Extension<Arc<Gateway>>,
931 Json(payload): Json<GetInvoiceRequest>,
932) -> Result<Json<serde_json::Value>, GatewayError> {
933 let invoice = gateway.handle_get_invoice_msg(payload).await?;
934 Ok(Json(json!(invoice)))
935}
936
937#[instrument(target = LOG_GATEWAY, skip_all, err)]
938async fn list_transactions(
939 Extension(gateway): Extension<Arc<Gateway>>,
940 Json(payload): Json<ListTransactionsPayload>,
941) -> Result<Json<serde_json::Value>, GatewayError> {
942 let transactions = gateway.handle_list_transactions_msg(payload).await?;
943 Ok(Json(json!(transactions)))
944}
945
946#[instrument(target = LOG_GATEWAY, skip_all, err)]
947async fn create_offer_for_operator(
948 Extension(gateway): Extension<Arc<Gateway>>,
949 Json(payload): Json<CreateOfferPayload>,
950) -> Result<Json<serde_json::Value>, GatewayError> {
951 let offer = gateway
952 .handle_create_offer_for_operator_msg(payload)
953 .await?;
954 Ok(Json(json!(offer)))
955}
956
957#[instrument(target = LOG_GATEWAY, skip_all, err)]
958async fn pay_offer_operator(
959 Extension(gateway): Extension<Arc<Gateway>>,
960 Json(payload): Json<PayOfferPayload>,
961) -> Result<Json<serde_json::Value>, GatewayError> {
962 let response = gateway.handle_pay_offer_for_operator_msg(payload).await?;
963 Ok(Json(json!(response)))
964}
965
966#[instrument(target = LOG_GATEWAY, skip_all, err)]
967async fn invite_codes(
968 Extension(gateway): Extension<Arc<Gateway>>,
969) -> Result<Json<serde_json::Value>, GatewayError> {
970 let invite_codes = gateway.handle_export_invite_codes().await;
971 Ok(Json(json!(invite_codes)))
972}
973
974#[cfg(test)]
975mod tests;