lexe/types/
payment.rs

1//! Lexe SDK payment types.
2
3use std::sync::Arc;
4
5use bitcoin::address::NetworkUnchecked;
6use lexe_api::types::{invoice::Invoice, payments::BasicPaymentV2};
7use lexe_common::{
8    ln::{amount::Amount, hashes::Txid, priority::ConfirmationPriority},
9    time::TimestampMs,
10};
11use serde::{Deserialize, Serialize};
12
13/// Re-exports that are part of the SDK's public API.
14/// Wrapped in a module so `rustfmt` doesn't merge them with regular imports.
15mod reexports {
16    pub use lexe_api::types::payments::{
17        ClientPaymentId, LnClaimId, PaymentCreatedIndex, PaymentDirection,
18        PaymentHash, PaymentId, PaymentKind, PaymentRail, PaymentSecret,
19        PaymentStatus, PaymentUpdatedIndex,
20    };
21}
22pub use reexports::*;
23
24/// Information about a payment.
25#[derive(Serialize, Deserialize)]
26pub struct Payment {
27    /// Unique payment identifier, ordered by `created_at`.
28    ///
29    /// This implements [`Ord`] and is generally the thing you want to key your
30    /// payments by, e.g. `BTreeMap<PaymentCreatedIndex, Payment>`.
31    pub index: PaymentCreatedIndex,
32
33    /// The technical 'rail' used to fulfill a payment:
34    /// 'onchain', 'invoice', 'offer', 'spontaneous', 'waived_fee', etc.
35    pub rail: PaymentRail,
36
37    /// Application-level payment kind.
38    pub kind: PaymentKind,
39
40    /// The payment direction: `"inbound"`, `"outbound"`, or `"info"`.
41    pub direction: PaymentDirection,
42
43    /* TODO(max): Expose offer_id once we have out-of-line Offer storage.
44    /// (Offer payments only) The id of the BOLT12 offer used in this payment.
45    pub offer_id: Option<OfferId>,
46    */
47    /// (Onchain payments only) The hex-encoded Bitcoin txid.
48    pub txid: Option<Txid>,
49
50    /// The amount of this payment.
51    ///
52    /// - If this is a completed inbound invoice payment, this is the amount we
53    ///   received.
54    /// - If this is a pending or failed inbound inbound invoice payment, this
55    ///   is the amount encoded in our invoice, which may be null.
56    /// - For all other payment types, an amount is always included.
57    pub amount: Option<Amount>,
58
59    /// The fees for this payment.
60    ///
61    /// - For outbound Lightning payments, these are the routing fees. If the
62    ///   payment is not completed, this value is an estimation only. This
63    ///   value reflects the actual fees paid if and only if the payment
64    ///   completes.
65    /// - For inbound Lightning payments, the routing fees are not paid by us
66    ///   (the recipient), but if a JIT channel open was required to facilitate
67    ///   this payment, then the on-chain fee is reflected here.
68    pub fees: Amount,
69
70    /// The status of this payment: ["pending", "completed", "failed"].
71    pub status: PaymentStatus,
72
73    /// The payment status as a human-readable message. These strings are
74    /// customized per payment type, e.g. "invoice generated", "timed out"
75    pub status_msg: String,
76
77    /// (Onchain send only) The address that we're sending to.
78    pub address: Option<Arc<bitcoin::Address<NetworkUnchecked>>>,
79
80    /// (Invoice payments only) The BOLT11 invoice used in this payment.
81    pub invoice: Option<Arc<Invoice>>,
82
83    /* TODO(max): Expose offer once we have out-of-line Offer storage.
84    /// (Outbound offer payments only) The BOLT12 offer used in this payment.
85    /// Until we store offers out-of-line, this is not yet available for
86    /// inbound offer payments.
87    pub offer: Option<Arc<Offer>>,
88    */
89    /// The on-chain transaction, if there is one.
90    /// Always [`Some`] for on-chain sends and receives.
91    pub tx: Option<Arc<bitcoin::Transaction>>,
92
93    /// An optional personal note which a user can attach to any payment.
94    /// A note can always be added or modified when a payment already exists,
95    /// but this may not always be possible at creation time.
96    pub note: Option<String>,
97
98    /// (Offer payments only) The payer's self-reported human-readable name.
99    pub payer_name: Option<String>,
100
101    /// (Offer payments, LNURL-pay invoices) A payer-provided note for this
102    /// payment.
103    pub payer_note: Option<String>,
104
105    /// (Onchain send only) The confirmation priority used for this payment.
106    pub priority: Option<ConfirmationPriority>,
107
108    /* TODO(max): Expose replacement_txid once someone cares about it.
109    /// (Onchain payments only) The hex-encoded txid of the transaction that
110    /// replaced this on-chain payment, if one exists.
111    pub replacement_txid: Option<Txid>,
112    */
113    /// The invoice or offer expiry time.
114    /// `None` otherwise, or if the timestamp overflows.
115    pub expires_at: Option<TimestampMs>,
116
117    /// If this payment is finalized, meaning it is "completed" or "failed",
118    /// this is the time it was finalized, in milliseconds since the UNIX
119    /// epoch.
120    pub finalized_at: Option<TimestampMs>,
121
122    /// When this payment was created.
123    pub created_at: TimestampMs,
124
125    /// When this payment was last updated.
126    pub updated_at: TimestampMs,
127}
128
129/// Sort order for listing results.
130#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
131pub enum Order {
132    /// Ascending order (oldest first).
133    #[serde(rename = "asc")]
134    Asc,
135    /// Descending order (newest first).
136    #[serde(rename = "desc")]
137    Desc,
138}
139
140/// Filter for listing payments.
141#[derive(Clone, Debug, Serialize, Deserialize)]
142pub enum PaymentFilter {
143    /// Include all payments.
144    #[serde(rename = "all")]
145    All,
146    /// Include only pending payments.
147    #[serde(rename = "pending")]
148    Pending,
149    /// Include only completed payments.
150    #[serde(rename = "completed")]
151    Completed,
152    /// Include only failed payments.
153    #[serde(rename = "failed")]
154    Failed,
155    /// Include only finalized payments (completed or failed).
156    #[serde(rename = "finalized")]
157    Finalized,
158}
159
160impl From<BasicPaymentV2> for Payment {
161    fn from(p: BasicPaymentV2) -> Self {
162        let BasicPaymentV2 {
163            id,
164            related_ids: _,
165            kind,
166            direction,
167            offer_id: _,
168            txid,
169            amount,
170            fee,
171            status,
172            status_str,
173            address,
174            invoice,
175            offer: _,
176            tx,
177            note,
178            payer_name,
179            payer_note,
180            priority,
181            quantity: _,
182            replacement_txid: _,
183            expires_at,
184            finalized_at,
185            created_at,
186            updated_at,
187        } = p;
188
189        let index = PaymentCreatedIndex { created_at, id };
190
191        Self {
192            index,
193            rail: kind.rail(),
194            kind,
195            direction,
196            txid,
197            amount,
198            fees: fee,
199            status,
200            status_msg: status_str,
201            address,
202            invoice,
203            tx,
204            note,
205            payer_name,
206            payer_note,
207            priority,
208            expires_at,
209            finalized_at,
210            created_at,
211            updated_at,
212        }
213    }
214}