use std::collections::HashMap;
use std::sync::Arc;
use cdk_common::common::PaymentProcessorKey;
use cdk_common::database::DynMintDatabase;
use cdk_common::mint::MintQuote;
use cdk_common::payment::DynMintPayment;
use cdk_common::MintQuoteState;
use tracing::instrument;
use super::subscription::PubSubManager;
use super::Mint;
use crate::Error;
impl Mint {
pub(crate) async fn check_mint_quote_payments(
localstore: DynMintDatabase,
payment_processors: Arc<HashMap<PaymentProcessorKey, DynMintPayment>>,
pubsub_manager: Option<Arc<PubSubManager>>,
quote: &mut MintQuote,
) -> Result<(), Error> {
let state = quote.state();
if quote.payment_method.is_bolt11()
&& (state == MintQuoteState::Issued || state == MintQuoteState::Paid)
{
return Ok(());
}
let ln = match payment_processors.get(&PaymentProcessorKey::new(
quote.unit.clone(),
quote.payment_method.clone(),
)) {
Some(ln) => ln,
None => {
tracing::info!("Could not get ln backend for {}, bolt11 ", quote.unit);
return Err(Error::UnsupportedUnit);
}
};
let ln_status = ln
.check_incoming_payment_status("e.request_lookup_id)
.await?;
if ln_status.is_empty() {
return Ok(());
}
let mut tx = localstore.begin_transaction().await?;
let mut new_quote = tx
.get_mint_quote("e.id)
.await?
.ok_or(Error::UnknownQuote)?;
let current_state = new_quote.state();
if new_quote.payment_method.is_bolt11()
&& (current_state == MintQuoteState::Issued || current_state == MintQuoteState::Paid)
{
*quote = new_quote.inner();
return Ok(());
}
let mut should_notify = false;
for payment in ln_status {
if !new_quote.payment_ids().contains(&&payment.payment_id)
&& payment.payment_amount.value() > 0
{
tracing::debug!(
"Found payment of {} {:?} for quote {} when checking.",
payment.payment_amount.value(),
payment.unit(),
new_quote.id
);
let amount_paid = payment.payment_amount.convert_to(&new_quote.unit)?;
match new_quote.add_payment(amount_paid, payment.payment_id.clone(), None) {
Ok(()) => {
tx.update_mint_quote(&mut new_quote).await?;
should_notify = true;
}
Err(crate::Error::DuplicatePaymentId) => {
tracing::debug!(
"Payment ID {} already processed (caught race condition in check_mint_quote_paid)",
payment.payment_id
);
}
Err(e) => return Err(e),
}
}
}
tx.commit().await?;
if should_notify {
if let Some(pubsub_manager) = pubsub_manager.as_ref() {
pubsub_manager.mint_quote_payment(&new_quote, new_quote.amount_paid());
}
}
*quote = new_quote.inner();
Ok(())
}
#[instrument(skip_all)]
pub async fn check_mint_quote_paid(&self, quote: &mut MintQuote) -> Result<(), Error> {
Self::check_mint_quote_payments(
self.localstore.clone(),
self.payment_processors.clone(),
Some(self.pubsub_manager.clone()),
quote,
)
.await
}
}