cdk_payment_processor/proto/
mod.rs

1use std::str::FromStr;
2
3use cdk_common::payment::{
4    CreateIncomingPaymentResponse, MakePaymentResponse as CdkMakePaymentResponse,
5    PaymentIdentifier as CdkPaymentIdentifier, WaitPaymentResponse,
6};
7use cdk_common::{CurrencyUnit, MeltOptions as CdkMeltOptions};
8
9mod client;
10mod server;
11
12pub use client::PaymentProcessorClient;
13pub use server::PaymentProcessorServer;
14
15tonic::include_proto!("cdk_payment_processor");
16
17impl From<CdkPaymentIdentifier> for PaymentIdentifier {
18    fn from(value: CdkPaymentIdentifier) -> Self {
19        match value {
20            CdkPaymentIdentifier::Label(id) => Self {
21                r#type: PaymentIdentifierType::Label.into(),
22                value: Some(payment_identifier::Value::Id(id)),
23            },
24            CdkPaymentIdentifier::OfferId(id) => Self {
25                r#type: PaymentIdentifierType::OfferId.into(),
26                value: Some(payment_identifier::Value::Id(id)),
27            },
28            CdkPaymentIdentifier::PaymentHash(hash) => Self {
29                r#type: PaymentIdentifierType::PaymentHash.into(),
30                value: Some(payment_identifier::Value::Hash(hex::encode(hash))),
31            },
32            CdkPaymentIdentifier::Bolt12PaymentHash(hash) => Self {
33                r#type: PaymentIdentifierType::Bolt12PaymentHash.into(),
34                value: Some(payment_identifier::Value::Hash(hex::encode(hash))),
35            },
36            CdkPaymentIdentifier::CustomId(id) => Self {
37                r#type: PaymentIdentifierType::CustomId.into(),
38                value: Some(payment_identifier::Value::Id(id)),
39            },
40            CdkPaymentIdentifier::PaymentId(hash) => Self {
41                r#type: PaymentIdentifierType::PaymentId.into(),
42                value: Some(payment_identifier::Value::Hash(hex::encode(hash))),
43            },
44        }
45    }
46}
47
48impl TryFrom<PaymentIdentifier> for CdkPaymentIdentifier {
49    type Error = crate::error::Error;
50
51    fn try_from(value: PaymentIdentifier) -> Result<Self, Self::Error> {
52        match (value.r#type(), value.value) {
53            (PaymentIdentifierType::Label, Some(payment_identifier::Value::Id(id))) => {
54                Ok(CdkPaymentIdentifier::Label(id))
55            }
56            (PaymentIdentifierType::OfferId, Some(payment_identifier::Value::Id(id))) => {
57                Ok(CdkPaymentIdentifier::OfferId(id))
58            }
59            (PaymentIdentifierType::PaymentHash, Some(payment_identifier::Value::Hash(hash))) => {
60                let decoded = hex::decode(hash)?;
61                let hash_array: [u8; 32] = decoded
62                    .try_into()
63                    .map_err(|_| crate::error::Error::InvalidHash)?;
64                Ok(CdkPaymentIdentifier::PaymentHash(hash_array))
65            }
66            (
67                PaymentIdentifierType::Bolt12PaymentHash,
68                Some(payment_identifier::Value::Hash(hash)),
69            ) => {
70                let decoded = hex::decode(hash)?;
71                let hash_array: [u8; 32] = decoded
72                    .try_into()
73                    .map_err(|_| crate::error::Error::InvalidHash)?;
74                Ok(CdkPaymentIdentifier::Bolt12PaymentHash(hash_array))
75            }
76            (PaymentIdentifierType::CustomId, Some(payment_identifier::Value::Id(id))) => {
77                Ok(CdkPaymentIdentifier::CustomId(id))
78            }
79            _ => Err(crate::error::Error::InvalidPaymentIdentifier),
80        }
81    }
82}
83
84impl TryFrom<MakePaymentResponse> for CdkMakePaymentResponse {
85    type Error = crate::error::Error;
86    fn try_from(value: MakePaymentResponse) -> Result<Self, Self::Error> {
87        let status = value.status().as_str_name().parse()?;
88        let payment_proof = value.payment_proof;
89        let total_spent = value.total_spent.into();
90        let unit = CurrencyUnit::from_str(&value.unit)?;
91        let payment_identifier = value
92            .payment_identifier
93            .ok_or(crate::error::Error::InvalidPaymentIdentifier)?;
94        Ok(Self {
95            payment_lookup_id: payment_identifier.try_into()?,
96            payment_proof,
97            status,
98            total_spent,
99            unit,
100        })
101    }
102}
103
104impl From<CdkMakePaymentResponse> for MakePaymentResponse {
105    fn from(value: CdkMakePaymentResponse) -> Self {
106        Self {
107            payment_identifier: Some(value.payment_lookup_id.into()),
108            payment_proof: value.payment_proof,
109            status: QuoteState::from(value.status).into(),
110            total_spent: value.total_spent.into(),
111            unit: value.unit.to_string(),
112        }
113    }
114}
115
116impl From<CreateIncomingPaymentResponse> for CreatePaymentResponse {
117    fn from(value: CreateIncomingPaymentResponse) -> Self {
118        Self {
119            request_identifier: Some(value.request_lookup_id.into()),
120            request: value.request,
121            expiry: value.expiry,
122        }
123    }
124}
125
126impl TryFrom<CreatePaymentResponse> for CreateIncomingPaymentResponse {
127    type Error = crate::error::Error;
128
129    fn try_from(value: CreatePaymentResponse) -> Result<Self, Self::Error> {
130        let request_identifier = value
131            .request_identifier
132            .ok_or(crate::error::Error::InvalidPaymentIdentifier)?;
133        Ok(Self {
134            request_lookup_id: request_identifier.try_into()?,
135            request: value.request,
136            expiry: value.expiry,
137        })
138    }
139}
140
141impl From<cdk_common::payment::PaymentQuoteResponse> for PaymentQuoteResponse {
142    fn from(value: cdk_common::payment::PaymentQuoteResponse) -> Self {
143        Self {
144            request_identifier: value.request_lookup_id.map(|i| i.into()),
145            amount: value.amount.into(),
146            fee: value.fee.into(),
147            unit: value.unit.to_string(),
148            state: QuoteState::from(value.state).into(),
149        }
150    }
151}
152
153impl From<PaymentQuoteResponse> for cdk_common::payment::PaymentQuoteResponse {
154    fn from(value: PaymentQuoteResponse) -> Self {
155        let state_val = value.state();
156        let request_identifier = value.request_identifier;
157
158        Self {
159            request_lookup_id: request_identifier
160                .map(|i| i.try_into().expect("valid request identifier")),
161            amount: value.amount.into(),
162            fee: value.fee.into(),
163            unit: CurrencyUnit::from_str(&value.unit).unwrap_or_default(),
164            state: state_val.into(),
165        }
166    }
167}
168
169impl From<MeltOptions> for CdkMeltOptions {
170    fn from(value: MeltOptions) -> Self {
171        match value.options.expect("option defined") {
172            melt_options::Options::Mpp(mpp) => Self::Mpp {
173                mpp: cashu::nuts::nut15::Mpp {
174                    amount: mpp.amount.into(),
175                },
176            },
177            melt_options::Options::Amountless(amountless) => Self::Amountless {
178                amountless: cashu::nuts::nut23::Amountless {
179                    amount_msat: amountless.amount_msat.into(),
180                },
181            },
182        }
183    }
184}
185
186impl From<CdkMeltOptions> for MeltOptions {
187    fn from(value: CdkMeltOptions) -> Self {
188        match value {
189            CdkMeltOptions::Mpp { mpp } => Self {
190                options: Some(melt_options::Options::Mpp(Mpp {
191                    amount: mpp.amount.into(),
192                })),
193            },
194            CdkMeltOptions::Amountless { amountless } => Self {
195                options: Some(melt_options::Options::Amountless(Amountless {
196                    amount_msat: amountless.amount_msat.into(),
197                })),
198            },
199        }
200    }
201}
202
203impl From<QuoteState> for cdk_common::nuts::MeltQuoteState {
204    fn from(value: QuoteState) -> Self {
205        match value {
206            QuoteState::Unpaid => Self::Unpaid,
207            QuoteState::Paid => Self::Paid,
208            QuoteState::Pending => Self::Pending,
209            QuoteState::Unknown => Self::Unknown,
210            QuoteState::Failed => Self::Failed,
211            QuoteState::Issued => Self::Unknown,
212        }
213    }
214}
215
216impl From<cdk_common::nuts::MeltQuoteState> for QuoteState {
217    fn from(value: cdk_common::nuts::MeltQuoteState) -> Self {
218        match value {
219            cdk_common::nuts::MeltQuoteState::Unpaid => Self::Unpaid,
220            cdk_common::nuts::MeltQuoteState::Paid => Self::Paid,
221            cdk_common::nuts::MeltQuoteState::Pending => Self::Pending,
222            cdk_common::nuts::MeltQuoteState::Unknown => Self::Unknown,
223            cdk_common::nuts::MeltQuoteState::Failed => Self::Failed,
224        }
225    }
226}
227
228impl From<cdk_common::nuts::MintQuoteState> for QuoteState {
229    fn from(value: cdk_common::nuts::MintQuoteState) -> Self {
230        match value {
231            cdk_common::nuts::MintQuoteState::Unpaid => Self::Unpaid,
232            cdk_common::nuts::MintQuoteState::Paid => Self::Paid,
233            cdk_common::nuts::MintQuoteState::Issued => Self::Issued,
234        }
235    }
236}
237
238impl From<WaitPaymentResponse> for WaitIncomingPaymentResponse {
239    fn from(value: WaitPaymentResponse) -> Self {
240        Self {
241            payment_identifier: Some(value.payment_identifier.into()),
242            payment_amount: value.payment_amount.into(),
243            unit: value.unit.to_string(),
244            payment_id: value.payment_id,
245        }
246    }
247}
248
249impl TryFrom<WaitIncomingPaymentResponse> for WaitPaymentResponse {
250    type Error = crate::error::Error;
251
252    fn try_from(value: WaitIncomingPaymentResponse) -> Result<Self, Self::Error> {
253        let payment_identifier = value
254            .payment_identifier
255            .ok_or(crate::error::Error::InvalidPaymentIdentifier)?
256            .try_into()?;
257
258        Ok(Self {
259            payment_identifier,
260            payment_amount: value.payment_amount.into(),
261            unit: CurrencyUnit::from_str(&value.unit)?,
262            payment_id: value.payment_id,
263        })
264    }
265}