1#![cfg(feature = "alloc")]
25
26use super::{
27 AccountId, AssetCode, AssetCode12, AssetCode4, ClaimableBalanceId, Error, Hash, MuxedAccount,
28 MuxedAccountMed25519, NodeId, PublicKey, ScAddress, SignerKey, SignerKeyEd25519SignedPayload,
29 Uint256,
30};
31
32impl From<stellar_strkey::DecodeError> for Error {
33 fn from(_: stellar_strkey::DecodeError) -> Self {
34 Error::Invalid
35 }
36}
37
38impl core::fmt::Display for PublicKey {
39 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
40 match self {
41 PublicKey::PublicKeyTypeEd25519(Uint256(k)) => {
42 let k = stellar_strkey::ed25519::PublicKey::from_payload(k)
43 .map_err(|_| core::fmt::Error)?;
44 let s = k.to_string();
45 f.write_str(&s)?;
46 }
47 }
48 Ok(())
49 }
50}
51
52impl core::str::FromStr for PublicKey {
53 type Err = Error;
54 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
55 let stellar_strkey::ed25519::PublicKey(k) =
56 stellar_strkey::ed25519::PublicKey::from_str(s)?;
57 Ok(PublicKey::PublicKeyTypeEd25519(Uint256(k)))
58 }
59}
60
61impl core::fmt::Display for AccountId {
62 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
63 self.0.fmt(f)
64 }
65}
66
67impl core::str::FromStr for AccountId {
68 type Err = Error;
69 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
70 Ok(AccountId(PublicKey::from_str(s)?))
71 }
72}
73
74impl core::fmt::Display for MuxedAccountMed25519 {
75 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
76 let MuxedAccountMed25519 {
77 ed25519: Uint256(ed25519),
78 id,
79 } = self;
80 let k = stellar_strkey::ed25519::MuxedAccount {
81 ed25519: *ed25519,
82 id: *id,
83 };
84 let s = k.to_string();
85 f.write_str(&s)?;
86 Ok(())
87 }
88}
89
90impl core::str::FromStr for MuxedAccountMed25519 {
91 type Err = Error;
92 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
93 let stellar_strkey::ed25519::MuxedAccount { ed25519, id } =
94 stellar_strkey::ed25519::MuxedAccount::from_str(s)?;
95 Ok(MuxedAccountMed25519 {
96 ed25519: Uint256(ed25519),
97 id,
98 })
99 }
100}
101
102impl core::str::FromStr for MuxedAccount {
103 type Err = Error;
104 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
105 let strkey = stellar_strkey::Strkey::from_str(s)?;
106 match strkey {
107 stellar_strkey::Strkey::PublicKeyEd25519(stellar_strkey::ed25519::PublicKey(k)) => {
108 Ok(MuxedAccount::Ed25519(Uint256(k)))
109 }
110 stellar_strkey::Strkey::MuxedAccountEd25519(
111 stellar_strkey::ed25519::MuxedAccount { ed25519, id },
112 ) => Ok(MuxedAccount::MuxedEd25519(MuxedAccountMed25519 {
113 ed25519: Uint256(ed25519),
114 id,
115 })),
116 stellar_strkey::Strkey::PrivateKeyEd25519(_)
117 | stellar_strkey::Strkey::PreAuthTx(_)
118 | stellar_strkey::Strkey::HashX(_)
119 | stellar_strkey::Strkey::SignedPayloadEd25519(_)
120 | stellar_strkey::Strkey::Contract(_) => Err(Error::Invalid),
121 }
122 }
123}
124
125impl core::fmt::Display for MuxedAccount {
126 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
127 match self {
128 MuxedAccount::Ed25519(Uint256(k)) => {
129 let k = stellar_strkey::ed25519::PublicKey(*k);
130 let s = k.to_string();
131 f.write_str(&s)?;
132 }
133 MuxedAccount::MuxedEd25519(m) => m.fmt(f)?,
134 }
135 Ok(())
136 }
137}
138
139impl core::fmt::Display for NodeId {
140 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
141 self.0.fmt(f)
142 }
143}
144
145impl core::str::FromStr for NodeId {
146 type Err = Error;
147 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
148 Ok(NodeId(PublicKey::from_str(s)?))
149 }
150}
151
152impl core::fmt::Display for SignerKeyEd25519SignedPayload {
153 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
154 let SignerKeyEd25519SignedPayload {
155 ed25519: Uint256(ed25519),
156 payload,
157 } = self;
158 let k = stellar_strkey::ed25519::SignedPayload {
159 ed25519: *ed25519,
160 payload: payload.into(),
161 };
162 let s = k.to_string();
163 f.write_str(&s)?;
164 Ok(())
165 }
166}
167
168impl core::str::FromStr for SignerKeyEd25519SignedPayload {
169 type Err = Error;
170 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
171 let stellar_strkey::ed25519::SignedPayload { ed25519, payload } =
172 stellar_strkey::ed25519::SignedPayload::from_str(s)?;
173 Ok(SignerKeyEd25519SignedPayload {
174 ed25519: Uint256(ed25519),
175 payload: payload.try_into()?,
176 })
177 }
178}
179
180impl core::str::FromStr for SignerKey {
181 type Err = Error;
182 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
183 let strkey = stellar_strkey::Strkey::from_str(s)?;
184 match strkey {
185 stellar_strkey::Strkey::PublicKeyEd25519(stellar_strkey::ed25519::PublicKey(k)) => {
186 Ok(SignerKey::Ed25519(Uint256(k)))
187 }
188 stellar_strkey::Strkey::PreAuthTx(stellar_strkey::PreAuthTx(h)) => {
189 Ok(SignerKey::PreAuthTx(Uint256(h)))
190 }
191 stellar_strkey::Strkey::HashX(stellar_strkey::HashX(h)) => {
192 Ok(SignerKey::HashX(Uint256(h)))
193 }
194 stellar_strkey::Strkey::SignedPayloadEd25519(
195 stellar_strkey::ed25519::SignedPayload { ed25519, payload },
196 ) => Ok(SignerKey::Ed25519SignedPayload(
197 SignerKeyEd25519SignedPayload {
198 ed25519: Uint256(ed25519),
199 payload: payload.try_into()?,
200 },
201 )),
202 stellar_strkey::Strkey::PrivateKeyEd25519(_)
203 | stellar_strkey::Strkey::Contract(_)
204 | stellar_strkey::Strkey::MuxedAccountEd25519(_) => Err(Error::Invalid),
205 }
206 }
207}
208
209impl core::fmt::Display for SignerKey {
210 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
211 match self {
212 SignerKey::Ed25519(Uint256(k)) => {
213 let k = stellar_strkey::ed25519::PublicKey(*k);
214 let s = k.to_string();
215 f.write_str(&s)?;
216 }
217 SignerKey::PreAuthTx(Uint256(h)) => {
218 let k = stellar_strkey::PreAuthTx(*h);
219 let s = k.to_string();
220 f.write_str(&s)?;
221 }
222 SignerKey::HashX(Uint256(h)) => {
223 let k = stellar_strkey::HashX(*h);
224 let s = k.to_string();
225 f.write_str(&s)?;
226 }
227 SignerKey::Ed25519SignedPayload(p) => p.fmt(f)?,
228 }
229 Ok(())
230 }
231}
232
233impl core::str::FromStr for ScAddress {
234 type Err = Error;
235 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
236 let strkey = stellar_strkey::Strkey::from_str(s)?;
237 match strkey {
238 stellar_strkey::Strkey::PublicKeyEd25519(stellar_strkey::ed25519::PublicKey(k)) => Ok(
239 ScAddress::Account(AccountId(PublicKey::PublicKeyTypeEd25519(Uint256(k)))),
240 ),
241 stellar_strkey::Strkey::Contract(stellar_strkey::Contract(h)) => {
242 Ok(ScAddress::Contract(Hash(h)))
243 }
244 stellar_strkey::Strkey::MuxedAccountEd25519(_)
245 | stellar_strkey::Strkey::PrivateKeyEd25519(_)
246 | stellar_strkey::Strkey::PreAuthTx(_)
247 | stellar_strkey::Strkey::HashX(_)
248 | stellar_strkey::Strkey::SignedPayloadEd25519(_) => Err(Error::Invalid),
249 }
250 }
251}
252
253impl core::fmt::Display for ScAddress {
254 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
255 match self {
256 ScAddress::Account(a) => a.fmt(f)?,
257 ScAddress::Contract(Hash(h)) => {
258 let k = stellar_strkey::Contract(*h);
259 let s = k.to_string();
260 f.write_str(&s)?;
261 }
262 }
263 Ok(())
264 }
265}
266
267impl core::str::FromStr for AssetCode4 {
268 type Err = Error;
269 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
270 let mut code = AssetCode4([0u8; 4]);
271 escape_bytes::unescape_into(&mut code.0, s.as_bytes()).map_err(|_| Error::Invalid)?;
272 Ok(code)
273 }
274}
275
276impl core::fmt::Display for AssetCode4 {
277 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
278 if let Some(last_idx) = self.0.iter().rposition(|c| *c != 0) {
279 for b in escape_bytes::Escape::new(&self.0[..=last_idx]) {
280 write!(f, "{}", b as char)?;
281 }
282 }
283 Ok(())
284 }
285}
286
287impl core::str::FromStr for AssetCode12 {
288 type Err = Error;
289 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
290 let mut code = AssetCode12([0u8; 12]);
291 escape_bytes::unescape_into(&mut code.0, s.as_bytes()).map_err(|_| Error::Invalid)?;
292 Ok(code)
293 }
294}
295
296impl core::fmt::Display for AssetCode12 {
297 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
298 if let Some(last_idx) = self.0.iter().rposition(|c| *c != 0) {
299 for b in escape_bytes::Escape::new(&self.0[..=last_idx]) {
300 write!(f, "{}", b as char)?;
301 }
302 }
303 Ok(())
304 }
305}
306
307impl core::str::FromStr for AssetCode {
308 type Err = Error;
309 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
310 let mut code = [0u8; 12];
311 let n = escape_bytes::unescape_into(&mut code, s.as_bytes()).map_err(|_| Error::Invalid)?;
312 if n <= 4 {
313 Ok(AssetCode::CreditAlphanum4(AssetCode4([
314 code[0], code[1], code[2], code[3],
315 ])))
316 } else if n <= 12 {
317 Ok(AssetCode::CreditAlphanum12(AssetCode12(code)))
318 } else {
319 Err(Error::Invalid)
320 }
321 }
322}
323
324impl core::fmt::Display for AssetCode {
325 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
326 match self {
327 AssetCode::CreditAlphanum4(c) => c.fmt(f),
328 AssetCode::CreditAlphanum12(c) => c.fmt(f),
329 }
330 }
331}
332
333impl core::str::FromStr for ClaimableBalanceId {
334 type Err = Error;
335 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
336 let bytes = hex::decode(s).map_err(|_| Error::InvalidHex)?;
341 match bytes.as_slice() {
342 [0, 0, 0, 0, ..] => Ok(ClaimableBalanceId::ClaimableBalanceIdTypeV0(Hash(
343 (&bytes[4..]).try_into()?,
344 ))),
345 _ => Err(Error::Invalid),
346 }
347 }
348}
349
350impl core::fmt::Display for ClaimableBalanceId {
351 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
352 match self {
357 ClaimableBalanceId::ClaimableBalanceIdTypeV0(Hash(bytes)) => {
358 for b in [0u8, 0, 0, 0] {
359 write!(f, "{b:02x}")?;
360 }
361 for b in bytes {
362 write!(f, "{b:02x}")?;
363 }
364 }
365 }
366 Ok(())
367 }
368}