use anyhow::{bail, Result};
use reqwest::StatusCode;
use serde::{Deserialize, Serialize};
use crate::{Amount, ConversionRate, Currency, Error, InvoiceState, Strike};
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PayInvoiceQuoteRequest {
pub ln_invoice: String,
pub source_currency: Currency,
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PayInvoiceQuoteResponse {
pub payment_quote_id: String,
pub description: Option<String>,
pub valid_until: String,
pub conversion_rate: Option<ConversionRate>,
pub amount: Amount,
pub lightning_network_fee: Amount,
pub total_amount: Amount,
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct InvoicePaymentResponse {
pub payment_id: String,
pub state: InvoiceState,
pub completed: Option<String>,
pub conversion_rate: Option<ConversionRate>,
pub amount: Amount,
pub lightning_network_fee: Amount,
pub total_amount: Amount,
}
impl Strike {
pub async fn payment_quote(
&self,
quote_request: PayInvoiceQuoteRequest,
) -> Result<PayInvoiceQuoteResponse> {
let url = self.base_url.join("/v1/payment-quotes/lightning")?;
let res = self
.make_post(url, Some(serde_json::to_value(quote_request)?))
.await?;
match serde_json::from_value(res.clone()) {
Ok(res) => Ok(res),
Err(_) => {
log::error!("Api error response on payment quote");
log::error!("{}", res);
bail!("Could not get payment quote")
}
}
}
pub async fn pay_quote(&self, payment_quote_id: &str) -> Result<InvoicePaymentResponse> {
let url = self
.base_url
.join(&format!("/v1/payment-quotes/{payment_quote_id}/execute"))?;
let res = self.make_patch(url).await?;
match serde_json::from_value(res.clone()) {
Ok(res) => Ok(res),
Err(_) => {
log::error!("Api error response on payment quote execution");
log::error!("{}", res);
bail!("Could not execute payment quote")
}
}
}
pub async fn get_outgoing_payment(
&self,
payment_id: &str,
) -> Result<InvoicePaymentResponse, Error> {
let url = self
.base_url
.join(&format!("/v1/payments/{payment_id}"))
.map_err(|_| Error::InvalidUrl)?;
let res = match self.make_get(url).await {
Ok(res) => res,
Err(err) => {
if let Error::ReqwestError(err) = &err {
if err.status().unwrap_or_default() == StatusCode::NOT_FOUND {
return Err(Error::NotFound);
}
}
return Err(err);
}
};
match serde_json::from_value(res.clone()) {
Ok(res) => Ok(res),
Err(err) => {
log::error!("Api error response getting payment quote");
log::error!("{}", res);
Err(err.into())
}
}
}
}