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