1use std::pin::Pin;
4
5use async_trait::async_trait;
6use futures::Stream;
7use lightning_invoice::{Bolt11Invoice, ParseOrSemanticError};
8use serde::{Deserialize, Serialize};
9use thiserror::Error;
10
11use crate::nuts::{CurrencyUnit, MeltQuoteBolt11Request, MeltQuoteState, MintQuoteState};
12use crate::{mint, Amount};
13
14#[derive(Debug, Error)]
16pub enum Error {
17    #[error("Invoice already paid")]
19    InvoiceAlreadyPaid,
20    #[error("Invoice pay is pending")]
22    InvoicePaymentPending,
23    #[error("Unsupported unit")]
25    UnsupportedUnit,
26    #[error("Payment state is unknown")]
28    UnknownPaymentState,
29    #[error(transparent)]
31    Lightning(Box<dyn std::error::Error + Send + Sync>),
32    #[error(transparent)]
34    Serde(#[from] serde_json::Error),
35    #[error(transparent)]
37    Anyhow(#[from] anyhow::Error),
38    #[error(transparent)]
40    Parse(#[from] ParseOrSemanticError),
41    #[error(transparent)]
43    Amount(#[from] crate::amount::Error),
44    #[error(transparent)]
46    NUT05(#[from] crate::nuts::nut05::Error),
47}
48
49#[async_trait]
51pub trait MintLightning {
52    type Err: Into<Error> + From<Error>;
54
55    fn get_settings(&self) -> Settings;
57
58    async fn create_invoice(
60        &self,
61        amount: Amount,
62        unit: &CurrencyUnit,
63        description: String,
64        unix_expiry: u64,
65    ) -> Result<CreateInvoiceResponse, Self::Err>;
66
67    async fn get_payment_quote(
70        &self,
71        melt_quote_request: &MeltQuoteBolt11Request,
72    ) -> Result<PaymentQuoteResponse, Self::Err>;
73
74    async fn pay_invoice(
76        &self,
77        melt_quote: mint::MeltQuote,
78        partial_amount: Option<Amount>,
79        max_fee_amount: Option<Amount>,
80    ) -> Result<PayInvoiceResponse, Self::Err>;
81
82    async fn wait_any_invoice(
85        &self,
86    ) -> Result<Pin<Box<dyn Stream<Item = String> + Send>>, Self::Err>;
87
88    fn is_wait_invoice_active(&self) -> bool;
90
91    fn cancel_wait_invoice(&self);
93
94    async fn check_incoming_invoice_status(
96        &self,
97        request_lookup_id: &str,
98    ) -> Result<MintQuoteState, Self::Err>;
99
100    async fn check_outgoing_payment(
102        &self,
103        request_lookup_id: &str,
104    ) -> Result<PayInvoiceResponse, Self::Err>;
105}
106
107#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
109pub struct CreateInvoiceResponse {
110    pub request_lookup_id: String,
112    pub request: Bolt11Invoice,
114    pub expiry: Option<u64>,
116}
117
118#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
120pub struct PayInvoiceResponse {
121    pub payment_lookup_id: String,
123    pub payment_preimage: Option<String>,
125    pub status: MeltQuoteState,
127    pub total_spent: Amount,
129    pub unit: CurrencyUnit,
131}
132
133#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
135pub struct PaymentQuoteResponse {
136    pub request_lookup_id: String,
138    pub amount: Amount,
140    pub fee: Amount,
142    pub state: MeltQuoteState,
144}
145
146#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
148pub struct Settings {
149    pub mpp: bool,
151    pub unit: CurrencyUnit,
153    pub invoice_description: bool,
155}