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