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