Skip to main content

lexe_api_core/
def.rs

1//! # API Definitions
2//!
3//! This module, as closely as possible, defines the various APIs exposed by
4//! different services to different clients. Although we do not have
5//! compile-time guarantees that the services exposed exactly match the
6//! definitions below, it is straightforward to compare the Axum routers and
7//! handlers with the definitions below to ensure consistency.
8//!
9//! ## Guidelines
10//!
11//! All API requests and responses should return structs for upgradeability,
12//! e.g. [`UserPkStruct`] instead of [`UserPk`].
13//!
14//! If an API method takes or returns nothing, make the type [`Empty`] and NOT
15//! `()` (unit type). Using `()` makes it impossible to add optional fields in a
16//! backwards-compatible way.
17//!
18//! Each endpoint should be documented with:
19//! - 1) HTTP method e.g. `GET`
20//! - 2) Endpoint e.g. `/v1/file`
21//! - 3) Data used to make the request e.g. `VfsFileId`
22//! - 4) The return type e.g. `MaybeVfsFile`
23//!
24//! The methods below should resemble the data actually sent across the wire.
25//!
26//! [`Empty`]: crate::types::Empty
27//! [`UserPk`]: lexe_common::api::user::UserPk
28//! [`UserPkStruct`]: lexe_common::api::user::UserPkStruct
29
30#![deny(missing_docs)]
31// We don't export our traits currently so auto trait stability is not relevant.
32#![allow(async_fn_in_trait)]
33
34use std::collections::HashSet;
35
36use async_trait::async_trait;
37use bytes::Bytes;
38use lexe_common::api::{
39    MegaId,
40    auth::{
41        BearerAuthRequestWire, BearerAuthResponse, BearerAuthToken,
42        UserSignupRequestWire, UserSignupRequestWireV1,
43    },
44    fiat_rates::FiatRates,
45    models::{
46        SignMsgRequest, SignMsgResponse, Status, VerifyMsgRequest,
47        VerifyMsgResponse,
48    },
49    provision::NodeProvisionRequest,
50    revocable_clients::{
51        CreateRevocableClientRequest, CreateRevocableClientResponse,
52        GetRevocableClients, RevocableClients, UpdateClientRequest,
53        UpdateClientResponse,
54    },
55    test_event::TestEventOp,
56    user::{GetNewScidsRequest, MaybeScid, MaybeUser, Scids, UserPk},
57    version::{CurrentEnclaves, EnclavesToProvision, NodeEnclave},
58};
59#[cfg(doc)]
60use lexe_common::{
61    api::MegaIdStruct,
62    api::models::BroadcastedTxInfo,
63    api::user::NodePkStruct,
64    api::user::{UserPkSet, UserPkStruct},
65    api::version::MeasurementStruct,
66};
67use lexe_crypto::ed25519;
68use lexe_enclave::enclave::Measurement;
69use lightning::events::Event;
70
71#[cfg(doc)]
72use crate::types::payments::{PaymentCreatedIndex, PaymentId};
73use crate::{
74    error::{
75        BackendApiError, GatewayApiError, LspApiError, MegaApiError,
76        NodeApiError, RunnerApiError,
77    },
78    models::{
79        command::{
80            BackupInfo, ClaimGeneratedHumanBitcoinAddress, CloseChannelRequest,
81            CreateInvoiceRequest, CreateInvoiceResponse, CreateOfferRequest,
82            CreateOfferResponse, DebugInfo, EnclavesToProvisionRequest,
83            GetAddressResponse, GetGeneratedUsernameResponse, GetNewPayments,
84            GetUpdatedPaymentMetadata, GetUpdatedPayments, HumanBitcoinAddress,
85            ListChannelsResponse, NodeInfo, NodeInfoV1, OpenChannelRequest,
86            OpenChannelResponse, PayInvoiceRequest, PayInvoiceResponse,
87            PayOfferRequest, PayOfferResponse, PayOnchainRequest,
88            PayOnchainResponse, PaymentCreatedIndexStruct,
89            PaymentCreatedIndexes, PaymentIdStruct,
90            PreflightCloseChannelRequest, PreflightCloseChannelResponse,
91            PreflightOpenChannelRequest, PreflightOpenChannelResponse,
92            PreflightPayInvoiceRequest, PreflightPayInvoiceResponse,
93            PreflightPayOfferRequest, PreflightPayOfferResponse,
94            PreflightPayOnchainRequest, PreflightPayOnchainResponse,
95            ResyncRequest, SetupGDrive, UpdateHumanBitcoinAddress,
96            UpdatePaymentNote, VecPaymentId,
97        },
98        nwc::{
99            CreateNwcClientRequest, CreateNwcClientResponse, DbNwcClient,
100            DbNwcClientFields, GetNwcClients, ListNwcClientResponse,
101            NostrPkStruct, NostrSignedEvent, NwcRequest,
102            UpdateNwcClientRequest, UpdateNwcClientResponse, VecDbNwcClient,
103        },
104        runner::{
105            MegaNodeApiUserEvictRequest, MegaNodeApiUserRunRequest,
106            MegaNodeApiUserRunResponse, UserFinishedRequest,
107            UserLeaseRenewalRequest,
108        },
109    },
110    types::{
111        Empty,
112        lnurl::{
113            LnurlCallbackRequest, LnurlCallbackResponse, LnurlError,
114            LnurlPayRequestWire,
115        },
116        payments::{
117            DbPaymentMetadata, DbPaymentV1, DbPaymentV2, MaybeBasicPaymentV2,
118            MaybeDbPaymentMetadata, MaybeDbPaymentV1, MaybeDbPaymentV2,
119            VecBasicPaymentV1, VecBasicPaymentV2, VecDbPaymentMetadata,
120            VecDbPaymentV1, VecDbPaymentV2,
121        },
122        ports::MegaPorts,
123        sealed_seed::{MaybeSealedSeed, SealedSeed, SealedSeedId},
124        username::UsernameStruct,
125    },
126    vfs::{
127        MaybeVfsFile, VecVfsFile, VfsDirectory, VfsDirectoryList, VfsFile,
128        VfsFileId,
129    },
130};
131
132// TODO(max): To make clear that only upgradeable structs are being serialized,
133// these methods should take e.g. `&UserPkStruct` instead of `UserPk`.
134
135/// Defines the api that the backend exposes to the app (via the gateway).
136pub trait AppBackendApi {
137    /// POST /app/v2/signup [`ed25519::Signed<UserSignupRequestWire>`] ->
138    /// [`Empty`]
139    async fn signup_v2(
140        &self,
141        signed_req: &ed25519::Signed<&UserSignupRequestWire>,
142    ) -> Result<Empty, BackendApiError>;
143
144    /// POST /app/v1/signup [`ed25519::Signed<UserSignupRequestWireV1>`] ->
145    /// [`Empty`]
146    // TODO(phlip9): remove once all installed mobile clients above `app-v0.7.6`
147    #[deprecated = "Use the `signup_v2` API instead"]
148    async fn signup_v1(
149        &self,
150        signed_req: &ed25519::Signed<&UserSignupRequestWireV1>,
151    ) -> Result<Empty, BackendApiError>;
152
153    /// Query which node enclaves the user needs to provision to.
154    ///
155    /// POST /app/v1/enclaves_to_provision
156    /// [`EnclavesToProvisionRequest`] -> [`EnclavesToProvision`]
157    async fn enclaves_to_provision(
158        &self,
159        req: &EnclavesToProvisionRequest,
160        auth: BearerAuthToken,
161    ) -> Result<EnclavesToProvision, BackendApiError>;
162}
163
164/// Defines the api that the gateway directly exposes to the app.
165pub trait AppGatewayApi {
166    /// GET /app/v1/fiat_rates [`Empty`] -> [`FiatRates`]
167    async fn get_fiat_rates(&self) -> Result<FiatRates, GatewayApiError>;
168
169    /// Get the measurement and semver version of the latest node release.
170    ///
171    /// GET /app/v1/latest_release [`Empty`] -> [`NodeEnclave`]
172    #[deprecated(note = "since app-v0.8.1: Use current_releases() instead")]
173    async fn latest_release(&self) -> Result<NodeEnclave, GatewayApiError>;
174
175    /// Get the measurements, enclave machine id and versions of all
176    /// current node enclaves.
177    ///
178    /// GET /app/v1/current_releases [`Empty`] -> [`CurrentEnclaves`]
179    #[deprecated(note = "since app-v0.8.8: Use current_enclaves() instead")]
180    async fn current_releases(
181        &self,
182    ) -> Result<CurrentEnclaves, GatewayApiError>;
183
184    /// Get the measurements, enclave machine id and versions of all
185    /// current node enclaves.
186    ///
187    /// GET /app/v1/current_enclaves [`Empty`] -> [`CurrentEnclaves`]
188    async fn current_enclaves(
189        &self,
190    ) -> Result<CurrentEnclaves, GatewayApiError>;
191}
192
193/// Defines the api that the node exposes to the app during provisioning.
194pub trait AppNodeProvisionApi {
195    /// Provision a node with the given [`Measurement`]. The provisioning node's
196    /// remote attestation will be checked against the given [`Measurement`].
197    ///
198    /// POST /app/provision [`NodeProvisionRequest`] -> [`Empty`]
199    async fn provision(
200        &self,
201        measurement: Measurement,
202        data: NodeProvisionRequest,
203    ) -> Result<Empty, NodeApiError>;
204}
205
206/// Defines the api that the node exposes to the app during normal operation.
207pub trait AppNodeRunApi {
208    /// GET /app/v2/node_info [`Empty`] -> [`NodeInfo`]
209    async fn node_info(&self) -> Result<NodeInfo, NodeApiError>;
210
211    /// GET /app/node_info [`Empty`] -> [`NodeInfoV1`]
212    #[deprecated(note = "since node-v0.9.4: Use node_info instead")]
213    async fn node_info_v1(&self) -> Result<NodeInfoV1, NodeApiError>;
214
215    /// GET /app/debug_info [`Empty`] -> [`DebugInfo`]
216    async fn debug_info(&self) -> Result<DebugInfo, NodeApiError>;
217
218    /// GET /app/list_channels [`Empty`] -> [`ListChannelsResponse`]
219    async fn list_channels(&self)
220    -> Result<ListChannelsResponse, NodeApiError>;
221
222    /// POST /app/sign_message [`SignMsgRequest`] -> [`SignMsgResponse`]
223    ///
224    /// Introduced in `node-v0.6.5`.
225    async fn sign_message(
226        &self,
227        req: SignMsgRequest,
228    ) -> Result<SignMsgResponse, NodeApiError>;
229
230    /// POST /app/verify_message [`VerifyMsgRequest`] -> [`VerifyMsgResponse`]
231    ///
232    /// Introduced in `node-v0.6.5`.
233    async fn verify_message(
234        &self,
235        req: VerifyMsgRequest,
236    ) -> Result<VerifyMsgResponse, NodeApiError>;
237
238    /// POST /app/open_channel [`OpenChannelRequest`] -> [`OpenChannelResponse`]
239    ///
240    /// Opens a channel to the LSP.
241    async fn open_channel(
242        &self,
243        req: OpenChannelRequest,
244    ) -> Result<OpenChannelResponse, NodeApiError>;
245
246    /// POST /app/preflight_open_channel [`PreflightOpenChannelRequest`]
247    ///                                  -> [`PreflightOpenChannelResponse`]
248    ///
249    /// Estimate on-chain fees required for an [`open_channel`] to the LSP.
250    ///
251    /// [`open_channel`]: AppNodeRunApi::open_channel
252    async fn preflight_open_channel(
253        &self,
254        req: PreflightOpenChannelRequest,
255    ) -> Result<PreflightOpenChannelResponse, NodeApiError>;
256
257    /// POST /app/close_channel [`CloseChannelRequest`] -> [`Empty`]
258    ///
259    /// Closes a channel to the LSP.
260    async fn close_channel(
261        &self,
262        req: CloseChannelRequest,
263    ) -> Result<Empty, NodeApiError>;
264
265    /// POST /app/preflight_close_channel [`PreflightCloseChannelRequest`]
266    ///                                   -> [`PreflightCloseChannelResponse`]
267    ///
268    /// Estimate the on-chain fees required for a [`close_channel`].
269    ///
270    /// [`close_channel`]: AppNodeRunApi::close_channel
271    async fn preflight_close_channel(
272        &self,
273        req: PreflightCloseChannelRequest,
274    ) -> Result<PreflightCloseChannelResponse, NodeApiError>;
275
276    /// POST /app/create_invoice [`CreateInvoiceRequest`]
277    ///                          -> [`CreateInvoiceResponse`]
278    async fn create_invoice(
279        &self,
280        req: CreateInvoiceRequest,
281    ) -> Result<CreateInvoiceResponse, NodeApiError>;
282
283    /// POST /app/pay_invoice [`PayInvoiceRequest`] -> [`PayInvoiceResponse`]
284    async fn pay_invoice(
285        &self,
286        req: PayInvoiceRequest,
287    ) -> Result<PayInvoiceResponse, NodeApiError>;
288
289    /// POST /app/preflight_pay_invoice [`PreflightPayInvoiceRequest`]
290    ///                                 -> [`PreflightPayInvoiceResponse`]
291    ///
292    /// This endpoint lets the app ask its node to "pre-flight" a BOLT11 invoice
293    /// payment without going through with the actual payment. We verify as much
294    /// as we can, find a route, and get the fee estimates.
295    async fn preflight_pay_invoice(
296        &self,
297        req: PreflightPayInvoiceRequest,
298    ) -> Result<PreflightPayInvoiceResponse, NodeApiError>;
299
300    /// POST /app/create_offer [`CreateOfferRequest`] -> [`CreateOfferResponse`]
301    ///
302    /// Create a new Lightning offer (BOLT12).
303    //
304    // Added in `node-v0.7.3`.
305    async fn create_offer(
306        &self,
307        req: CreateOfferRequest,
308    ) -> Result<CreateOfferResponse, NodeApiError>;
309
310    /// POST /app/pay_offer [`PayOfferRequest`] -> [`PayOfferResponse`]
311    ///
312    /// Pay a Lightning offer (BOLT12).
313    //
314    // Added in `node-v0.7.4`.
315    async fn pay_offer(
316        &self,
317        req: PayOfferRequest,
318    ) -> Result<PayOfferResponse, NodeApiError>;
319
320    /// POST /app/preflight_pay_offer [`PreflightPayOfferRequest`]
321    ///                               -> [`PreflightPayOfferResponse`]
322    ///
323    /// This endpoint lets the app ask its node to "pre-flight" a Lightning
324    /// offer (BOLT12) payment without going through with the actual payment. We
325    /// verify as much as we can, find a route, and get the fee estimates.
326    //
327    // Added in `node-v0.7.4`.
328    async fn preflight_pay_offer(
329        &self,
330        req: PreflightPayOfferRequest,
331    ) -> Result<PreflightPayOfferResponse, NodeApiError>;
332
333    // TODO(phlip9): BOLT12: /app/request_refund
334
335    /// POST /app/get_address [`Empty`] -> [`GetAddressResponse`]
336    ///
337    /// Returns an address which can be used to receive funds. It is unused
338    /// unless there is an incoming tx and BDK hasn't detected it yet.
339    async fn get_address(&self) -> Result<GetAddressResponse, NodeApiError>;
340
341    /// POST /app/pay_onchain [`PayOnchainRequest`] -> [`PayOnchainResponse`]
342    ///
343    /// Pay bitcoin onchain. If the address is valid and we have sufficient
344    /// onchain funds, this will broadcast a new transaction to the bitcoin
345    /// mempool.
346    async fn pay_onchain(
347        &self,
348        req: PayOnchainRequest,
349    ) -> Result<PayOnchainResponse, NodeApiError>;
350
351    /// POST /app/preflight_pay_onchain [`PreflightPayOnchainRequest`]
352    ///                              -> [`PreflightPayOnchainResponse`]
353    ///
354    /// Returns estimated network fees for a potential onchain payment.
355    async fn preflight_pay_onchain(
356        &self,
357        req: PreflightPayOnchainRequest,
358    ) -> Result<PreflightPayOnchainResponse, NodeApiError>;
359
360    /// GET /app/v1/payments/id [`PaymentIdStruct`] -> [`MaybeBasicPaymentV2`]
361    //
362    // Added in `node-v0.8.10`.
363    async fn get_payment_by_id(
364        &self,
365        req: PaymentIdStruct,
366    ) -> Result<MaybeBasicPaymentV2, NodeApiError>;
367
368    /// POST /app/payments/indexes [`PaymentCreatedIndexes`]
369    ///                         -> [`VecDbPaymentV1`]
370    ///
371    /// Fetch a batch of payments by their [`PaymentCreatedIndex`]s. This is
372    /// typically used by a mobile client to poll for updates on payments
373    /// which it currently has stored locally as "pending"; the intention is
374    /// to check if any of these payments have been updated.
375    //
376    // We use POST because there may be a lot of idxs, which might be too large
377    // to fit inside query parameters.
378    #[deprecated(note = "since app-v0.8.9+29 and sdk-sidecar-v0.3.1: \
379                         Use get_payments_by_ids instead")]
380    async fn get_payments_by_indexes(
381        &self,
382        req: PaymentCreatedIndexes,
383    ) -> Result<VecBasicPaymentV1, NodeApiError>;
384
385    /// GET /app/payments/new [`GetNewPayments`] -> [`VecBasicPaymentV1`]
386    #[deprecated(note = "since app-v0.8.9+29 and sdk-sidecar-v0.3.1: \
387                         Use get_updated_payments instead")]
388    async fn get_new_payments(
389        &self,
390        req: GetNewPayments,
391    ) -> Result<VecBasicPaymentV1, NodeApiError>;
392
393    /// GET /app/payments/updated [`GetUpdatedPayments`]
394    ///                        -> [`VecBasicPaymentV2`]
395    async fn get_updated_payments(
396        &self,
397        req: GetUpdatedPayments,
398    ) -> Result<VecBasicPaymentV2, NodeApiError>;
399
400    /// PUT /app/payments/note [`UpdatePaymentNote`] -> [`Empty`]
401    async fn update_payment_note(
402        &self,
403        req: UpdatePaymentNote,
404    ) -> Result<Empty, NodeApiError>;
405
406    /// Lists all revocable clients.
407    ///
408    /// GET /app/clients [`GetRevocableClients`] -> [`RevocableClients`]
409    // Added in `node-0.7.9`
410    async fn get_revocable_clients(
411        &self,
412        req: GetRevocableClients,
413    ) -> Result<RevocableClients, NodeApiError>;
414
415    /// Creates a new revocable client. Returns the newly issued client cert.
416    ///
417    /// POST /app/clients [`CreateRevocableClientRequest`]
418    ///                   -> [`CreateRevocableClientResponse`]
419    // Added in `node-0.7.9`
420    async fn create_revocable_client(
421        &self,
422        req: CreateRevocableClientRequest,
423    ) -> Result<CreateRevocableClientResponse, NodeApiError>;
424
425    /// Updates this revocable client. Returns the updated client.
426    ///
427    /// PUT /app/clients [`UpdateClientRequest`] -> [`UpdateClientResponse`]
428    // Added in `node-0.7.9`
429    async fn update_revocable_client(
430        &self,
431        req: UpdateClientRequest,
432    ) -> Result<UpdateClientResponse, NodeApiError>;
433
434    /// List all broadcasted transactions.
435    ///
436    /// GET /app/list_broadcasted_txs [`Empty`] -> [`Vec<BroadcastedTxInfo>`]
437    async fn list_broadcasted_txs(
438        &self,
439    ) -> Result<serde_json::Value, NodeApiError>;
440
441    /// Get the current status of Node backup.
442    ///
443    /// GET /app/backup [`Empty`] -> [`BackupInfo`]
444    async fn backup_info(&self) -> Result<BackupInfo, NodeApiError>;
445
446    /// Setup GDrive backup.
447    ///
448    /// POST /app/backup/gdrive [`SetupGDrive`] -> [`Empty`]
449    async fn setup_gdrive(
450        &self,
451        req: SetupGDrive,
452    ) -> Result<Empty, NodeApiError>;
453
454    /// Get current user's human Bitcoin address.
455    ///
456    /// GET /app/human_bitcoin_address [`Empty`] -> [`HumanBitcoinAddress`]
457    async fn get_human_bitcoin_address(
458        &self,
459    ) -> Result<HumanBitcoinAddress, NodeApiError>;
460
461    /// Update current user's human Bitcoin address.
462    ///
463    /// PUT /app/human_bitcoin_address [`UsernameStruct`] ->
464    /// [`HumanBitcoinAddress`]
465    async fn update_human_bitcoin_address(
466        &self,
467        req: UsernameStruct,
468    ) -> Result<HumanBitcoinAddress, NodeApiError>;
469
470    /// GET /app/payment_address [`Empty`] -> [`HumanBitcoinAddress`]
471    #[deprecated(note = "since app-v0.9.3 and sdk-sidecar-v0.4.2: \
472                         Use get_human_bitcoin_address instead")]
473    async fn get_payment_address(
474        &self,
475    ) -> Result<HumanBitcoinAddress, NodeApiError> {
476        self.get_human_bitcoin_address().await
477    }
478
479    /// PUT /app/payment_address [`UsernameStruct`] -> [`HumanBitcoinAddress`]
480    #[deprecated(note = "since app-v0.9.3 and sdk-sidecar-v0.4.2: \
481                         Use update_human_bitcoin_address instead")]
482    async fn update_payment_address(
483        &self,
484        req: UsernameStruct,
485    ) -> Result<HumanBitcoinAddress, NodeApiError> {
486        self.update_human_bitcoin_address(req).await
487    }
488
489    /// List NWC clients for the current user.
490    /// Returns client info without sensitive data (no connection strings).
491    ///
492    /// GET /app/nwc_clients [`Empty`] -> [`ListNwcClientResponse`]
493    async fn list_nwc_clients(
494        &self,
495    ) -> Result<ListNwcClientResponse, NodeApiError>;
496
497    /// Create a new NWC client.
498    /// Generates new keys and returns the connection string.
499    ///
500    /// POST /app/nwc_clients [`CreateNwcClientRequest`]
501    ///                    -> [`CreateNwcClientResponse`]
502    async fn create_nwc_client(
503        &self,
504        req: CreateNwcClientRequest,
505    ) -> Result<CreateNwcClientResponse, NodeApiError>;
506
507    /// Update an existing NWC client's label.
508    ///
509    /// PUT /app/nwc_clients [`UpdateNwcClientRequest`]
510    ///                   -> [`UpdateNwcClientResponse`]
511    async fn update_nwc_client(
512        &self,
513        req: UpdateNwcClientRequest,
514    ) -> Result<UpdateNwcClientResponse, NodeApiError>;
515
516    /// Delete an NWC client given its nostr client public key.
517    ///
518    /// DELETE /app/nwc_clients [`NostrPkStruct`] -> [`Empty`]
519    async fn delete_nwc_client(
520        &self,
521        req: NostrPkStruct,
522    ) -> Result<Empty, NodeApiError>;
523}
524
525/// The bearer auth API exposed by the backend (sometimes via the gateway) to
526/// various consumers. This trait is defined separately from the
527/// usual `ConsumerServiceApi` traits because `BearerAuthenticator` needs to
528/// abstract over a generic implementor of [`BearerAuthBackendApi`].
529#[async_trait]
530pub trait BearerAuthBackendApi {
531    /// POST /CONSUMER/bearer_auth [`ed25519::Signed<BearerAuthRequest>`]
532    ///                         -> [`BearerAuthResponse`]
533    ///
534    /// Valid values for `CONSUMER` are: "app", "node" and "lsp".
535    async fn bearer_auth(
536        &self,
537        signed_req: &ed25519::Signed<&BearerAuthRequestWire>,
538    ) -> Result<BearerAuthResponse, BackendApiError>;
539}
540
541/// Defines the API the mega node exposes to the Lexe operators.
542///
543/// NOTE: For performance, this API does not use TLS! This API should only
544/// contain methods for limited operational and lifecycle management endpoints.
545pub trait LexeMegaApi {
546    /// POST /lexe/run_user [`MegaNodeApiUserRunRequest`]
547    ///                  -> [`MegaNodeApiUserRunResponse`]
548    async fn run_user(
549        &self,
550        req: MegaNodeApiUserRunRequest,
551    ) -> Result<MegaNodeApiUserRunResponse, MegaApiError>;
552
553    /// POST /lexe/evict_user [`MegaNodeApiUserEvictRequest`] -> [`Empty`]
554    async fn evict_user(
555        &self,
556        req: MegaNodeApiUserEvictRequest,
557    ) -> Result<Empty, MegaApiError>;
558
559    /// GET /lexe/status [`MegaIdStruct`] -> [`Status`]
560    async fn status_mega(
561        &self,
562        mega_id: MegaId,
563    ) -> Result<Status, MegaApiError>;
564
565    /// POST /lexe/shutdown [`Empty`] -> [`Empty`]
566    async fn shutdown_mega(&self) -> Result<Empty, MegaApiError>;
567}
568
569/// Defines the API the node exposes to the Lexe operators at run time.
570///
571/// NOTE: For performance, this API does not use TLS! This API should only
572/// contain methods for limited operational and lifecycle management endpoints.
573pub trait LexeNodeRunApi {
574    /// GET /lexe/status [`UserPkStruct`] -> [`Status`]
575    async fn status_run(&self, user_pk: UserPk)
576    -> Result<Status, NodeApiError>;
577
578    /// POST /lexe/resync [`ResyncRequest`] -> [`Empty`]
579    ///
580    /// Triggers an immediate resync of BDK and LDK. Optionally full sync the
581    /// BDK wallet. Returns only once sync has either completed or timed out.
582    async fn resync(&self, req: ResyncRequest) -> Result<Empty, NodeApiError>;
583
584    /// POST /lexe/test_event [`TestEventOp`] -> [`Empty`]
585    ///
586    /// Calls the corresponding `TestEventReceiver` method.
587    /// This endpoint can only be called by one caller at any one time.
588    /// Does nothing and returns an error if called in prod.
589    async fn test_event(&self, op: &TestEventOp)
590    -> Result<Empty, NodeApiError>;
591
592    /// GET /lexe/shutdown [`UserPkStruct`] -> [`Empty`]
593    ///
594    /// Not to be confused with [`LexeMegaApi::shutdown_mega`].
595    async fn shutdown_run(
596        &self,
597        user_pk: UserPk,
598    ) -> Result<Empty, NodeApiError>;
599
600    /// POST /lexe/create_invoice [`CreateInvoiceRequest`] ->
601    /// [`CreateInvoiceResponse`]
602    async fn create_invoice(
603        &self,
604        req: CreateInvoiceRequest,
605    ) -> Result<CreateInvoiceResponse, NodeApiError>;
606
607    /// POST /lexe/nwc_request [`NwcRequest`] -> [`NostrSignedEvent`]
608    ///
609    /// Processes an encrypted NWC request from the nostr-bridge.
610    /// The node will decrypt the request, execute the command, and return
611    /// an encrypted response.
612    async fn nwc_request(
613        &self,
614        req: NwcRequest,
615    ) -> Result<NostrSignedEvent, NodeApiError>;
616}
617
618/// Defines the API the runner exposes to mega nodes.
619pub trait MegaRunnerApi {
620    /// POST /mega/ready [`MegaPorts`] -> [`Empty`]
621    ///
622    /// Indicates this mega node is initialized and ready to load user nodes.
623    async fn mega_ready(
624        &self,
625        ports: &MegaPorts,
626    ) -> Result<Empty, RunnerApiError>;
627
628    /// POST /mega/activity [`UserPkSet`] -> [`Empty`]
629    ///
630    /// Indicates the meganode received some activity from its users.
631    async fn activity(
632        &self,
633        user_pks: HashSet<UserPk>,
634    ) -> Result<Empty, RunnerApiError>;
635
636    /// POST /mega/user_finished [`UserFinishedRequest`] -> [`Empty`]
637    ///
638    /// Notifies the runner that a user has shut down,
639    /// and that the user's lease can be terminated.
640    async fn user_finished(
641        &self,
642        req: &UserFinishedRequest,
643    ) -> Result<Empty, RunnerApiError>;
644}
645
646/// Defines the api that the backend exposes to the node.
647pub trait NodeBackendApi {
648    // --- Unauthenticated --- //
649
650    /// GET /node/v1/user [`UserPkStruct`] -> [`MaybeUser`]
651    async fn get_user(
652        &self,
653        user_pk: UserPk,
654    ) -> Result<MaybeUser, BackendApiError>;
655
656    /// GET /node/v1/sealed_seed [`SealedSeedId`] -> [`MaybeSealedSeed`]
657    async fn get_sealed_seed(
658        &self,
659        data: &SealedSeedId,
660    ) -> Result<MaybeSealedSeed, BackendApiError>;
661
662    // --- Bearer authentication required --- //
663
664    /// PUT /node/v1/sealed_seed [`SealedSeed`] -> [`Empty`]
665    ///
666    /// Idempotent: does nothing if the [`SealedSeedId`] already exists.
667    async fn create_sealed_seed(
668        &self,
669        data: &SealedSeed,
670        auth: BearerAuthToken,
671    ) -> Result<Empty, BackendApiError>;
672
673    /// Delete all sealed seeds which have the given measurement and the user_pk
674    /// of the authenticated user.
675    ///
676    /// DELETE /node/v1/sealed_seed [`MeasurementStruct`] -> [`Empty`]
677    async fn delete_sealed_seeds(
678        &self,
679        measurement: Measurement,
680        auth: BearerAuthToken,
681    ) -> Result<Empty, BackendApiError>;
682
683    /// GET /node/v1/scids [`Empty`] -> [`Scids`]
684    async fn get_scids(
685        &self,
686        auth: BearerAuthToken,
687    ) -> Result<Scids, BackendApiError>;
688
689    /// GET /node/v1/scid [`Empty`] -> [`MaybeScid`]
690    // NOTE: Keep this def around until we can remove the backend handler.
691    #[deprecated(note = "since lsp-v0.7.3: Use multi scid version instead")]
692    async fn get_scid(
693        &self,
694        auth: BearerAuthToken,
695    ) -> Result<MaybeScid, BackendApiError>;
696
697    /// GET /node/v1/file [`VfsFileId`] -> [`MaybeVfsFile`]
698    #[deprecated(note = "since node-v0.8.5: Use get_file instead")]
699    async fn get_file_v1(
700        &self,
701        file_id: &VfsFileId,
702        auth: BearerAuthToken,
703    ) -> Result<MaybeVfsFile, BackendApiError>;
704
705    /// GET /node/v2/file [`VfsFileId`] -> [`Bytes`] ([`VfsFile::data`])
706    async fn get_file(
707        &self,
708        file_id: &VfsFileId,
709        token: BearerAuthToken,
710    ) -> Result<Bytes, BackendApiError>;
711
712    /// POST /node/v1/file [`VfsFile`] -> [`Empty`]
713    #[deprecated(note = "since node-v0.8.5: Use create_file instead")]
714    async fn create_file_v1(
715        &self,
716        file: &VfsFile,
717        auth: BearerAuthToken,
718    ) -> Result<Empty, BackendApiError>;
719
720    /// POST /node/v2/file [`VfsFileId`] (query) + [`Bytes`] (body) -> [`Empty`]
721    async fn create_file(
722        &self,
723        file_id: &VfsFileId,
724        data: bytes::Bytes,
725        auth: BearerAuthToken,
726    ) -> Result<Empty, BackendApiError>;
727
728    /// PUT /node/v1/file [`VfsFile`] -> [`Empty`]
729    #[deprecated(note = "since node-v0.8.5: Use upsert_file instead")]
730    async fn upsert_file_v1(
731        &self,
732        file: &VfsFile,
733        auth: BearerAuthToken,
734    ) -> Result<Empty, BackendApiError>;
735
736    /// PUT /node/v2/file [`VfsFileId`] (query) + [`Bytes`] (body) -> [`Empty`]
737    async fn upsert_file(
738        &self,
739        file_id: &VfsFileId,
740        data: bytes::Bytes,
741        auth: BearerAuthToken,
742    ) -> Result<Empty, BackendApiError>;
743
744    /// DELETE /node/v1/file [`VfsFileId`] -> [`Empty`]
745    ///
746    /// Returns [`Ok`] only if exactly one row was deleted.
747    async fn delete_file(
748        &self,
749        file_id: &VfsFileId,
750        auth: BearerAuthToken,
751    ) -> Result<Empty, BackendApiError>;
752
753    /// GET /node/v1/directory [`VfsDirectory`] -> [`VecVfsFile`]
754    #[deprecated(note = "since node-v0.8.5: Use list_directory instead")]
755    async fn get_directory_v1(
756        &self,
757        dir: &VfsDirectory,
758        auth: BearerAuthToken,
759    ) -> Result<VecVfsFile, BackendApiError>;
760
761    /// GET /node/v2/directory [`VfsDirectory`] -> [`VecVfsFile`]
762    async fn list_directory(
763        &self,
764        dir: &VfsDirectory,
765        auth: BearerAuthToken,
766    ) -> Result<VfsDirectoryList, BackendApiError>;
767
768    /// GET /node/v1/payments [`PaymentCreatedIndexStruct`]
769    ///                    -> [`MaybeDbPaymentV1`]
770    #[deprecated(note = "since node-v0.8.8: Use get_payment_by_index instead")]
771    async fn get_payment_by_index_v1(
772        &self,
773        req: PaymentCreatedIndexStruct,
774        auth: BearerAuthToken,
775    ) -> Result<MaybeDbPaymentV1, BackendApiError>;
776
777    /// POST /node/v1/payments [`DbPaymentV1`] -> [`Empty`]
778    #[deprecated(note = "since node-v0.8.10: Use upsert_payment instead")]
779    async fn create_payment(
780        &self,
781        payment: DbPaymentV1,
782        auth: BearerAuthToken,
783    ) -> Result<Empty, BackendApiError>;
784
785    /// PUT /node/v1/payments [`DbPaymentV1`] -> [`Empty`]
786    #[deprecated(note = "since node-v0.8.8: Use upsert_payment instead")]
787    async fn upsert_payment_v1(
788        &self,
789        payment: DbPaymentV1,
790        auth: BearerAuthToken,
791    ) -> Result<Empty, BackendApiError>;
792
793    /// PUT /node/v2/payments [`DbPaymentV2`] -> [`Empty`]
794    async fn upsert_payment(
795        &self,
796        payment: DbPaymentV2,
797        auth: BearerAuthToken,
798    ) -> Result<Empty, BackendApiError>;
799
800    /// GET /node/v1/payments/id [`PaymentIdStruct`] -> [`MaybeDbPaymentV1`]
801    #[deprecated(note = "since node-v0.8.10: Use get_payment_by_id instead")]
802    async fn get_payment_by_id_v1(
803        &self,
804        req: PaymentIdStruct,
805        auth: BearerAuthToken,
806    ) -> Result<MaybeDbPaymentV1, BackendApiError>;
807
808    /// GET /node/v2/payments/id [`PaymentIdStruct`] -> [`MaybeDbPaymentV2`]
809    async fn get_payment_by_id(
810        &self,
811        req: PaymentIdStruct,
812        auth: BearerAuthToken,
813    ) -> Result<MaybeDbPaymentV2, BackendApiError>;
814
815    /// GET /node/v1/payments/index [`PaymentCreatedIndexStruct`]
816    ///                          -> [`MaybeDbPaymentV1`]
817    #[deprecated(note = "since node-v0.8.10: Use get_payment_by_id instead")]
818    async fn get_payment_by_index(
819        &self,
820        req: PaymentCreatedIndexStruct,
821        auth: BearerAuthToken,
822    ) -> Result<MaybeDbPaymentV1, BackendApiError>;
823
824    /// PUT /node/v1/payments/batch [`VecDbPaymentV1`] -> [`Empty`]
825    ///
826    /// ACID endpoint for upserting a batch of payments.
827    #[deprecated(note = "since node-v0.8.8: Use upsert_payment_batch instead")]
828    async fn upsert_payment_batch_v1(
829        &self,
830        payments: VecDbPaymentV1,
831        auth: BearerAuthToken,
832    ) -> Result<Empty, BackendApiError>;
833
834    /// PUT /node/v2/payments/batch [`VecDbPaymentV2`] -> [`Empty`]
835    ///
836    /// ACID endpoint for upserting a batch of payments.
837    async fn upsert_payment_batch(
838        &self,
839        payments: VecDbPaymentV2,
840        auth: BearerAuthToken,
841    ) -> Result<Empty, BackendApiError>;
842
843    /// POST /node/v1/payments/indexes [`PaymentCreatedIndexes`]
844    ///                             -> [`VecDbPaymentV1`]
845    ///
846    /// Fetch a batch of payments by their [`PaymentCreatedIndex`]s. This is
847    /// typically used by a mobile client to poll for updates on payments
848    /// which it currently has stored locally as "pending"; the intention is
849    /// to check if any of these payments have been updated.
850    //
851    // We use POST because there may be a lot of idxs, which might be too large
852    // to fit inside query parameters.
853    #[deprecated(note = "since node-v0.8.10: Use get_payments_by_ids instead")]
854    async fn get_payments_by_indexes(
855        &self,
856        req: PaymentCreatedIndexes,
857        auth: BearerAuthToken,
858    ) -> Result<VecDbPaymentV1, BackendApiError>;
859
860    /// POST /node/v1/payments/ids [`VecPaymentId`]
861    ///                         -> [`VecDbPaymentV2`]
862    ///
863    /// Fetch a batch of payments by their [`PaymentId`]s.
864    //
865    // We use POST because there may be a lot of ids,
866    // which might be too large to fit inside query params.
867    async fn get_payments_by_ids(
868        &self,
869        req: VecPaymentId,
870        auth: BearerAuthToken,
871    ) -> Result<VecDbPaymentV2, BackendApiError>;
872
873    /// GET /node/v1/payments/new [`GetNewPayments`] -> [`VecDbPaymentV1`]
874    ///
875    /// Sync a batch of new payments to local storage, optionally starting from
876    /// a known [`PaymentCreatedIndex`] (exclusive).
877    /// Results are in ascending order, by `(created_at, payment_id)`.
878    /// See [`GetNewPayments`] for more info.
879    #[deprecated(note = "since app-v0.8.9+29 and sdk-sidecar-v0.3.1: \
880                         Use get_updated_payments instead")]
881    // NOTE: This fn is used in the app->node handler for /app/payments/new, so
882    // the node->backend client code must remain until all app and sdk-sidecar
883    // clients have been updated.
884    async fn get_new_payments(
885        &self,
886        req: GetNewPayments,
887        auth: BearerAuthToken,
888    ) -> Result<VecDbPaymentV1, BackendApiError>;
889
890    /// GET /node/v1/payments/updated [`GetUpdatedPayments`]
891    ///                            -> [`VecDbPaymentV2`]
892    async fn get_updated_payments(
893        &self,
894        req: GetUpdatedPayments,
895        auth: BearerAuthToken,
896    ) -> Result<VecDbPaymentV2, BackendApiError>;
897
898    /// GET /node/v1/payments/pending -> [`VecDbPaymentV1`]
899    ///
900    /// Fetches all pending payments.
901    #[deprecated(note = "since node-v0.8.10: Use get_pending_payments instead")]
902    async fn get_pending_payments_v1(
903        &self,
904        auth: BearerAuthToken,
905    ) -> Result<VecDbPaymentV1, BackendApiError>;
906
907    /// GET /node/v2/payments/pending -> [`VecDbPaymentV2`]
908    ///
909    /// Fetches all pending payments.
910    async fn get_pending_payments(
911        &self,
912        auth: BearerAuthToken,
913    ) -> Result<VecDbPaymentV2, BackendApiError>;
914
915    /// GET /node/v1/payments/final -> [`VecPaymentId`]
916    ///
917    /// Fetches the IDs of all finalized payments.
918    #[deprecated(note = "since node-v0.8.8")]
919    async fn get_finalized_payment_ids(
920        &self,
921        auth: BearerAuthToken,
922    ) -> Result<VecPaymentId, BackendApiError>;
923
924    /// PUT /node/v1/payments/metadata [`DbPaymentMetadata`] -> [`Empty`]
925    async fn upsert_payment_metadata(
926        &self,
927        metadata: DbPaymentMetadata,
928        auth: BearerAuthToken,
929    ) -> Result<Empty, BackendApiError>;
930
931    /// PUT /node/v1/payments/metadata/batch [`VecDbPaymentMetadata`]
932    ///                                   -> [`Empty`]
933    ///
934    /// ACID endpoint for upserting a batch of payments metadata.
935    async fn upsert_payment_metadata_batch(
936        &self,
937        payments: VecDbPaymentMetadata,
938        auth: BearerAuthToken,
939    ) -> Result<Empty, BackendApiError>;
940
941    /// GET /node/v1/payments/metadata/id [`PaymentIdStruct`]
942    ///                                -> [`MaybeDbPaymentMetadata`]
943    ///
944    /// Fetch a payment metadata by its [`PaymentId`].
945    async fn get_payment_metadata_by_id(
946        &self,
947        req: PaymentIdStruct,
948        token: BearerAuthToken,
949    ) -> Result<MaybeDbPaymentMetadata, BackendApiError>;
950
951    /// POST /node/v1/payments/metadata/ids [`VecPaymentId`]
952    ///                                  -> [`VecDbPaymentMetadata`]
953    ///
954    /// Fetch a batch of payment metadata by their [`PaymentId`]s.
955    //
956    // We use POST because there may be a lot of ids,
957    // which might be too large to fit inside query params.
958    async fn get_payment_metadata_by_ids(
959        &self,
960        req: VecPaymentId,
961        token: BearerAuthToken,
962    ) -> Result<VecDbPaymentMetadata, BackendApiError>;
963
964    /// GET /node/v1/payments/metadata/updated [`GetUpdatedPaymentMetadata`]
965    ///                                     -> [`VecDbPaymentMetadata`]
966    ///
967    /// Get a batch of payment metadata in asc `(updated_at, payment_id)` order.
968    async fn get_updated_payment_metadata(
969        &self,
970        req: GetUpdatedPaymentMetadata,
971        auth: BearerAuthToken,
972    ) -> Result<VecDbPaymentMetadata, BackendApiError>;
973
974    /// PUT /node/v1/human_bitcoin_address [`UpdateHumanBitcoinAddress`]
975    ///                         -> [`HumanBitcoinAddress`]
976    ///
977    /// Updates the human Bitcoin address (username and offer) of the given
978    /// node.
979    async fn update_human_bitcoin_address(
980        &self,
981        req: UpdateHumanBitcoinAddress,
982        auth: BearerAuthToken,
983    ) -> Result<HumanBitcoinAddress, BackendApiError>;
984
985    /// PUT /node/v1/payment_address [`UpdateHumanBitcoinAddress`]
986    ///                           -> [`HumanBitcoinAddress`]
987    #[deprecated(note = "since node-v0.9.3: \
988                         Use update_human_bitcoin_address instead")]
989    async fn update_payment_address(
990        &self,
991        req: UpdateHumanBitcoinAddress,
992        auth: BearerAuthToken,
993    ) -> Result<HumanBitcoinAddress, BackendApiError> {
994        self.update_human_bitcoin_address(req, auth).await
995    }
996
997    /// GET /node/v1/human_bitcoin_address [`Empty`] -> [`HumanBitcoinAddress`]
998    ///
999    /// Fetches the node's primary human Bitcoin address (username and offer).
1000    async fn get_human_bitcoin_address(
1001        &self,
1002        auth: BearerAuthToken,
1003    ) -> Result<HumanBitcoinAddress, BackendApiError>;
1004
1005    /// GET /node/v1/payment_address [`Empty`] -> [`HumanBitcoinAddress`]
1006    #[deprecated(note = "since node-v0.9.3: \
1007                         Use get_human_bitcoin_address instead")]
1008    async fn get_payment_address(
1009        &self,
1010        auth: BearerAuthToken,
1011    ) -> Result<HumanBitcoinAddress, BackendApiError> {
1012        self.get_human_bitcoin_address(auth).await
1013    }
1014
1015    /// POST /node/v1/claim_generated_human_bitcoin_address
1016    ///   [`ClaimGeneratedHumanBitcoinAddress`] -> [`Empty`]
1017    ///
1018    /// Claims a generated human Bitcoin address for the given node.
1019    async fn claim_generated_human_bitcoin_address(
1020        &self,
1021        req: ClaimGeneratedHumanBitcoinAddress,
1022        auth: BearerAuthToken,
1023    ) -> Result<Empty, BackendApiError>;
1024
1025    /// POST /node/v1/claim_generated_payment_address
1026    ///   [`ClaimGeneratedHumanBitcoinAddress`] -> [`Empty`]
1027    #[deprecated(note = "since node-v0.9.3: \
1028                         Use claim_generated_human_bitcoin_address instead")]
1029    async fn claim_generated_payment_address(
1030        &self,
1031        req: ClaimGeneratedHumanBitcoinAddress,
1032        auth: BearerAuthToken,
1033    ) -> Result<Empty, BackendApiError> {
1034        self.claim_generated_human_bitcoin_address(req, auth).await
1035    }
1036
1037    /// GET /node/v1/generated_username [`Empty`]
1038    ///                              -> [`GetGeneratedUsernameResponse`]
1039    ///
1040    /// Generates an available username for the authenticated user without
1041    /// storing it. The username is derived deterministically from the
1042    /// user's `user_pk`, with collision handling via numeric suffixes.
1043    async fn get_generated_username(
1044        &self,
1045        auth: BearerAuthToken,
1046    ) -> Result<GetGeneratedUsernameResponse, BackendApiError>;
1047
1048    /// GET /node/v1/nwc_clients [`Empty`] -> [`VecDbNwcClient`]
1049    ///
1050    /// Fetches the node's NWC clients and optionally filters by
1051    /// client_nostr_pk.
1052    async fn get_nwc_clients(
1053        &self,
1054        req: GetNwcClients,
1055        auth: BearerAuthToken,
1056    ) -> Result<VecDbNwcClient, BackendApiError>;
1057
1058    /// PUT /node/v1/nwc_clients [`DbNwcClientFields`] -> [`DbNwcClient`]
1059    ///
1060    /// Upserts a NWC client in the database.
1061    async fn upsert_nwc_client(
1062        &self,
1063        req: DbNwcClientFields,
1064        auth: BearerAuthToken,
1065    ) -> Result<DbNwcClient, BackendApiError>;
1066
1067    /// DELETE /node/v1/nwc_clients [`NostrPkStruct`] -> [`Empty`]
1068    ///
1069    /// Deletes a NWC client given its nostr client public key.
1070    async fn delete_nwc_client(
1071        &self,
1072        req: NostrPkStruct,
1073        auth: BearerAuthToken,
1074    ) -> Result<Empty, BackendApiError>;
1075}
1076
1077/// Defines the api that the LSP exposes to user nodes.
1078pub trait NodeLspApi {
1079    /// GET /node/v1/scids [`GetNewScidsRequest`] -> [`Scids`]
1080    async fn get_new_scids(
1081        &self,
1082        req: &GetNewScidsRequest,
1083    ) -> Result<Scids, LspApiError>;
1084
1085    /// GET /node/v1/network_graph [`Empty`] -> [`Bytes`] (LDK-serialized graph)
1086    ///
1087    /// Introduced in node-v0.6.8 and lsp-v0.6.29.
1088    async fn get_network_graph(&self) -> Result<Bytes, LspApiError>;
1089
1090    /// GET /node/v1/prob_scorer [`Empty`]
1091    ///                       -> [`Bytes`] (LDK-serialized probabilistic scorer)
1092    ///
1093    /// Introduced in node-v0.6.17 and lsp-v0.6.33.
1094    async fn get_prob_scorer(&self) -> Result<Bytes, LspApiError>;
1095
1096    /// POST /node/v1/payment_path [`Bytes`] (LDK-serialized [`Event`])
1097    ///                         -> [`Empty`]
1098    ///
1099    /// Sends an anonymized successful or failed payment path to the LSP to
1100    /// update Lexe's shared network graph and improve payment reliability.
1101    ///
1102    /// Introduced in node-v0.6.17 and lsp-v0.6.33.
1103    async fn payment_path(&self, event: &Event) -> Result<Empty, LspApiError>;
1104}
1105
1106/// Defines the api that the runner exposes to the user node.
1107pub trait NodeRunnerApi {
1108    /// POST /node/renew_lease [`UserLeaseRenewalRequest`] -> [`Empty`]
1109    ///
1110    /// Renew's a user node's lease with the megarunner.
1111    async fn renew_lease(
1112        &self,
1113        req: &UserLeaseRenewalRequest,
1114    ) -> Result<Empty, RunnerApiError>;
1115
1116    /// POST /node/sync_success [`UserPkStruct`] -> [`Empty`]
1117    ///
1118    /// Indicates the node successfully completed sync.
1119    async fn sync_succ(&self, user_pk: UserPk)
1120    -> Result<Empty, RunnerApiError>;
1121}
1122
1123/// Defines the api that the gateway exposes to the internet.
1124pub trait PublicGatewayApi {
1125    /// Get the LNURL pay request message, if any username has been set.
1126    /// Uses lnurl_callback endpoint as the callback.
1127    ///
1128    /// GET /.well-known/lnurlp/{username}
1129    async fn get_lnurl_pay_request(
1130        &self,
1131    ) -> Result<LnurlPayRequestWire, LnurlError>;
1132
1133    /// Resolves the invoice given a LNURL pay request previously generated.
1134    /// Ciphertext is a base64 encoded string of the username and
1135    /// other metadata information.
1136    ///
1137    /// GET /public/v1/lnurl_callback/{encoded_params}
1138    async fn lnurl_callback(
1139        &self,
1140        req: LnurlCallbackRequest,
1141    ) -> Result<LnurlCallbackResponse, LnurlError>;
1142}