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}