cdk_common/
subscription.rs

1//! Subscription types and traits
2#[cfg(feature = "mint")]
3use std::str::FromStr;
4
5use cashu::nut17::{self};
6#[cfg(feature = "mint")]
7use cashu::nut17::{Error, Kind, Notification};
8#[cfg(feature = "mint")]
9use cashu::quote_id::QuoteId;
10#[cfg(feature = "mint")]
11use cashu::{NotificationPayload, PublicKey};
12#[cfg(feature = "mint")]
13use serde::{Deserialize, Serialize};
14
15#[cfg(feature = "mint")]
16use crate::pub_sub::index::{Index, Indexable, SubscriptionGlobalId};
17use crate::pub_sub::SubId;
18
19/// Subscription parameters.
20///
21/// This is a concrete type alias for `nut17::Params<SubId>`.
22pub type Params = nut17::Params<SubId>;
23
24/// Wrapper around `nut17::Params` to implement `Indexable` for `Notification`.
25#[cfg(feature = "mint")]
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct IndexableParams(Params);
28
29#[cfg(feature = "mint")]
30impl From<Params> for IndexableParams {
31    fn from(params: Params) -> Self {
32        Self(params)
33    }
34}
35
36#[cfg(feature = "mint")]
37impl TryFrom<IndexableParams> for Vec<Index<Notification>> {
38    type Error = Error;
39    fn try_from(params: IndexableParams) -> Result<Self, Self::Error> {
40        let sub_id: SubscriptionGlobalId = Default::default();
41        let params = params.0;
42        params
43            .filters
44            .into_iter()
45            .map(|filter| {
46                let idx = match params.kind {
47                    Kind::Bolt11MeltQuote => {
48                        Notification::MeltQuoteBolt11(QuoteId::from_str(&filter)?)
49                    }
50                    Kind::Bolt11MintQuote => {
51                        Notification::MintQuoteBolt11(QuoteId::from_str(&filter)?)
52                    }
53                    Kind::ProofState => Notification::ProofState(PublicKey::from_str(&filter)?),
54                    Kind::Bolt12MintQuote => {
55                        Notification::MintQuoteBolt12(QuoteId::from_str(&filter)?)
56                    }
57                };
58
59                Ok(Index::from((idx, params.id.clone(), sub_id)))
60            })
61            .collect::<Result<_, _>>()
62    }
63}
64
65#[cfg(feature = "mint")]
66impl AsRef<SubId> for IndexableParams {
67    fn as_ref(&self) -> &SubId {
68        &self.0.id
69    }
70}
71
72#[cfg(feature = "mint")]
73impl Indexable for NotificationPayload<QuoteId> {
74    type Type = Notification;
75
76    fn to_indexes(&self) -> Vec<Index<Self::Type>> {
77        match self {
78            NotificationPayload::ProofState(proof_state) => {
79                vec![Index::from(Notification::ProofState(proof_state.y))]
80            }
81            NotificationPayload::MeltQuoteBolt11Response(melt_quote) => {
82                vec![Index::from(Notification::MeltQuoteBolt11(
83                    melt_quote.quote.clone(),
84                ))]
85            }
86            NotificationPayload::MintQuoteBolt11Response(mint_quote) => {
87                vec![Index::from(Notification::MintQuoteBolt11(
88                    mint_quote.quote.clone(),
89                ))]
90            }
91            NotificationPayload::MintQuoteBolt12Response(mint_quote) => {
92                vec![Index::from(Notification::MintQuoteBolt12(
93                    mint_quote.quote.clone(),
94                ))]
95            }
96        }
97    }
98}