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