algo_rust_sdk/
util.rs

1//! This file mostly just hides away various trait implementations that would clutter up and distract from the more important code elsewhere
2use crate::crypto::{Address, MultisigSignature, MultisigSubsig, Signature};
3use crate::kmd::responses::ExportKeyResponse;
4use crate::{Ed25519PublicKey, HashDigest, MasterDerivationKey, MicroAlgos, Round, VotePK, VRFPK};
5use data_encoding::BASE64;
6use serde::de::Visitor;
7use serde::{Deserialize, Deserializer, Serialize, Serializer};
8use static_assertions::_core::ops::{Add, Sub};
9use std::error::Error;
10use std::fmt::{Debug, Display, Formatter};
11use std::ops::Mul;
12use crate::transaction::{TransactionType, Transaction};
13
14impl Serialize for Transaction {
15    fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
16        where
17            S: Serializer,
18    {
19        use serde::ser::SerializeStruct;
20        let type_len = match &self.txn_type {
21            TransactionType::Payment(payment) => {
22                1 + if payment.close_remainder_to.is_some() {
23                    1
24                } else {
25                    0
26                } + if payment.amount.0 != 0 { 1 } else { 0 }
27            }
28            TransactionType::KeyRegistration(_) => 5,
29        };
30        let len = 6
31            + type_len
32            + if self.note.is_empty() { 0 } else { 1 }
33            + if self.genesis_id.is_empty() { 0 } else { 1 };
34        let mut state = serializer.serialize_struct("Transaction", len)?;
35        if let TransactionType::Payment(payment) = &self.txn_type {
36            if payment.amount.0 != 0 {
37                state.serialize_field("amt", &payment.amount)?;
38            }
39        }
40        if let TransactionType::Payment(payment) = &self.txn_type {
41            if payment.close_remainder_to.is_some() {
42                state.serialize_field("close", &payment.close_remainder_to)?;
43            }
44        }
45        state.serialize_field("fee", &self.fee)?;
46        state.serialize_field("fv", &self.first_valid)?;
47        if !self.genesis_id.is_empty() {
48            state.serialize_field("gen", &self.genesis_id)?;
49        }
50        state.serialize_field("gh", &self.genesis_hash)?;
51        state.serialize_field("lv", &self.last_valid)?;
52        if !self.note.is_empty() {
53            state.serialize_field("note", &serde_bytes::ByteBuf::from(self.note.clone()))?;
54        }
55        if let TransactionType::Payment(payment) = &self.txn_type {
56            state.serialize_field("rcv", &payment.receiver)?;
57        }
58        if let TransactionType::KeyRegistration(key_registration) = &self.txn_type {
59            state.serialize_field("selkey", &key_registration.selection_pk)?;
60        }
61        state.serialize_field("snd", &self.sender)?;
62        match &self.txn_type {
63            TransactionType::Payment(_payment) => {
64                state.serialize_field("type", "pay")?;
65            }
66            TransactionType::KeyRegistration(_key_registration) => {
67                state.serialize_field("type", "keyreg")?;
68            }
69        }
70        if let TransactionType::KeyRegistration(key_registration) = &self.txn_type {
71            state.serialize_field("votefst", &key_registration.vote_first)?;
72        }
73        if let TransactionType::KeyRegistration(key_registration) = &self.txn_type {
74            state.serialize_field("votekd", &key_registration.vote_key_dilution)?;
75        }
76        if let TransactionType::KeyRegistration(key_registration) = &self.txn_type {
77            state.serialize_field("votekey", &key_registration.vote_pk)?;
78        }
79        if let TransactionType::KeyRegistration(key_registration) = &self.txn_type {
80            state.serialize_field("votelst", &key_registration.vote_last)?;
81        }
82        state.end()
83    }
84}
85
86impl Serialize for HashDigest {
87    fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
88    where
89        S: Serializer,
90    {
91        serializer.serialize_bytes(&self.0[..])
92    }
93}
94
95impl Serialize for VotePK {
96    fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
97    where
98        S: Serializer,
99    {
100        serializer.serialize_bytes(&self.0[..])
101    }
102}
103
104impl Serialize for VRFPK {
105    fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
106    where
107        S: Serializer,
108    {
109        serializer.serialize_bytes(&self.0[..])
110    }
111}
112
113impl Serialize for Ed25519PublicKey {
114    fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
115    where
116        S: Serializer,
117    {
118        serializer.serialize_bytes(&self.0[..])
119    }
120}
121
122impl<'de> Deserialize<'de> for HashDigest {
123    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
124    where
125        D: Deserializer<'de>,
126    {
127        Ok(HashDigest(deserializer.deserialize_bytes(U8_32Visitor)?))
128    }
129}
130
131impl<'de> Deserialize<'de> for VotePK {
132    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
133    where
134        D: Deserializer<'de>,
135    {
136        Ok(VotePK(deserializer.deserialize_bytes(U8_32Visitor)?))
137    }
138}
139
140impl<'de> Deserialize<'de> for VRFPK {
141    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
142    where
143        D: Deserializer<'de>,
144    {
145        Ok(VRFPK(deserializer.deserialize_bytes(U8_32Visitor)?))
146    }
147}
148
149impl<'de> Deserialize<'de> for Ed25519PublicKey {
150    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
151    where
152        D: Deserializer<'de>,
153    {
154        Ok(Ed25519PublicKey(
155            deserializer.deserialize_bytes(U8_32Visitor)?,
156        ))
157    }
158}
159
160impl Serialize for MultisigSignature {
161    fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
162    where
163        S: Serializer,
164    {
165        // For some reason SerializeStruct ends up serializing as an array, so this explicitly serializes as a map
166        use serde::ser::SerializeMap;
167        let mut state = serializer.serialize_map(Some(3))?;
168        state.serialize_entry("subsig", &self.subsigs)?;
169        state.serialize_entry("thr", &self.threshold)?;
170        state.serialize_entry("v", &self.version)?;
171        state.end()
172    }
173}
174
175impl Serialize for MultisigSubsig {
176    fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
177    where
178        S: Serializer,
179    {
180        use serde::ser::SerializeMap;
181        let len = if self.sig.is_some() { 2 } else { 1 };
182        let mut state = serializer.serialize_map(Some(len))?;
183        state.serialize_entry("pk", &self.key)?;
184        if let Some(sig) = &self.sig {
185            state.serialize_entry("s", sig)?;
186        }
187        state.end()
188    }
189}
190
191impl Serialize for Address {
192    fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
193    where
194        S: Serializer,
195    {
196        serializer.serialize_bytes(&self.0[..])
197    }
198}
199
200impl<'de> Deserialize<'de> for Address {
201    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
202    where
203        D: Deserializer<'de>,
204    {
205        Ok(Address(deserializer.deserialize_bytes(U8_32Visitor)?))
206    }
207}
208
209impl Serialize for Signature {
210    fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
211    where
212        S: Serializer,
213    {
214        serializer.serialize_bytes(&self.0[..])
215    }
216}
217
218impl<'de> Deserialize<'de> for Signature {
219    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
220    where
221        D: Deserializer<'de>,
222    {
223        Ok(Signature(deserializer.deserialize_bytes(SignatureVisitor)?))
224    }
225}
226
227struct SignatureVisitor;
228
229impl<'de> Visitor<'de> for SignatureVisitor {
230    type Value = [u8; 64];
231
232    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
233        formatter.write_str("a 64 byte array")
234    }
235
236    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
237    where
238        E: serde::de::Error,
239    {
240        if v.len() == 64 {
241            let mut bytes = [0; 64];
242            bytes.copy_from_slice(v);
243            Ok(bytes)
244        } else {
245            Err(E::custom(format!("Invalid signature length: {}", v.len())))
246        }
247    }
248}
249
250pub(crate) struct U8_32Visitor;
251
252impl<'de> Visitor<'de> for U8_32Visitor {
253    type Value = [u8; 32];
254
255    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
256        formatter.write_str("a 32 byte array")
257    }
258
259    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
260    where
261        E: serde::de::Error,
262    {
263        if v.len() == 32 {
264            let mut bytes = [0; 32];
265            bytes.copy_from_slice(v);
266            Ok(bytes)
267        } else {
268            Err(E::custom(format!("Invalid byte array length: {}", v.len())))
269        }
270    }
271}
272
273pub fn deserialize_hash<'de, D>(deserializer: D) -> Result<HashDigest, D::Error>
274where
275    D: Deserializer<'de>,
276{
277    Ok(HashDigest(deserialize_bytes32(deserializer)?))
278}
279
280pub fn deserialize_mdk<'de, D>(deserializer: D) -> Result<MasterDerivationKey, D::Error>
281where
282    D: Deserializer<'de>,
283{
284    Ok(MasterDerivationKey(deserialize_bytes32(deserializer)?))
285}
286
287pub fn deserialize_bytes32<'de, D>(deserializer: D) -> Result<[u8; 32], D::Error>
288where
289    D: Deserializer<'de>,
290{
291    let s = <&str>::deserialize(deserializer)?;
292    let mut decoded = [0; 32];
293    decoded.copy_from_slice(&BASE64.decode(s.as_bytes()).unwrap());
294    Ok(decoded)
295}
296
297pub fn deserialize_bytes64<'de, D>(deserializer: D) -> Result<[u8; 64], D::Error>
298where
299    D: Deserializer<'de>,
300{
301    use serde::de::Error;
302    let s = <&str>::deserialize(deserializer)?;
303    let mut decoded = [0; 64];
304    let bytes = BASE64.decode(s.as_bytes()).map_err(D::Error::custom)?;
305    decoded.copy_from_slice(&bytes);
306    Ok(decoded)
307}
308
309pub fn deserialize_bytes<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
310where
311    D: Deserializer<'de>,
312{
313    let s = <&str>::deserialize(deserializer)?;
314    Ok(BASE64.decode(s.as_bytes()).unwrap())
315}
316
317pub fn serialize_bytes<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
318where
319    S: Serializer,
320{
321    serializer.serialize_str(&BASE64.encode(bytes))
322}
323
324impl Error for crate::Error {
325    fn source(&self) -> Option<&(dyn Error + 'static)> {
326        match self {
327            crate::Error::Reqwest(e) => Some(e),
328            crate::Error::Encode(e) => Some(e),
329            crate::Error::Json(e) => Some(e),
330            crate::Error::Api(_) => None,
331        }
332    }
333}
334
335impl From<rmp_serde::encode::Error> for crate::Error {
336    fn from(err: rmp_serde::encode::Error) -> Self {
337        crate::Error::Encode(err)
338    }
339}
340
341impl From<reqwest::Error> for crate::Error {
342    fn from(err: reqwest::Error) -> Self {
343        crate::Error::Reqwest(err)
344    }
345}
346
347impl From<serde_json::Error> for crate::Error {
348    fn from(err: serde_json::Error) -> Self {
349        crate::Error::Json(err)
350    }
351}
352
353impl Display for crate::Error {
354    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
355        match self {
356            crate::Error::Reqwest(e) => Display::fmt(e, f),
357            crate::Error::Encode(e) => Display::fmt(e, f),
358            crate::Error::Json(e) => Display::fmt(e, f),
359            crate::Error::Api(e) => Display::fmt(e, f),
360        }
361    }
362}
363
364impl Display for MicroAlgos {
365    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
366        Display::fmt(&self.0, f)
367    }
368}
369
370impl Display for Round {
371    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
372        Display::fmt(&self.0, f)
373    }
374}
375
376impl Debug for ExportKeyResponse {
377    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
378        f.debug_struct("ExportKeyResponse")
379            .field("private_key", &self.private_key.to_vec())
380            .finish()
381    }
382}
383
384impl Debug for Signature {
385    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
386        f.debug_tuple("Signature").field(&self.0.to_vec()).finish()
387    }
388}
389
390impl Add for Round {
391    type Output = Self;
392
393    fn add(self, rhs: Self) -> Self::Output {
394        Round(self.0 + rhs.0)
395    }
396}
397
398impl Add<u64> for Round {
399    type Output = Self;
400
401    fn add(self, rhs: u64) -> Self::Output {
402        Round(self.0 + rhs)
403    }
404}
405
406impl Add for MicroAlgos {
407    type Output = Self;
408
409    fn add(self, rhs: Self) -> Self::Output {
410        MicroAlgos(self.0 + rhs.0)
411    }
412}
413
414impl Add<u64> for MicroAlgos {
415    type Output = Self;
416
417    fn add(self, rhs: u64) -> Self::Output {
418        MicroAlgos(self.0 + rhs)
419    }
420}
421
422impl Sub for Round {
423    type Output = Self;
424
425    fn sub(self, rhs: Self) -> Self::Output {
426        Round(self.0 - rhs.0)
427    }
428}
429
430impl Sub<u64> for Round {
431    type Output = Self;
432
433    fn sub(self, rhs: u64) -> Self::Output {
434        Round(self.0 - rhs)
435    }
436}
437
438impl Sub for MicroAlgos {
439    type Output = Self;
440
441    fn sub(self, rhs: Self) -> Self::Output {
442        MicroAlgos(self.0 - rhs.0)
443    }
444}
445
446impl Sub<u64> for MicroAlgos {
447    type Output = Self;
448
449    fn sub(self, rhs: u64) -> Self::Output {
450        MicroAlgos(self.0 - rhs)
451    }
452}
453
454// Intentionally not implementing Mul<Rhs=Self>
455// If you're multiplying a Round by a Round or MicroAlgos by MicroAlgos, something has gone wrong in your math
456// That would give you MicroAlgos squared or Rounds squared and those don't exist
457impl Mul<u64> for Round {
458    type Output = Self;
459
460    fn mul(self, rhs: u64) -> Self::Output {
461        Round(self.0 * rhs)
462    }
463}
464
465impl Mul<u64> for MicroAlgos {
466    type Output = Self;
467
468    fn mul(self, rhs: u64) -> Self::Output {
469        MicroAlgos(self.0 * rhs)
470    }
471}
472
473impl PartialEq for Signature {
474    fn eq(&self, other: &Self) -> bool {
475        for i in 0..64 {
476            if self.0[i] != other.0[i] {
477                return false;
478            }
479        }
480        true
481    }
482}
483
484impl Eq for Signature {}