|
@@ -4,6 +4,7 @@
|
|
|
//!
|
|
|
//! Bolt11 will mint once
|
|
|
|
|
|
+use std::collections::HashMap;
|
|
|
use std::task::Poll;
|
|
|
|
|
|
use cdk_common::amount::SplitTarget;
|
|
@@ -16,31 +17,35 @@ use super::payment::PaymentStream;
|
|
|
use super::{RecvFuture, WaitableEvent};
|
|
|
use crate::Wallet;
|
|
|
|
|
|
-/// Mint waiter
|
|
|
-pub struct ProofStream<'a> {
|
|
|
+/// Proofs for many mint quotes, as they are minted, in streams
|
|
|
+pub struct MultipleMintQuoteProofStream<'a> {
|
|
|
payment_stream: PaymentStream<'a>,
|
|
|
wallet: &'a Wallet,
|
|
|
- mint_quote: MintQuote,
|
|
|
+ quotes: HashMap<String, MintQuote>,
|
|
|
amount_split_target: SplitTarget,
|
|
|
spending_conditions: Option<SpendingConditions>,
|
|
|
- minting_future: Option<RecvFuture<'a, Result<Proofs, Error>>>,
|
|
|
+ minting_future: Option<RecvFuture<'a, Result<(MintQuote, Proofs), Error>>>,
|
|
|
}
|
|
|
|
|
|
-impl<'a> ProofStream<'a> {
|
|
|
+impl<'a> MultipleMintQuoteProofStream<'a> {
|
|
|
/// Create a new Stream
|
|
|
pub fn new(
|
|
|
wallet: &'a Wallet,
|
|
|
- mint_quote: MintQuote,
|
|
|
+ quotes: Vec<MintQuote>,
|
|
|
amount_split_target: SplitTarget,
|
|
|
spending_conditions: Option<SpendingConditions>,
|
|
|
) -> Self {
|
|
|
- let filter: WaitableEvent = (&mint_quote).into();
|
|
|
+ let filter: WaitableEvent = quotes.as_slice().into();
|
|
|
+
|
|
|
Self {
|
|
|
- payment_stream: PaymentStream::new(wallet, filter.into()),
|
|
|
+ payment_stream: PaymentStream::new(wallet, filter.into_subscription()),
|
|
|
wallet,
|
|
|
amount_split_target,
|
|
|
spending_conditions,
|
|
|
- mint_quote,
|
|
|
+ quotes: quotes
|
|
|
+ .into_iter()
|
|
|
+ .map(|mint_quote| (mint_quote.id.clone(), mint_quote))
|
|
|
+ .collect(),
|
|
|
minting_future: None,
|
|
|
}
|
|
|
}
|
|
@@ -51,8 +56,8 @@ impl<'a> ProofStream<'a> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-impl Stream for ProofStream<'_> {
|
|
|
- type Item = Result<Proofs, Error>;
|
|
|
+impl Stream for MultipleMintQuoteProofStream<'_> {
|
|
|
+ type Item = Result<(MintQuote, Proofs), Error>;
|
|
|
|
|
|
fn poll_next(
|
|
|
self: std::pin::Pin<&mut Self>,
|
|
@@ -75,18 +80,24 @@ impl Stream for ProofStream<'_> {
|
|
|
Poll::Ready(result) => match result {
|
|
|
None => Poll::Ready(None),
|
|
|
Some(result) => {
|
|
|
- let amount = match result {
|
|
|
+ let (quote_id, amount) = match result {
|
|
|
Err(err) => {
|
|
|
tracing::error!(
|
|
|
- "Error while waiting for payment for {}",
|
|
|
- this.mint_quote.id
|
|
|
+ "Error while waiting for payment for {:?}",
|
|
|
+ this.quotes.keys().collect::<Vec<_>>()
|
|
|
);
|
|
|
return Poll::Ready(Some(Err(err)));
|
|
|
}
|
|
|
Ok(amount) => amount,
|
|
|
};
|
|
|
|
|
|
- let mint_quote = this.mint_quote.clone();
|
|
|
+ let mint_quote = if let Some(quote) = this.quotes.get("e_id) {
|
|
|
+ quote.clone()
|
|
|
+ } else {
|
|
|
+ tracing::error!("Cannot find mint_quote {} internally", quote_id);
|
|
|
+ return Poll::Ready(Some(Err(Error::UnknownQuote)));
|
|
|
+ };
|
|
|
+
|
|
|
let amount_split_target = this.amount_split_target.clone();
|
|
|
let spending_conditions = this.spending_conditions.clone();
|
|
|
let wallet = this.wallet;
|
|
@@ -99,21 +110,19 @@ impl Stream for ProofStream<'_> {
|
|
|
|
|
|
let mut minting_future = Box::pin(async move {
|
|
|
match mint_quote.payment_method {
|
|
|
- PaymentMethod::Bolt11 => {
|
|
|
- wallet
|
|
|
- .mint(&mint_quote.id, amount_split_target, spending_conditions)
|
|
|
- .await
|
|
|
- }
|
|
|
- PaymentMethod::Bolt12 => {
|
|
|
- wallet
|
|
|
- .mint_bolt12(
|
|
|
- &mint_quote.id,
|
|
|
- amount,
|
|
|
- amount_split_target,
|
|
|
- spending_conditions,
|
|
|
- )
|
|
|
- .await
|
|
|
- }
|
|
|
+ PaymentMethod::Bolt11 => wallet
|
|
|
+ .mint(&mint_quote.id, amount_split_target, spending_conditions)
|
|
|
+ .await
|
|
|
+ .map(|proofs| (mint_quote, proofs)),
|
|
|
+ PaymentMethod::Bolt12 => wallet
|
|
|
+ .mint_bolt12(
|
|
|
+ &mint_quote.id,
|
|
|
+ amount,
|
|
|
+ amount_split_target,
|
|
|
+ spending_conditions,
|
|
|
+ )
|
|
|
+ .await
|
|
|
+ .map(|proofs| (mint_quote, proofs)),
|
|
|
_ => Err(Error::UnsupportedPaymentMethod),
|
|
|
}
|
|
|
});
|
|
@@ -123,10 +132,54 @@ impl Stream for ProofStream<'_> {
|
|
|
this.minting_future = Some(minting_future);
|
|
|
Poll::Pending
|
|
|
}
|
|
|
- Poll::Ready(proofs) => Poll::Ready(Some(proofs)),
|
|
|
+ Poll::Ready(result) => Poll::Ready(Some(result)),
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+/// Proofs for a single mint quote
|
|
|
+pub struct SingleMintQuoteProofStream<'a>(MultipleMintQuoteProofStream<'a>);
|
|
|
+
|
|
|
+impl<'a> SingleMintQuoteProofStream<'a> {
|
|
|
+ /// Create a new Stream
|
|
|
+ pub fn new(
|
|
|
+ wallet: &'a Wallet,
|
|
|
+ quote: MintQuote,
|
|
|
+ amount_split_target: SplitTarget,
|
|
|
+ spending_conditions: Option<SpendingConditions>,
|
|
|
+ ) -> Self {
|
|
|
+ Self(MultipleMintQuoteProofStream::new(
|
|
|
+ wallet,
|
|
|
+ vec![quote],
|
|
|
+ amount_split_target,
|
|
|
+ spending_conditions,
|
|
|
+ ))
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Get cancellation token
|
|
|
+ pub fn get_cancel_token(&self) -> CancellationToken {
|
|
|
+ self.0.payment_stream.get_cancel_token()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl Stream for SingleMintQuoteProofStream<'_> {
|
|
|
+ type Item = Result<Proofs, Error>;
|
|
|
+
|
|
|
+ fn poll_next(
|
|
|
+ self: std::pin::Pin<&mut Self>,
|
|
|
+ cx: &mut std::task::Context<'_>,
|
|
|
+ ) -> std::task::Poll<Option<Self::Item>> {
|
|
|
+ let this = self.get_mut();
|
|
|
+ match this.0.poll_next_unpin(cx) {
|
|
|
+ Poll::Pending => Poll::Pending,
|
|
|
+ Poll::Ready(result) => match result {
|
|
|
+ None => Poll::Ready(None),
|
|
|
+ Some(Err(err)) => Poll::Ready(Some(Err(err))),
|
|
|
+ Some(Ok((_, proofs))) => Poll::Ready(Some(Ok(proofs))),
|
|
|
+ },
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|