fedimint_gateway_server/
rpc_server.rs

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    CREATE_BOLT11_INVOICE_FOR_OPERATOR_ENDPOINT, CREATE_BOLT12_OFFER_FOR_OPERATOR_ENDPOINT,
19    CloseChannelsWithPeerRequest, ConfigPayload, ConnectFedPayload,
20    CreateInvoiceForOperatorPayload, CreateOfferPayload, DepositAddressPayload,
21    DepositAddressRecheckPayload, GATEWAY_INFO_ENDPOINT, GET_BALANCES_ENDPOINT,
22    GET_INVOICE_ENDPOINT, GET_LN_ONCHAIN_ADDRESS_ENDPOINT, GetInvoiceRequest, LEAVE_FED_ENDPOINT,
23    LIST_CHANNELS_ENDPOINT, LIST_TRANSACTIONS_ENDPOINT, LeaveFedPayload, ListTransactionsPayload,
24    MNEMONIC_ENDPOINT, OPEN_CHANNEL_ENDPOINT, OpenChannelRequest,
25    PAY_INVOICE_FOR_OPERATOR_ENDPOINT, PAY_OFFER_FOR_OPERATOR_ENDPOINT, PAYMENT_LOG_ENDPOINT,
26    PAYMENT_SUMMARY_ENDPOINT, PayInvoiceForOperatorPayload, PayOfferPayload, PaymentLogPayload,
27    PaymentSummaryPayload, RECEIVE_ECASH_ENDPOINT, ReceiveEcashPayload, SEND_ONCHAIN_ENDPOINT,
28    SET_FEES_ENDPOINT, SPEND_ECASH_ENDPOINT, STOP_ENDPOINT, SendOnchainRequest, SetFeesPayload,
29    SpendEcashPayload, V1_API_ENDPOINT, WITHDRAW_ENDPOINT, WithdrawPayload,
30};
31use fedimint_gateway_ui::IAdminGateway;
32use fedimint_ln_common::gateway_endpoint_constants::{
33    GET_GATEWAY_ID_ENDPOINT, PAY_INVOICE_ENDPOINT,
34};
35use fedimint_lnv2_common::endpoint_constants::{
36    CREATE_BOLT11_INVOICE_ENDPOINT, ROUTING_INFO_ENDPOINT, SEND_PAYMENT_ENDPOINT,
37};
38use fedimint_lnv2_common::gateway_api::{CreateBolt11InvoicePayload, SendPaymentPayload};
39use fedimint_logging::LOG_GATEWAY;
40use hex::ToHex;
41use serde::de::DeserializeOwned;
42use serde_json::json;
43use tokio::net::TcpListener;
44use tower_http::cors::CorsLayer;
45use tracing::{info, instrument, warn};
46
47use crate::Gateway;
48use crate::error::{GatewayError, LnurlError};
49use crate::iroh_server::{Handlers, start_iroh_endpoint};
50
51/// Creates the webserver's routes and spawns the webserver in a separate task.
52pub async fn run_webserver(gateway: Arc<Gateway>) -> anyhow::Result<()> {
53    let task_group = gateway.task_group.clone();
54    let mut handlers = Handlers::new();
55
56    let routes = routes(gateway.clone(), task_group.clone(), &mut handlers);
57    let ui_routes = fedimint_gateway_ui::router(gateway.clone());
58    let api_v1 = Router::new()
59        .nest(&format!("/{V1_API_ENDPOINT}"), routes.clone())
60        // Backwards compatibility: Continue supporting gateway APIs without versioning
61        .merge(routes)
62        .merge(ui_routes);
63
64    let handle = task_group.make_handle();
65    let shutdown_rx = handle.make_shutdown_rx();
66    let listener = TcpListener::bind(&gateway.listen).await?;
67    let serve = axum::serve(listener, api_v1.into_make_service());
68    task_group.spawn("Gateway Webserver", |_| async {
69        let graceful = serve.with_graceful_shutdown(async {
70            shutdown_rx.await;
71        });
72
73        match graceful.await {
74            Err(err) => {
75                warn!(target: LOG_GATEWAY, err = %err.fmt_compact(), "Error shutting down gatewayd webserver");
76            }
77            _ => {
78                info!(target: LOG_GATEWAY, "Successfully shutdown webserver");
79            }
80        }
81    });
82    info!(target: LOG_GATEWAY, listen = %gateway.listen, "Successfully started webserver");
83
84    start_iroh_endpoint(&gateway, task_group, Arc::new(handlers)).await?;
85
86    Ok(())
87}
88
89/// Extracts the Bearer token from the Authorization header of the request.
90fn extract_bearer_token(request: &Request) -> Result<String, StatusCode> {
91    let headers = request.headers();
92    let auth_header = headers.get(header::AUTHORIZATION);
93    if let Some(header_value) = auth_header {
94        let auth_str = header_value
95            .to_str()
96            .map_err(|_| StatusCode::UNAUTHORIZED)?;
97        let token = auth_str.trim_start_matches("Bearer ").to_string();
98        return Ok(token);
99    }
100
101    Err(StatusCode::UNAUTHORIZED)
102}
103
104/// Middleware to authenticate an incoming request. Routes that are
105/// authenticated with this middleware always require a Bearer token to be
106/// supplied in the Authorization header.
107async fn auth_middleware(
108    Extension(gateway): Extension<Arc<Gateway>>,
109    request: Request,
110    next: Next,
111) -> Result<impl IntoResponse, StatusCode> {
112    let token = extract_bearer_token(&request)?;
113    if bcrypt::verify(token, &gateway.bcrypt_password_hash.to_string())
114        .expect("Bcrypt hash is valid since we just stringified it")
115    {
116        return Ok(next.run(request).await);
117    }
118
119    Err(StatusCode::UNAUTHORIZED)
120}
121
122/// Registers a GET API handler for both the HTTP server and the Iroh
123/// `Endpoint`.
124fn register_get_handler<F, Fut>(
125    handlers: &mut Handlers,
126    route: &str,
127    func: F,
128    is_authenticated: bool,
129    router: Router,
130) -> Router
131where
132    F: Fn(Extension<Arc<Gateway>>) -> Fut + Clone + Send + Sync + 'static,
133    Fut: Future<Output = Result<Json<serde_json::Value>, GatewayError>> + Send + 'static,
134{
135    handlers.add_handler(route, func.clone(), is_authenticated);
136    router.route(route, get(func))
137}
138
139/// Registers a POST API handler for both the HTTP server and the Iroh
140/// `Endpoint`.
141fn register_post_handler<P, F, Fut>(
142    handlers: &mut Handlers,
143    route: &str,
144    func: F,
145    is_authenticated: bool,
146    router: Router,
147) -> Router
148where
149    P: DeserializeOwned + Send + 'static,
150    F: Fn(Extension<Arc<Gateway>>, Json<P>) -> Fut + Clone + Send + Sync + 'static,
151    Fut: Future<Output = Result<Json<serde_json::Value>, GatewayError>> + Send + 'static,
152{
153    handlers.add_handler_with_payload(route, func.clone(), is_authenticated);
154    router.route(route, post(func))
155}
156
157/// Public routes that are used in the LNv1 protocol
158fn lnv1_routes(handlers: &mut Handlers) -> Router {
159    let router = Router::new();
160    let router = register_post_handler(handlers, PAY_INVOICE_ENDPOINT, pay_invoice, false, router);
161    register_get_handler(
162        handlers,
163        GET_GATEWAY_ID_ENDPOINT,
164        get_gateway_id,
165        false,
166        router,
167    )
168}
169
170/// Public routes that are used in the LNv2 protocol
171fn lnv2_routes(handlers: &mut Handlers) -> Router {
172    let router = Router::new();
173    let router = register_post_handler(
174        handlers,
175        ROUTING_INFO_ENDPOINT,
176        routing_info_v2,
177        false,
178        router,
179    );
180    let router = register_post_handler(
181        handlers,
182        SEND_PAYMENT_ENDPOINT,
183        pay_bolt11_invoice_v2,
184        false,
185        router,
186    );
187    let router = register_post_handler(
188        handlers,
189        CREATE_BOLT11_INVOICE_ENDPOINT,
190        create_bolt11_invoice_v2,
191        false,
192        router,
193    );
194    // Verify endpoint does not have the same signature, it is handled separately
195    router.route("/verify/{payment_hash}", get(verify_bolt11_preimage_v2_get))
196}
197
198/// Gateway Webserver Routes. The gateway supports two types of routes
199/// - Always Authenticated: these routes always require a Bearer token. Used by
200///   gateway administrators.
201/// - Un-authenticated: anyone can request these routes. Used by fedimint
202///   clients.
203fn routes(gateway: Arc<Gateway>, task_group: TaskGroup, handlers: &mut Handlers) -> Router {
204    // Public routes on gateway webserver
205    let mut public_routes = register_post_handler(
206        handlers,
207        RECEIVE_ECASH_ENDPOINT,
208        receive_ecash,
209        false,
210        Router::new(),
211    );
212    public_routes = public_routes.merge(lnv1_routes(handlers));
213    public_routes = public_routes.merge(lnv2_routes(handlers));
214
215    // Authenticated routes used for gateway administration
216    let is_authenticated = true;
217    let authenticated_routes = Router::new();
218    let authenticated_routes = register_post_handler(
219        handlers,
220        ADDRESS_ENDPOINT,
221        address,
222        is_authenticated,
223        authenticated_routes,
224    );
225    let authenticated_routes = register_post_handler(
226        handlers,
227        WITHDRAW_ENDPOINT,
228        withdraw,
229        is_authenticated,
230        authenticated_routes,
231    );
232    let authenticated_routes = register_post_handler(
233        handlers,
234        CONNECT_FED_ENDPOINT,
235        connect_fed,
236        is_authenticated,
237        authenticated_routes,
238    );
239    let authenticated_routes = register_post_handler(
240        handlers,
241        LEAVE_FED_ENDPOINT,
242        leave_fed,
243        is_authenticated,
244        authenticated_routes,
245    );
246    let authenticated_routes = register_post_handler(
247        handlers,
248        BACKUP_ENDPOINT,
249        backup,
250        is_authenticated,
251        authenticated_routes,
252    );
253    let authenticated_routes = register_post_handler(
254        handlers,
255        CREATE_BOLT11_INVOICE_FOR_OPERATOR_ENDPOINT,
256        create_invoice_for_operator,
257        is_authenticated,
258        authenticated_routes,
259    );
260    let authenticated_routes = register_post_handler(
261        handlers,
262        CREATE_BOLT12_OFFER_FOR_OPERATOR_ENDPOINT,
263        create_offer_for_operator,
264        is_authenticated,
265        authenticated_routes,
266    );
267    let authenticated_routes = register_post_handler(
268        handlers,
269        PAY_INVOICE_FOR_OPERATOR_ENDPOINT,
270        pay_invoice_operator,
271        is_authenticated,
272        authenticated_routes,
273    );
274    let authenticated_routes = register_post_handler(
275        handlers,
276        PAY_OFFER_FOR_OPERATOR_ENDPOINT,
277        pay_offer_operator,
278        is_authenticated,
279        authenticated_routes,
280    );
281    let authenticated_routes = register_post_handler(
282        handlers,
283        GET_INVOICE_ENDPOINT,
284        get_invoice,
285        is_authenticated,
286        authenticated_routes,
287    );
288    let authenticated_routes = register_get_handler(
289        handlers,
290        GET_LN_ONCHAIN_ADDRESS_ENDPOINT,
291        get_ln_onchain_address,
292        is_authenticated,
293        authenticated_routes,
294    );
295    let authenticated_routes = register_post_handler(
296        handlers,
297        OPEN_CHANNEL_ENDPOINT,
298        open_channel,
299        is_authenticated,
300        authenticated_routes,
301    );
302    let authenticated_routes = register_post_handler(
303        handlers,
304        CLOSE_CHANNELS_WITH_PEER_ENDPOINT,
305        close_channels_with_peer,
306        is_authenticated,
307        authenticated_routes,
308    );
309    let authenticated_routes = register_get_handler(
310        handlers,
311        LIST_CHANNELS_ENDPOINT,
312        list_channels,
313        is_authenticated,
314        authenticated_routes,
315    );
316    let authenticated_routes = register_post_handler(
317        handlers,
318        LIST_TRANSACTIONS_ENDPOINT,
319        list_transactions,
320        is_authenticated,
321        authenticated_routes,
322    );
323    let authenticated_routes = register_post_handler(
324        handlers,
325        SEND_ONCHAIN_ENDPOINT,
326        send_onchain,
327        is_authenticated,
328        authenticated_routes,
329    );
330    let authenticated_routes = register_post_handler(
331        handlers,
332        ADDRESS_RECHECK_ENDPOINT,
333        recheck_address,
334        is_authenticated,
335        authenticated_routes,
336    );
337    let authenticated_routes = register_get_handler(
338        handlers,
339        GET_BALANCES_ENDPOINT,
340        get_balances,
341        is_authenticated,
342        authenticated_routes,
343    );
344    let authenticated_routes = register_post_handler(
345        handlers,
346        SPEND_ECASH_ENDPOINT,
347        spend_ecash,
348        is_authenticated,
349        authenticated_routes,
350    );
351    let authenticated_routes = register_get_handler(
352        handlers,
353        MNEMONIC_ENDPOINT,
354        mnemonic,
355        is_authenticated,
356        authenticated_routes,
357    );
358    // Stop does not have the same function signature, it is handled separately
359    let authenticated_routes = authenticated_routes.route(STOP_ENDPOINT, get(stop));
360    let authenticated_routes = register_post_handler(
361        handlers,
362        PAYMENT_LOG_ENDPOINT,
363        payment_log,
364        is_authenticated,
365        authenticated_routes,
366    );
367    let authenticated_routes = register_post_handler(
368        handlers,
369        PAYMENT_SUMMARY_ENDPOINT,
370        payment_summary,
371        is_authenticated,
372        authenticated_routes,
373    );
374    let authenticated_routes = register_post_handler(
375        handlers,
376        SET_FEES_ENDPOINT,
377        set_fees,
378        is_authenticated,
379        authenticated_routes,
380    );
381    let authenticated_routes = register_post_handler(
382        handlers,
383        CONFIGURATION_ENDPOINT,
384        configuration,
385        is_authenticated,
386        authenticated_routes,
387    );
388    let authenticated_routes = register_get_handler(
389        handlers,
390        GATEWAY_INFO_ENDPOINT,
391        info,
392        is_authenticated,
393        authenticated_routes,
394    );
395    let authenticated_routes = authenticated_routes.layer(middleware::from_fn(auth_middleware));
396
397    Router::new()
398        .merge(public_routes)
399        .merge(authenticated_routes)
400        .layer(Extension(gateway))
401        .layer(Extension(task_group))
402        .layer(CorsLayer::permissive())
403}
404
405/// Display high-level information about the Gateway
406#[instrument(target = LOG_GATEWAY, skip_all, err)]
407async fn info(
408    Extension(gateway): Extension<Arc<Gateway>>,
409) -> Result<Json<serde_json::Value>, GatewayError> {
410    let info = gateway.handle_get_info().await?;
411    Ok(Json(json!(info)))
412}
413
414/// Display high-level information about the Gateway config
415#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
416async fn configuration(
417    Extension(gateway): Extension<Arc<Gateway>>,
418    Json(payload): Json<ConfigPayload>,
419) -> Result<Json<serde_json::Value>, GatewayError> {
420    let gateway_fed_config = gateway
421        .handle_get_federation_config(payload.federation_id)
422        .await?;
423    Ok(Json(json!(gateway_fed_config)))
424}
425
426/// Generate deposit address
427#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
428async fn address(
429    Extension(gateway): Extension<Arc<Gateway>>,
430    Json(payload): Json<DepositAddressPayload>,
431) -> Result<Json<serde_json::Value>, GatewayError> {
432    let address = gateway.handle_address_msg(payload).await?;
433    Ok(Json(json!(address)))
434}
435
436/// Withdraw from a gateway federation.
437#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
438async fn withdraw(
439    Extension(gateway): Extension<Arc<Gateway>>,
440    Json(payload): Json<WithdrawPayload>,
441) -> Result<Json<serde_json::Value>, GatewayError> {
442    let txid = gateway.handle_withdraw_msg(payload).await?;
443    Ok(Json(json!(txid)))
444}
445
446#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
447async fn create_invoice_for_operator(
448    Extension(gateway): Extension<Arc<Gateway>>,
449    Json(payload): Json<CreateInvoiceForOperatorPayload>,
450) -> Result<Json<serde_json::Value>, GatewayError> {
451    let invoice = gateway
452        .handle_create_invoice_for_operator_msg(payload)
453        .await?;
454    Ok(Json(json!(invoice)))
455}
456
457#[instrument(target = LOG_GATEWAY, skip_all, err)]
458async fn pay_invoice_operator(
459    Extension(gateway): Extension<Arc<Gateway>>,
460    Json(payload): Json<PayInvoiceForOperatorPayload>,
461) -> Result<Json<serde_json::Value>, GatewayError> {
462    let preimage = gateway.handle_pay_invoice_for_operator_msg(payload).await?;
463    Ok(Json(json!(preimage.0.encode_hex::<String>())))
464}
465
466#[instrument(target = LOG_GATEWAY, skip_all, err)]
467async fn pay_invoice(
468    Extension(gateway): Extension<Arc<Gateway>>,
469    Json(payload): Json<fedimint_ln_client::pay::PayInvoicePayload>,
470) -> Result<Json<serde_json::Value>, GatewayError> {
471    let preimage = gateway.handle_pay_invoice_msg(payload).await?;
472    Ok(Json(json!(preimage.0.encode_hex::<String>())))
473}
474
475/// Connect a new federation
476#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
477async fn connect_fed(
478    Extension(gateway): Extension<Arc<Gateway>>,
479    Json(payload): Json<ConnectFedPayload>,
480) -> Result<Json<serde_json::Value>, GatewayError> {
481    let fed = gateway.handle_connect_federation(payload).await?;
482    Ok(Json(json!(fed)))
483}
484
485/// Leave a federation
486#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
487async fn leave_fed(
488    Extension(gateway): Extension<Arc<Gateway>>,
489    Json(payload): Json<LeaveFedPayload>,
490) -> Result<Json<serde_json::Value>, GatewayError> {
491    let fed = gateway.handle_leave_federation(payload).await?;
492    Ok(Json(json!(fed)))
493}
494
495/// Backup a gateway actor state
496#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
497async fn backup(
498    Extension(gateway): Extension<Arc<Gateway>>,
499    Json(payload): Json<BackupPayload>,
500) -> Result<Json<serde_json::Value>, GatewayError> {
501    gateway.handle_backup_msg(payload).await?;
502    Ok(Json(json!(())))
503}
504
505#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
506async fn set_fees(
507    Extension(gateway): Extension<Arc<Gateway>>,
508    Json(payload): Json<SetFeesPayload>,
509) -> Result<Json<serde_json::Value>, GatewayError> {
510    gateway.handle_set_fees_msg(payload).await?;
511    Ok(Json(json!(())))
512}
513
514#[instrument(target = LOG_GATEWAY, skip_all, err)]
515async fn get_ln_onchain_address(
516    Extension(gateway): Extension<Arc<Gateway>>,
517) -> Result<Json<serde_json::Value>, GatewayError> {
518    let address = gateway.handle_get_ln_onchain_address_msg().await?;
519    Ok(Json(json!(address.to_string())))
520}
521
522#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
523async fn open_channel(
524    Extension(gateway): Extension<Arc<Gateway>>,
525    Json(payload): Json<OpenChannelRequest>,
526) -> Result<Json<serde_json::Value>, GatewayError> {
527    let funding_txid = gateway.handle_open_channel_msg(payload).await?;
528    Ok(Json(json!(funding_txid)))
529}
530
531#[instrument(target = LOG_GATEWAY, skip_all, err, fields(?payload))]
532async fn close_channels_with_peer(
533    Extension(gateway): Extension<Arc<Gateway>>,
534    Json(payload): Json<CloseChannelsWithPeerRequest>,
535) -> Result<Json<serde_json::Value>, GatewayError> {
536    let response = gateway.handle_close_channels_with_peer_msg(payload).await?;
537    Ok(Json(json!(response)))
538}
539
540#[instrument(target = LOG_GATEWAY, skip_all, err)]
541async fn list_channels(
542    Extension(gateway): Extension<Arc<Gateway>>,
543) -> Result<Json<serde_json::Value>, GatewayError> {
544    let channels = gateway.handle_list_channels_msg().await?;
545    Ok(Json(json!(channels)))
546}
547
548#[instrument(target = LOG_GATEWAY, skip_all, err)]
549async fn send_onchain(
550    Extension(gateway): Extension<Arc<Gateway>>,
551    Json(payload): Json<SendOnchainRequest>,
552) -> Result<Json<serde_json::Value>, GatewayError> {
553    let txid = gateway.handle_send_onchain_msg(payload).await?;
554    Ok(Json(json!(txid)))
555}
556
557#[instrument(target = LOG_GATEWAY, skip_all, err)]
558async fn recheck_address(
559    Extension(gateway): Extension<Arc<Gateway>>,
560    Json(payload): Json<DepositAddressRecheckPayload>,
561) -> Result<Json<serde_json::Value>, GatewayError> {
562    gateway.handle_recheck_address_msg(payload).await?;
563    Ok(Json(json!({})))
564}
565
566#[instrument(target = LOG_GATEWAY, skip_all, err)]
567async fn get_balances(
568    Extension(gateway): Extension<Arc<Gateway>>,
569) -> Result<Json<serde_json::Value>, GatewayError> {
570    let balances = gateway.handle_get_balances_msg().await?;
571    Ok(Json(json!(balances)))
572}
573
574#[instrument(target = LOG_GATEWAY, skip_all, err)]
575async fn get_gateway_id(
576    Extension(gateway): Extension<Arc<Gateway>>,
577) -> Result<Json<serde_json::Value>, GatewayError> {
578    Ok(Json(json!(gateway.gateway_id)))
579}
580
581#[instrument(target = LOG_GATEWAY, skip_all, err)]
582async fn routing_info_v2(
583    Extension(gateway): Extension<Arc<Gateway>>,
584    Json(federation_id): Json<FederationId>,
585) -> Result<Json<serde_json::Value>, GatewayError> {
586    let routing_info = gateway.routing_info_v2(&federation_id).await?;
587    Ok(Json(json!(routing_info)))
588}
589
590#[instrument(target = LOG_GATEWAY, skip_all, err)]
591async fn pay_bolt11_invoice_v2(
592    Extension(gateway): Extension<Arc<Gateway>>,
593    Json(payload): Json<SendPaymentPayload>,
594) -> Result<Json<serde_json::Value>, GatewayError> {
595    let payment_result = gateway.send_payment_v2(payload).await?;
596    Ok(Json(json!(payment_result)))
597}
598
599#[instrument(target = LOG_GATEWAY, skip_all, err)]
600async fn create_bolt11_invoice_v2(
601    Extension(gateway): Extension<Arc<Gateway>>,
602    Json(payload): Json<CreateBolt11InvoicePayload>,
603) -> Result<Json<serde_json::Value>, GatewayError> {
604    let invoice = gateway.create_bolt11_invoice_v2(payload).await?;
605    Ok(Json(json!(invoice)))
606}
607
608pub(crate) async fn verify_bolt11_preimage_v2_get(
609    Extension(gateway): Extension<Arc<Gateway>>,
610    Path(payment_hash): Path<sha256::Hash>,
611    Query(query): Query<HashMap<String, String>>,
612) -> Result<Json<serde_json::Value>, GatewayError> {
613    let response = gateway
614        .verify_bolt11_preimage_v2(payment_hash, query.contains_key("wait"))
615        .await
616        .map_err(|e| LnurlError::internal(anyhow!(e)))?;
617
618    Ok(Json(json!(response)))
619}
620
621#[instrument(target = LOG_GATEWAY, skip_all, err)]
622async fn spend_ecash(
623    Extension(gateway): Extension<Arc<Gateway>>,
624    Json(payload): Json<SpendEcashPayload>,
625) -> Result<Json<serde_json::Value>, GatewayError> {
626    Ok(Json(json!(gateway.handle_spend_ecash_msg(payload).await?)))
627}
628
629#[instrument(target = LOG_GATEWAY, skip_all, err)]
630async fn receive_ecash(
631    Extension(gateway): Extension<Arc<Gateway>>,
632    Json(payload): Json<ReceiveEcashPayload>,
633) -> Result<Json<serde_json::Value>, GatewayError> {
634    Ok(Json(json!(
635        gateway.handle_receive_ecash_msg(payload).await?
636    )))
637}
638
639#[instrument(target = LOG_GATEWAY, skip_all, err)]
640async fn mnemonic(
641    Extension(gateway): Extension<Arc<Gateway>>,
642) -> Result<Json<serde_json::Value>, GatewayError> {
643    let words = gateway.handle_mnemonic_msg().await?;
644    Ok(Json(json!(words)))
645}
646
647#[instrument(target = LOG_GATEWAY, skip_all, err)]
648pub(crate) async fn stop(
649    Extension(task_group): Extension<TaskGroup>,
650    Extension(gateway): Extension<Arc<Gateway>>,
651) -> Result<Json<serde_json::Value>, GatewayError> {
652    gateway.handle_shutdown_msg(task_group).await?;
653    Ok(Json(json!(())))
654}
655
656#[instrument(target = LOG_GATEWAY, skip_all, err)]
657async fn payment_log(
658    Extension(gateway): Extension<Arc<Gateway>>,
659    Json(payload): Json<PaymentLogPayload>,
660) -> Result<Json<serde_json::Value>, GatewayError> {
661    let payment_log = gateway.handle_payment_log_msg(payload).await?;
662    Ok(Json(json!(payment_log)))
663}
664
665#[instrument(target = LOG_GATEWAY, skip_all, err)]
666async fn payment_summary(
667    Extension(gateway): Extension<Arc<Gateway>>,
668    Json(payload): Json<PaymentSummaryPayload>,
669) -> Result<Json<serde_json::Value>, GatewayError> {
670    let payment_summary = gateway.handle_payment_summary_msg(payload).await?;
671    Ok(Json(json!(payment_summary)))
672}
673
674#[instrument(target = LOG_GATEWAY, skip_all, err)]
675async fn get_invoice(
676    Extension(gateway): Extension<Arc<Gateway>>,
677    Json(payload): Json<GetInvoiceRequest>,
678) -> Result<Json<serde_json::Value>, GatewayError> {
679    let invoice = gateway.handle_get_invoice_msg(payload).await?;
680    Ok(Json(json!(invoice)))
681}
682
683#[instrument(target = LOG_GATEWAY, skip_all, err)]
684async fn list_transactions(
685    Extension(gateway): Extension<Arc<Gateway>>,
686    Json(payload): Json<ListTransactionsPayload>,
687) -> Result<Json<serde_json::Value>, GatewayError> {
688    let transactions = gateway.handle_list_transactions_msg(payload).await?;
689    Ok(Json(json!(transactions)))
690}
691
692#[instrument(target = LOG_GATEWAY, skip_all, err)]
693async fn create_offer_for_operator(
694    Extension(gateway): Extension<Arc<Gateway>>,
695    Json(payload): Json<CreateOfferPayload>,
696) -> Result<Json<serde_json::Value>, GatewayError> {
697    let offer = gateway
698        .handle_create_offer_for_operator_msg(payload)
699        .await?;
700    Ok(Json(json!(offer)))
701}
702
703#[instrument(target = LOG_GATEWAY, skip_all, err)]
704async fn pay_offer_operator(
705    Extension(gateway): Extension<Arc<Gateway>>,
706    Json(payload): Json<PayOfferPayload>,
707) -> Result<Json<serde_json::Value>, GatewayError> {
708    let response = gateway.handle_pay_offer_for_operator_msg(payload).await?;
709    Ok(Json(json!(response)))
710}