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}