1use anyhow::{bail, Result};
4use reqwest::StatusCode;
5use serde::{Deserialize, Serialize};
6
7use crate::{Amount, ConversionRate, Currency, Error, InvoiceState, Strike};
8
9#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
11#[serde(rename_all = "camelCase")]
12pub struct PayInvoiceQuoteRequest {
13 pub ln_invoice: String,
15 pub source_currency: Currency,
17}
18
19#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
21#[serde(rename_all = "camelCase")]
22pub struct PayInvoiceQuoteResponse {
23 pub payment_quote_id: String,
25 pub description: Option<String>,
27 pub valid_until: String,
29 pub conversion_rate: Option<ConversionRate>,
31 pub amount: Amount,
33 pub lightning_network_fee: Amount,
35 pub total_amount: Amount,
37}
38
39#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
41#[serde(rename_all = "camelCase")]
42pub struct InvoicePaymentResponse {
43 pub payment_id: String,
45 pub state: InvoiceState,
47 pub completed: Option<String>,
49 pub conversion_rate: Option<ConversionRate>,
51 pub amount: Amount,
53 pub lightning_network_fee: Amount,
55 pub total_amount: Amount,
57}
58
59impl Strike {
60 pub async fn payment_quote(
62 &self,
63 quote_request: PayInvoiceQuoteRequest,
64 ) -> Result<PayInvoiceQuoteResponse> {
65 let url = self.base_url.join("/v1/payment-quotes/lightning")?;
66
67 let res = self
68 .make_post(url, Some(serde_json::to_value(quote_request)?))
69 .await?;
70
71 match serde_json::from_value(res.clone()) {
72 Ok(res) => Ok(res),
73 Err(_) => {
74 log::error!("Api error response on payment quote");
75 log::error!("{}", res);
76 bail!("Could not get payment quote")
77 }
78 }
79 }
80
81 pub async fn pay_quote(&self, payment_quote_id: &str) -> Result<InvoicePaymentResponse> {
83 let url = self
84 .base_url
85 .join(&format!("/v1/payment-quotes/{payment_quote_id}/execute"))?;
86
87 let res = self.make_patch(url).await?;
88
89 match serde_json::from_value(res.clone()) {
90 Ok(res) => Ok(res),
91 Err(_) => {
92 log::error!("Api error response on payment quote execution");
93 log::error!("{}", res);
94 bail!("Could not execute payment quote")
95 }
96 }
97 }
98
99 pub async fn get_outgoing_payment(
101 &self,
102 payment_id: &str,
103 ) -> Result<InvoicePaymentResponse, Error> {
104 let url = self
105 .base_url
106 .join(&format!("/v1/payments/{payment_id}"))
107 .map_err(|_| Error::InvalidUrl)?;
108
109 let res = match self.make_get(url).await {
110 Ok(res) => res,
111 Err(err) => {
112 if let Error::ReqwestError(err) = &err {
113 if err.status().unwrap_or_default() == StatusCode::NOT_FOUND {
114 return Err(Error::NotFound);
115 }
116 }
117 return Err(err);
118 }
119 };
120
121 match serde_json::from_value(res.clone()) {
122 Ok(res) => Ok(res),
123 Err(err) => {
124 log::error!("Api error response getting payment quote");
125 log::error!("{}", res);
126
127 Err(err.into())
128 }
129 }
130 }
131}