1use serde::{Deserialize, Serialize};
6use thiserror::Error;
7
8#[cfg(feature = "wallet")]
9use super::nut00::PreMintSecrets;
10use super::nut00::{BlindSignature, BlindedMessage, Proofs};
11use super::ProofsMethods;
12use crate::Amount;
13
14#[derive(Debug, Error)]
16pub enum Error {
17 #[error(transparent)]
19 DHKE(#[from] crate::dhke::Error),
20 #[error(transparent)]
22 Amount(#[from] crate::amount::Error),
23}
24
25#[cfg(feature = "wallet")]
27#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
28pub struct PreSwap {
29 pub pre_mint_secrets: PreMintSecrets,
31 pub swap_request: SwapRequest,
33 pub derived_secret_count: u32,
35 pub fee: Amount,
37}
38
39#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
41#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
42pub struct SwapRequest {
43 #[cfg_attr(feature = "swagger", schema(value_type = Vec<crate::Proof>))]
45 inputs: Proofs,
46 outputs: Vec<BlindedMessage>,
48}
49
50impl SwapRequest {
51 pub fn new(inputs: Proofs, outputs: Vec<BlindedMessage>) -> Self {
53 Self {
54 inputs: inputs.without_dleqs(),
55 outputs,
56 }
57 }
58
59 pub fn inputs(&self) -> &Proofs {
61 &self.inputs
62 }
63
64 pub fn inputs_mut(&mut self) -> &mut Proofs {
66 &mut self.inputs
67 }
68
69 pub fn outputs(&self) -> &Vec<BlindedMessage> {
71 &self.outputs
72 }
73
74 pub fn outputs_mut(&mut self) -> &mut Vec<BlindedMessage> {
76 &mut self.outputs
77 }
78
79 pub fn input_amount(&self) -> Result<Amount, Error> {
81 Ok(Amount::try_sum(
82 self.inputs.iter().map(|proof| proof.amount),
83 )?)
84 }
85
86 pub fn output_amount(&self) -> Result<Amount, Error> {
88 Ok(Amount::try_sum(
89 self.outputs.iter().map(|proof| proof.amount),
90 )?)
91 }
92}
93
94impl super::nut10::SpendingConditionVerification for SwapRequest {
95 fn inputs(&self) -> &Proofs {
96 &self.inputs
97 }
98
99 fn sig_all_msg_to_sign(&self) -> String {
100 let mut msg = String::new();
101
102 for proof in &self.inputs {
105 msg.push_str(&proof.secret.to_string());
106 msg.push_str(&proof.c.to_hex());
107 }
108
109 for output in &self.outputs {
112 msg.push_str(&output.amount.to_string());
113 msg.push_str(&output.blinded_secret.to_hex());
114 }
115
116 msg
117 }
118}
119
120#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
122#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
123pub struct SwapResponse {
124 pub signatures: Vec<BlindSignature>,
126}
127
128impl SwapResponse {
129 pub fn new(promises: Vec<BlindSignature>) -> Self {
131 Self {
132 signatures: promises,
133 }
134 }
135
136 pub fn promises_amount(&self) -> Result<Amount, Error> {
138 Ok(Amount::try_sum(
139 self.signatures
140 .iter()
141 .map(|BlindSignature { amount, .. }| *amount),
142 )?)
143 }
144}