mod.rs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. use std::str::FromStr;
  2. use cdk_common::payment::{
  3. CreateIncomingPaymentResponse, MakePaymentResponse as CdkMakePaymentResponse,
  4. PaymentIdentifier as CdkPaymentIdentifier, WaitPaymentResponse,
  5. };
  6. use cdk_common::{CurrencyUnit, MeltOptions as CdkMeltOptions};
  7. mod client;
  8. mod server;
  9. pub use client::PaymentProcessorClient;
  10. pub use server::PaymentProcessorServer;
  11. tonic::include_proto!("cdk_payment_processor");
  12. impl From<CdkPaymentIdentifier> for PaymentIdentifier {
  13. fn from(value: CdkPaymentIdentifier) -> Self {
  14. match value {
  15. CdkPaymentIdentifier::Label(id) => Self {
  16. r#type: PaymentIdentifierType::Label.into(),
  17. value: Some(payment_identifier::Value::Id(id)),
  18. },
  19. CdkPaymentIdentifier::OfferId(id) => Self {
  20. r#type: PaymentIdentifierType::OfferId.into(),
  21. value: Some(payment_identifier::Value::Id(id)),
  22. },
  23. CdkPaymentIdentifier::PaymentHash(hash) => Self {
  24. r#type: PaymentIdentifierType::PaymentHash.into(),
  25. value: Some(payment_identifier::Value::Hash(hex::encode(hash))),
  26. },
  27. CdkPaymentIdentifier::Bolt12PaymentHash(hash) => Self {
  28. r#type: PaymentIdentifierType::Bolt12PaymentHash.into(),
  29. value: Some(payment_identifier::Value::Hash(hex::encode(hash))),
  30. },
  31. CdkPaymentIdentifier::CustomId(id) => Self {
  32. r#type: PaymentIdentifierType::CustomId.into(),
  33. value: Some(payment_identifier::Value::Id(id)),
  34. },
  35. CdkPaymentIdentifier::PaymentId(hash) => Self {
  36. r#type: PaymentIdentifierType::PaymentId.into(),
  37. value: Some(payment_identifier::Value::Hash(hex::encode(hash))),
  38. },
  39. }
  40. }
  41. }
  42. impl TryFrom<PaymentIdentifier> for CdkPaymentIdentifier {
  43. type Error = crate::error::Error;
  44. fn try_from(value: PaymentIdentifier) -> Result<Self, Self::Error> {
  45. match (value.r#type(), value.value) {
  46. (PaymentIdentifierType::Label, Some(payment_identifier::Value::Id(id))) => {
  47. Ok(CdkPaymentIdentifier::Label(id))
  48. }
  49. (PaymentIdentifierType::OfferId, Some(payment_identifier::Value::Id(id))) => {
  50. Ok(CdkPaymentIdentifier::OfferId(id))
  51. }
  52. (PaymentIdentifierType::PaymentHash, Some(payment_identifier::Value::Hash(hash))) => {
  53. let decoded = hex::decode(hash)?;
  54. let hash_array: [u8; 32] = decoded
  55. .try_into()
  56. .map_err(|_| crate::error::Error::InvalidHash)?;
  57. Ok(CdkPaymentIdentifier::PaymentHash(hash_array))
  58. }
  59. (
  60. PaymentIdentifierType::Bolt12PaymentHash,
  61. Some(payment_identifier::Value::Hash(hash)),
  62. ) => {
  63. let decoded = hex::decode(hash)?;
  64. let hash_array: [u8; 32] = decoded
  65. .try_into()
  66. .map_err(|_| crate::error::Error::InvalidHash)?;
  67. Ok(CdkPaymentIdentifier::Bolt12PaymentHash(hash_array))
  68. }
  69. (PaymentIdentifierType::CustomId, Some(payment_identifier::Value::Id(id))) => {
  70. Ok(CdkPaymentIdentifier::CustomId(id))
  71. }
  72. _ => Err(crate::error::Error::InvalidPaymentIdentifier),
  73. }
  74. }
  75. }
  76. impl TryFrom<MakePaymentResponse> for CdkMakePaymentResponse {
  77. type Error = crate::error::Error;
  78. fn try_from(value: MakePaymentResponse) -> Result<Self, Self::Error> {
  79. let status = value.status().as_str_name().parse()?;
  80. let payment_proof = value.payment_proof;
  81. let total_spent = value.total_spent.into();
  82. let unit = CurrencyUnit::from_str(&value.unit)?;
  83. let payment_identifier = value
  84. .payment_identifier
  85. .ok_or(crate::error::Error::InvalidPaymentIdentifier)?;
  86. Ok(Self {
  87. payment_lookup_id: payment_identifier.try_into()?,
  88. payment_proof,
  89. status,
  90. total_spent,
  91. unit,
  92. })
  93. }
  94. }
  95. impl From<CdkMakePaymentResponse> for MakePaymentResponse {
  96. fn from(value: CdkMakePaymentResponse) -> Self {
  97. Self {
  98. payment_identifier: Some(value.payment_lookup_id.into()),
  99. payment_proof: value.payment_proof,
  100. status: QuoteState::from(value.status).into(),
  101. total_spent: value.total_spent.into(),
  102. unit: value.unit.to_string(),
  103. }
  104. }
  105. }
  106. impl From<CreateIncomingPaymentResponse> for CreatePaymentResponse {
  107. fn from(value: CreateIncomingPaymentResponse) -> Self {
  108. Self {
  109. request_identifier: Some(value.request_lookup_id.into()),
  110. request: value.request,
  111. expiry: value.expiry,
  112. }
  113. }
  114. }
  115. impl TryFrom<CreatePaymentResponse> for CreateIncomingPaymentResponse {
  116. type Error = crate::error::Error;
  117. fn try_from(value: CreatePaymentResponse) -> Result<Self, Self::Error> {
  118. let request_identifier = value
  119. .request_identifier
  120. .ok_or(crate::error::Error::InvalidPaymentIdentifier)?;
  121. Ok(Self {
  122. request_lookup_id: request_identifier.try_into()?,
  123. request: value.request,
  124. expiry: value.expiry,
  125. })
  126. }
  127. }
  128. impl From<cdk_common::payment::PaymentQuoteResponse> for PaymentQuoteResponse {
  129. fn from(value: cdk_common::payment::PaymentQuoteResponse) -> Self {
  130. Self {
  131. request_identifier: value.request_lookup_id.map(|i| i.into()),
  132. amount: value.amount.into(),
  133. fee: value.fee.into(),
  134. unit: value.unit.to_string(),
  135. state: QuoteState::from(value.state).into(),
  136. }
  137. }
  138. }
  139. impl From<PaymentQuoteResponse> for cdk_common::payment::PaymentQuoteResponse {
  140. fn from(value: PaymentQuoteResponse) -> Self {
  141. let state_val = value.state();
  142. let request_identifier = value.request_identifier;
  143. Self {
  144. request_lookup_id: request_identifier
  145. .map(|i| i.try_into().expect("valid request identifier")),
  146. amount: value.amount.into(),
  147. fee: value.fee.into(),
  148. unit: CurrencyUnit::from_str(&value.unit).unwrap_or_default(),
  149. state: state_val.into(),
  150. }
  151. }
  152. }
  153. impl From<MeltOptions> for CdkMeltOptions {
  154. fn from(value: MeltOptions) -> Self {
  155. match value.options.expect("option defined") {
  156. melt_options::Options::Mpp(mpp) => Self::Mpp {
  157. mpp: cashu::nuts::nut15::Mpp {
  158. amount: mpp.amount.into(),
  159. },
  160. },
  161. melt_options::Options::Amountless(amountless) => Self::Amountless {
  162. amountless: cashu::nuts::nut23::Amountless {
  163. amount_msat: amountless.amount_msat.into(),
  164. },
  165. },
  166. }
  167. }
  168. }
  169. impl From<CdkMeltOptions> for MeltOptions {
  170. fn from(value: CdkMeltOptions) -> Self {
  171. match value {
  172. CdkMeltOptions::Mpp { mpp } => Self {
  173. options: Some(melt_options::Options::Mpp(Mpp {
  174. amount: mpp.amount.into(),
  175. })),
  176. },
  177. CdkMeltOptions::Amountless { amountless } => Self {
  178. options: Some(melt_options::Options::Amountless(Amountless {
  179. amount_msat: amountless.amount_msat.into(),
  180. })),
  181. },
  182. }
  183. }
  184. }
  185. impl From<QuoteState> for cdk_common::nuts::MeltQuoteState {
  186. fn from(value: QuoteState) -> Self {
  187. match value {
  188. QuoteState::Unpaid => Self::Unpaid,
  189. QuoteState::Paid => Self::Paid,
  190. QuoteState::Pending => Self::Pending,
  191. QuoteState::Unknown => Self::Unknown,
  192. QuoteState::Failed => Self::Failed,
  193. QuoteState::Issued => Self::Unknown,
  194. }
  195. }
  196. }
  197. impl From<cdk_common::nuts::MeltQuoteState> for QuoteState {
  198. fn from(value: cdk_common::nuts::MeltQuoteState) -> Self {
  199. match value {
  200. cdk_common::nuts::MeltQuoteState::Unpaid => Self::Unpaid,
  201. cdk_common::nuts::MeltQuoteState::Paid => Self::Paid,
  202. cdk_common::nuts::MeltQuoteState::Pending => Self::Pending,
  203. cdk_common::nuts::MeltQuoteState::Unknown => Self::Unknown,
  204. cdk_common::nuts::MeltQuoteState::Failed => Self::Failed,
  205. }
  206. }
  207. }
  208. impl From<cdk_common::nuts::MintQuoteState> for QuoteState {
  209. fn from(value: cdk_common::nuts::MintQuoteState) -> Self {
  210. match value {
  211. cdk_common::nuts::MintQuoteState::Unpaid => Self::Unpaid,
  212. cdk_common::nuts::MintQuoteState::Paid => Self::Paid,
  213. cdk_common::nuts::MintQuoteState::Issued => Self::Issued,
  214. }
  215. }
  216. }
  217. impl From<WaitPaymentResponse> for WaitIncomingPaymentResponse {
  218. fn from(value: WaitPaymentResponse) -> Self {
  219. Self {
  220. payment_identifier: Some(value.payment_identifier.into()),
  221. payment_amount: value.payment_amount.into(),
  222. unit: value.unit.to_string(),
  223. payment_id: value.payment_id,
  224. }
  225. }
  226. }
  227. impl TryFrom<WaitIncomingPaymentResponse> for WaitPaymentResponse {
  228. type Error = crate::error::Error;
  229. fn try_from(value: WaitIncomingPaymentResponse) -> Result<Self, Self::Error> {
  230. let payment_identifier = value
  231. .payment_identifier
  232. .ok_or(crate::error::Error::InvalidPaymentIdentifier)?
  233. .try_into()?;
  234. Ok(Self {
  235. payment_identifier,
  236. payment_amount: value.payment_amount.into(),
  237. unit: CurrencyUnit::from_str(&value.unit)?,
  238. payment_id: value.payment_id,
  239. })
  240. }
  241. }