cashu/nuts/
nut03.rs

1//! NUT-03: Swap
2//!
3//! <https://github.com/cashubtc/nuts/blob/main/03.md>
4
5use serde::{Deserialize, Serialize};
6use thiserror::Error;
7
8#[cfg(feature = "wallet")]
9use super::nut00::PreMintSecrets;
10use super::nut00::{BlindSignature, BlindedMessage, Proofs};
11use crate::Amount;
12
13/// NUT03 Error
14#[derive(Debug, Error)]
15pub enum Error {
16    /// DHKE error
17    #[error(transparent)]
18    DHKE(#[from] crate::dhke::Error),
19    /// Amount Error
20    #[error(transparent)]
21    Amount(#[from] crate::amount::Error),
22}
23
24/// Preswap information
25#[cfg(feature = "wallet")]
26#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
27pub struct PreSwap {
28    /// Preswap mint secrets
29    pub pre_mint_secrets: PreMintSecrets,
30    /// Swap request
31    pub swap_request: SwapRequest,
32    /// Amount to increment keyset counter by
33    pub derived_secret_count: u32,
34    /// Fee amount
35    pub fee: Amount,
36}
37
38/// Swap Request [NUT-03]
39#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
40#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
41pub struct SwapRequest {
42    /// Proofs that are to be spent in a `Swap`
43    #[cfg_attr(feature = "swagger", schema(value_type = Vec<Proof>))]
44    pub inputs: Proofs,
45    /// Blinded Messages for Mint to sign
46    pub outputs: Vec<BlindedMessage>,
47}
48
49impl SwapRequest {
50    /// Create new [`SwapRequest`]
51    pub fn new(inputs: Proofs, outputs: Vec<BlindedMessage>) -> Self {
52        Self { inputs, outputs }
53    }
54
55    /// Total value of proofs in [`SwapRequest`]
56    pub fn input_amount(&self) -> Result<Amount, Error> {
57        Ok(Amount::try_sum(
58            self.inputs.iter().map(|proof| proof.amount),
59        )?)
60    }
61
62    /// Total value of outputs in [`SwapRequest`]
63    pub fn output_amount(&self) -> Result<Amount, Error> {
64        Ok(Amount::try_sum(
65            self.outputs.iter().map(|proof| proof.amount),
66        )?)
67    }
68}
69
70/// Split Response [NUT-06]
71#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
72#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
73pub struct SwapResponse {
74    /// Promises
75    pub signatures: Vec<BlindSignature>,
76}
77
78impl SwapResponse {
79    /// Create new [`SwapRequest`]
80    pub fn new(promises: Vec<BlindSignature>) -> SwapResponse {
81        SwapResponse {
82            signatures: promises,
83        }
84    }
85
86    /// Total [`Amount`] of promises
87    pub fn promises_amount(&self) -> Result<Amount, Error> {
88        Ok(Amount::try_sum(
89            self.signatures
90                .iter()
91                .map(|BlindSignature { amount, .. }| *amount),
92        )?)
93    }
94}