hcnet_strkey/
strkey.rs

1use std::{fmt::Debug, fmt::Display, str::FromStr};
2
3use crate::{
4    convert::{decode, encode},
5    ed25519,
6    error::DecodeError,
7    version,
8};
9
10#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
11pub enum Strkey {
12    PublicKeyEd25519(ed25519::PublicKey),
13    PrivateKeyEd25519(ed25519::PrivateKey),
14    PreAuthTx(PreAuthTx),
15    HashX(HashX),
16    MuxedAccountEd25519(ed25519::MuxedAccount),
17    SignedPayloadEd25519(ed25519::SignedPayload),
18    Contract(Contract),
19}
20
21impl Strkey {
22    pub fn to_string(&self) -> String {
23        match self {
24            Self::PublicKeyEd25519(x) => x.to_string(),
25            Self::PrivateKeyEd25519(x) => x.to_string(),
26            Self::PreAuthTx(x) => x.to_string(),
27            Self::HashX(x) => x.to_string(),
28            Self::MuxedAccountEd25519(x) => x.to_string(),
29            Self::SignedPayloadEd25519(x) => x.to_string(),
30            Self::Contract(x) => x.to_string(),
31        }
32    }
33
34    pub fn from_string(s: &str) -> Result<Self, DecodeError> {
35        let (ver, payload) = decode(s)?;
36        match ver {
37            version::PUBLIC_KEY_ED25519 => Ok(Self::PublicKeyEd25519(
38                ed25519::PublicKey::from_payload(&payload)?,
39            )),
40            version::PRIVATE_KEY_ED25519 => Ok(Self::PrivateKeyEd25519(
41                ed25519::PrivateKey::from_payload(&payload)?,
42            )),
43            version::PRE_AUTH_TX => Ok(Self::PreAuthTx(PreAuthTx::from_payload(&payload)?)),
44            version::HASH_X => Ok(Self::HashX(HashX::from_payload(&payload)?)),
45            version::MUXED_ACCOUNT_ED25519 => Ok(Self::MuxedAccountEd25519(
46                ed25519::MuxedAccount::from_payload(&payload)?,
47            )),
48            version::SIGNED_PAYLOAD_ED25519 => Ok(Self::SignedPayloadEd25519(
49                ed25519::SignedPayload::from_payload(&payload)?,
50            )),
51            version::CONTRACT => Ok(Self::Contract(Contract::from_payload(&payload)?)),
52            _ => Err(DecodeError::Invalid),
53        }
54    }
55}
56
57impl Display for Strkey {
58    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59        write!(f, "{}", self.to_string())
60    }
61}
62
63impl FromStr for Strkey {
64    type Err = DecodeError;
65
66    fn from_str(s: &str) -> Result<Self, Self::Err> {
67        Strkey::from_string(s)
68    }
69}
70
71#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
72pub struct PreAuthTx(pub [u8; 32]);
73
74impl Debug for PreAuthTx {
75    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76        write!(f, "PreAuthTx(")?;
77        write!(
78            f,
79            "{}",
80            &self
81                .0
82                .iter()
83                .map(|b| format!("{b:02x}"))
84                .collect::<String>()
85        )?;
86        write!(f, ")")?;
87        Ok(())
88    }
89}
90
91impl PreAuthTx {
92    pub fn to_string(&self) -> String {
93        encode(version::PRE_AUTH_TX, &self.0)
94    }
95
96    fn from_payload(payload: &[u8]) -> Result<Self, DecodeError> {
97        Ok(Self(payload.try_into().map_err(|_| DecodeError::Invalid)?))
98    }
99
100    pub fn from_string(s: &str) -> Result<Self, DecodeError> {
101        let (ver, payload) = decode(s)?;
102        match ver {
103            version::PRE_AUTH_TX => Self::from_payload(&payload),
104            _ => Err(DecodeError::Invalid),
105        }
106    }
107}
108
109impl Display for PreAuthTx {
110    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
111        write!(f, "{}", self.to_string())
112    }
113}
114
115impl FromStr for PreAuthTx {
116    type Err = DecodeError;
117
118    fn from_str(s: &str) -> Result<Self, Self::Err> {
119        PreAuthTx::from_string(s)
120    }
121}
122
123#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
124pub struct HashX(pub [u8; 32]);
125
126impl Debug for HashX {
127    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128        write!(f, "HashX(")?;
129        write!(
130            f,
131            "{}",
132            &self
133                .0
134                .iter()
135                .map(|b| format!("{b:02x}"))
136                .collect::<String>()
137        )?;
138        write!(f, ")")?;
139        Ok(())
140    }
141}
142
143impl HashX {
144    pub fn to_string(&self) -> String {
145        encode(version::HASH_X, &self.0)
146    }
147
148    fn from_payload(payload: &[u8]) -> Result<Self, DecodeError> {
149        Ok(Self(payload.try_into().map_err(|_| DecodeError::Invalid)?))
150    }
151
152    pub fn from_string(s: &str) -> Result<Self, DecodeError> {
153        let (ver, payload) = decode(s)?;
154        match ver {
155            version::HASH_X => Self::from_payload(&payload),
156            _ => Err(DecodeError::Invalid),
157        }
158    }
159}
160
161impl Display for HashX {
162    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
163        write!(f, "{}", self.to_string())
164    }
165}
166
167impl FromStr for HashX {
168    type Err = DecodeError;
169
170    fn from_str(s: &str) -> Result<Self, Self::Err> {
171        HashX::from_string(s)
172    }
173}
174
175#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
176pub struct Contract(pub [u8; 32]);
177
178impl Debug for Contract {
179    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
180        write!(f, "Contract(")?;
181        write!(
182            f,
183            "{}",
184            &self
185                .0
186                .iter()
187                .map(|b| format!("{b:02x}"))
188                .collect::<String>()
189        )?;
190        write!(f, ")")?;
191        Ok(())
192    }
193}
194
195impl Contract {
196    pub fn to_string(&self) -> String {
197        encode(version::CONTRACT, &self.0)
198    }
199
200    fn from_payload(payload: &[u8]) -> Result<Self, DecodeError> {
201        Ok(Self(payload.try_into().map_err(|_| DecodeError::Invalid)?))
202    }
203
204    pub fn from_string(s: &str) -> Result<Self, DecodeError> {
205        let (ver, payload) = decode(s)?;
206        match ver {
207            version::CONTRACT => Self::from_payload(&payload),
208            _ => Err(DecodeError::Invalid),
209        }
210    }
211}
212
213impl Display for Contract {
214    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
215        write!(f, "{}", self.to_string())
216    }
217}
218
219impl FromStr for Contract {
220    type Err = DecodeError;
221
222    fn from_str(s: &str) -> Result<Self, Self::Err> {
223        Contract::from_string(s)
224    }
225}