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