payment.rs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. //! CDK Mint Lightning
  2. use std::pin::Pin;
  3. use async_trait::async_trait;
  4. use cashu::MeltOptions;
  5. use futures::Stream;
  6. use lightning_invoice::ParseOrSemanticError;
  7. use serde::{Deserialize, Serialize};
  8. use serde_json::Value;
  9. use thiserror::Error;
  10. use crate::nuts::{CurrencyUnit, MeltQuoteState, MintQuoteState};
  11. use crate::{mint, Amount};
  12. /// CDK Lightning Error
  13. #[derive(Debug, Error)]
  14. pub enum Error {
  15. /// Invoice already paid
  16. #[error("Invoice already paid")]
  17. InvoiceAlreadyPaid,
  18. /// Invoice pay pending
  19. #[error("Invoice pay is pending")]
  20. InvoicePaymentPending,
  21. /// Unsupported unit
  22. #[error("Unsupported unit")]
  23. UnsupportedUnit,
  24. /// Unsupported payment option
  25. #[error("Unsupported payment option")]
  26. UnsupportedPaymentOption,
  27. /// Payment state is unknown
  28. #[error("Payment state is unknown")]
  29. UnknownPaymentState,
  30. /// Lightning Error
  31. #[error(transparent)]
  32. Lightning(Box<dyn std::error::Error + Send + Sync>),
  33. /// Serde Error
  34. #[error(transparent)]
  35. Serde(#[from] serde_json::Error),
  36. /// AnyHow Error
  37. #[error(transparent)]
  38. Anyhow(#[from] anyhow::Error),
  39. /// Parse Error
  40. #[error(transparent)]
  41. Parse(#[from] ParseOrSemanticError),
  42. /// Amount Error
  43. #[error(transparent)]
  44. Amount(#[from] crate::amount::Error),
  45. /// NUT04 Error
  46. #[error(transparent)]
  47. NUT04(#[from] crate::nuts::nut04::Error),
  48. /// NUT05 Error
  49. #[error(transparent)]
  50. NUT05(#[from] crate::nuts::nut05::Error),
  51. /// Custom
  52. #[error("`{0}`")]
  53. Custom(String),
  54. }
  55. /// Mint payment trait
  56. #[async_trait]
  57. pub trait MintPayment {
  58. /// Mint Lightning Error
  59. type Err: Into<Error> + From<Error>;
  60. /// Base Settings
  61. async fn get_settings(&self) -> Result<serde_json::Value, Self::Err>;
  62. /// Create a new invoice
  63. async fn create_incoming_payment_request(
  64. &self,
  65. amount: Amount,
  66. unit: &CurrencyUnit,
  67. description: String,
  68. unix_expiry: Option<u64>,
  69. ) -> Result<CreateIncomingPaymentResponse, Self::Err>;
  70. /// Get payment quote
  71. /// Used to get fee and amount required for a payment request
  72. async fn get_payment_quote(
  73. &self,
  74. request: &str,
  75. unit: &CurrencyUnit,
  76. options: Option<MeltOptions>,
  77. ) -> Result<PaymentQuoteResponse, Self::Err>;
  78. /// Pay request
  79. async fn make_payment(
  80. &self,
  81. melt_quote: mint::MeltQuote,
  82. partial_amount: Option<Amount>,
  83. max_fee_amount: Option<Amount>,
  84. ) -> Result<MakePaymentResponse, Self::Err>;
  85. /// Listen for invoices to be paid to the mint
  86. /// Returns a stream of request_lookup_id once invoices are paid
  87. async fn wait_any_incoming_payment(
  88. &self,
  89. ) -> Result<Pin<Box<dyn Stream<Item = String> + Send>>, Self::Err>;
  90. /// Is wait invoice active
  91. fn is_wait_invoice_active(&self) -> bool;
  92. /// Cancel wait invoice
  93. fn cancel_wait_invoice(&self);
  94. /// Check the status of an incoming payment
  95. async fn check_incoming_payment_status(
  96. &self,
  97. request_lookup_id: &str,
  98. ) -> Result<MintQuoteState, Self::Err>;
  99. /// Check the status of an outgoing payment
  100. async fn check_outgoing_payment(
  101. &self,
  102. request_lookup_id: &str,
  103. ) -> Result<MakePaymentResponse, Self::Err>;
  104. }
  105. /// Create incoming payment response
  106. #[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
  107. pub struct CreateIncomingPaymentResponse {
  108. /// Id that is used to look up the payment from the ln backend
  109. pub request_lookup_id: String,
  110. /// Payment request
  111. pub request: String,
  112. /// Unix Expiry of Invoice
  113. pub expiry: Option<u64>,
  114. }
  115. /// Payment response
  116. #[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
  117. pub struct MakePaymentResponse {
  118. /// Payment hash
  119. pub payment_lookup_id: String,
  120. /// Payment proof
  121. pub payment_proof: Option<String>,
  122. /// Status
  123. pub status: MeltQuoteState,
  124. /// Total Amount Spent
  125. pub total_spent: Amount,
  126. /// Unit of total spent
  127. pub unit: CurrencyUnit,
  128. }
  129. /// Payment quote response
  130. #[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
  131. pub struct PaymentQuoteResponse {
  132. /// Request look up id
  133. pub request_lookup_id: String,
  134. /// Amount
  135. pub amount: Amount,
  136. /// Fee required for melt
  137. pub fee: Amount,
  138. /// Status
  139. pub state: MeltQuoteState,
  140. }
  141. /// Ln backend settings
  142. #[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
  143. pub struct Bolt11Settings {
  144. /// MPP supported
  145. pub mpp: bool,
  146. /// Base unit of backend
  147. pub unit: CurrencyUnit,
  148. /// Invoice Description supported
  149. pub invoice_description: bool,
  150. /// Paying amountless invoices supported
  151. pub amountless: bool,
  152. }
  153. impl TryFrom<Bolt11Settings> for Value {
  154. type Error = crate::error::Error;
  155. fn try_from(value: Bolt11Settings) -> Result<Self, Self::Error> {
  156. serde_json::to_value(value).map_err(|err| err.into())
  157. }
  158. }
  159. impl TryFrom<Value> for Bolt11Settings {
  160. type Error = crate::error::Error;
  161. fn try_from(value: Value) -> Result<Self, Self::Error> {
  162. serde_json::from_value(value).map_err(|err| err.into())
  163. }
  164. }