1#![cfg(feature = "alloc")]
32
33use super::{
34 AccountId, AssetCode, AssetCode12, AssetCode4, ClaimableBalanceId, ContractId, Error, Hash,
35 Int128Parts, Int256Parts, MuxedAccount, MuxedAccountMed25519, MuxedEd25519Account, NodeId,
36 PoolId, PublicKey, ScAddress, SignerKey, SignerKeyEd25519SignedPayload, UInt128Parts,
37 UInt256Parts, Uint256,
38};
39use crate::num128::{
40 i128_str_from_pieces, i128_str_into_pieces, u128_str_from_pieces, u128_str_into_pieces,
41};
42use crate::num256::{
43 i256_str_from_pieces, i256_str_into_pieces, u256_str_from_pieces, u256_str_into_pieces,
44};
45
46impl From<stellar_strkey::DecodeError> for Error {
47 fn from(_: stellar_strkey::DecodeError) -> Self {
48 Error::Invalid
49 }
50}
51
52impl core::fmt::Display for PublicKey {
53 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
54 match self {
55 PublicKey::PublicKeyTypeEd25519(Uint256(k)) => {
56 let k = stellar_strkey::ed25519::PublicKey::from_payload(k)
57 .map_err(|_| core::fmt::Error)?;
58 let s = k.to_string();
59 f.write_str(&s)?;
60 }
61 }
62 Ok(())
63 }
64}
65
66impl core::str::FromStr for PublicKey {
67 type Err = Error;
68 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
69 let stellar_strkey::ed25519::PublicKey(k) =
70 stellar_strkey::ed25519::PublicKey::from_str(s)?;
71 Ok(PublicKey::PublicKeyTypeEd25519(Uint256(k)))
72 }
73}
74
75impl core::fmt::Display for AccountId {
76 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
77 self.0.fmt(f)
78 }
79}
80
81impl core::str::FromStr for AccountId {
82 type Err = Error;
83 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
84 Ok(AccountId(PublicKey::from_str(s)?))
85 }
86}
87
88impl core::fmt::Display for ContractId {
89 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
90 let k = stellar_strkey::Contract(self.0 .0);
91 let s = k.to_string();
92 f.write_str(&s)?;
93 Ok(())
94 }
95}
96
97impl core::str::FromStr for ContractId {
98 type Err = Error;
99 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
100 let stellar_strkey::Contract(h) = stellar_strkey::Contract::from_str(s)?;
101 Ok(ContractId(Hash(h)))
102 }
103}
104
105impl core::fmt::Display for PoolId {
106 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
107 let PoolId(Hash(p_id)) = self.clone();
108 let key = stellar_strkey::Strkey::LiquidityPool(stellar_strkey::LiquidityPool(p_id));
109 key.fmt(f)
110 }
111}
112
113impl core::str::FromStr for PoolId {
114 type Err = Error;
115 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
116 let pool_key = stellar_strkey::LiquidityPool::from_str(s)?;
117 Ok(PoolId(Hash(pool_key.0)))
118 }
119}
120
121impl core::fmt::Display for MuxedAccountMed25519 {
122 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
123 let MuxedAccountMed25519 {
124 ed25519: Uint256(ed25519),
125 id,
126 } = self;
127 let k = stellar_strkey::ed25519::MuxedAccount {
128 ed25519: *ed25519,
129 id: *id,
130 };
131 let s = k.to_string();
132 f.write_str(&s)?;
133 Ok(())
134 }
135}
136
137impl core::str::FromStr for MuxedAccountMed25519 {
138 type Err = Error;
139 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
140 let stellar_strkey::ed25519::MuxedAccount { ed25519, id } =
141 stellar_strkey::ed25519::MuxedAccount::from_str(s)?;
142 Ok(MuxedAccountMed25519 {
143 ed25519: Uint256(ed25519),
144 id,
145 })
146 }
147}
148
149impl core::str::FromStr for MuxedAccount {
150 type Err = Error;
151 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
152 let strkey = stellar_strkey::Strkey::from_str(s)?;
153 match strkey {
154 stellar_strkey::Strkey::PublicKeyEd25519(stellar_strkey::ed25519::PublicKey(k)) => {
155 Ok(MuxedAccount::Ed25519(Uint256(k)))
156 }
157 stellar_strkey::Strkey::MuxedAccountEd25519(
158 stellar_strkey::ed25519::MuxedAccount { ed25519, id },
159 ) => Ok(MuxedAccount::MuxedEd25519(MuxedAccountMed25519 {
160 ed25519: Uint256(ed25519),
161 id,
162 })),
163 stellar_strkey::Strkey::PrivateKeyEd25519(_)
164 | stellar_strkey::Strkey::PreAuthTx(_)
165 | stellar_strkey::Strkey::HashX(_)
166 | stellar_strkey::Strkey::SignedPayloadEd25519(_)
167 | stellar_strkey::Strkey::Contract(_)
168 | stellar_strkey::Strkey::LiquidityPool(_)
169 | stellar_strkey::Strkey::ClaimableBalance(_) => Err(Error::Invalid),
170 }
171 }
172}
173
174impl core::fmt::Display for MuxedAccount {
175 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
176 match self {
177 MuxedAccount::Ed25519(Uint256(k)) => {
178 let k = stellar_strkey::ed25519::PublicKey(*k);
179 let s = k.to_string();
180 f.write_str(&s)?;
181 }
182 MuxedAccount::MuxedEd25519(m) => m.fmt(f)?,
183 }
184 Ok(())
185 }
186}
187
188impl core::fmt::Display for NodeId {
189 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
190 self.0.fmt(f)
191 }
192}
193
194impl core::str::FromStr for NodeId {
195 type Err = Error;
196 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
197 Ok(NodeId(PublicKey::from_str(s)?))
198 }
199}
200
201impl core::fmt::Display for SignerKeyEd25519SignedPayload {
202 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
203 let SignerKeyEd25519SignedPayload {
204 ed25519: Uint256(ed25519),
205 payload,
206 } = self;
207 let k = stellar_strkey::ed25519::SignedPayload {
208 ed25519: *ed25519,
209 payload: payload.into(),
210 };
211 let s = k.to_string();
212 f.write_str(&s)?;
213 Ok(())
214 }
215}
216
217impl core::str::FromStr for SignerKeyEd25519SignedPayload {
218 type Err = Error;
219 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
220 let stellar_strkey::ed25519::SignedPayload { ed25519, payload } =
221 stellar_strkey::ed25519::SignedPayload::from_str(s)?;
222 Ok(SignerKeyEd25519SignedPayload {
223 ed25519: Uint256(ed25519),
224 payload: payload.try_into()?,
225 })
226 }
227}
228
229impl core::str::FromStr for SignerKey {
230 type Err = Error;
231 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
232 let strkey = stellar_strkey::Strkey::from_str(s)?;
233 match strkey {
234 stellar_strkey::Strkey::PublicKeyEd25519(stellar_strkey::ed25519::PublicKey(k)) => {
235 Ok(SignerKey::Ed25519(Uint256(k)))
236 }
237 stellar_strkey::Strkey::PreAuthTx(stellar_strkey::PreAuthTx(h)) => {
238 Ok(SignerKey::PreAuthTx(Uint256(h)))
239 }
240 stellar_strkey::Strkey::HashX(stellar_strkey::HashX(h)) => {
241 Ok(SignerKey::HashX(Uint256(h)))
242 }
243 stellar_strkey::Strkey::SignedPayloadEd25519(
244 stellar_strkey::ed25519::SignedPayload { ed25519, payload },
245 ) => Ok(SignerKey::Ed25519SignedPayload(
246 SignerKeyEd25519SignedPayload {
247 ed25519: Uint256(ed25519),
248 payload: payload.try_into()?,
249 },
250 )),
251 stellar_strkey::Strkey::PrivateKeyEd25519(_)
252 | stellar_strkey::Strkey::Contract(_)
253 | stellar_strkey::Strkey::MuxedAccountEd25519(_)
254 | stellar_strkey::Strkey::LiquidityPool(_)
255 | stellar_strkey::Strkey::ClaimableBalance(_) => Err(Error::Invalid),
256 }
257 }
258}
259
260impl core::fmt::Display for SignerKey {
261 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
262 match self {
263 SignerKey::Ed25519(Uint256(k)) => {
264 let k = stellar_strkey::ed25519::PublicKey(*k);
265 let s = k.to_string();
266 f.write_str(&s)?;
267 }
268 SignerKey::PreAuthTx(Uint256(h)) => {
269 let k = stellar_strkey::PreAuthTx(*h);
270 let s = k.to_string();
271 f.write_str(&s)?;
272 }
273 SignerKey::HashX(Uint256(h)) => {
274 let k = stellar_strkey::HashX(*h);
275 let s = k.to_string();
276 f.write_str(&s)?;
277 }
278 SignerKey::Ed25519SignedPayload(p) => p.fmt(f)?,
279 }
280 Ok(())
281 }
282}
283
284impl core::str::FromStr for MuxedEd25519Account {
285 type Err = Error;
286 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
287 let strkey = stellar_strkey::Strkey::from_str(s)?;
288 match strkey {
289 stellar_strkey::Strkey::MuxedAccountEd25519(muxed_ed25519) => Ok(MuxedEd25519Account {
290 id: muxed_ed25519.id,
291 ed25519: Uint256(muxed_ed25519.ed25519),
292 }),
293 _ => Err(Error::Invalid),
294 }
295 }
296}
297
298impl core::fmt::Display for MuxedEd25519Account {
299 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
300 let k =
301 stellar_strkey::Strkey::MuxedAccountEd25519(stellar_strkey::ed25519::MuxedAccount {
302 ed25519: self.ed25519.0,
303 id: self.id,
304 });
305 let s = k.to_string();
306 f.write_str(&s)
307 }
308}
309
310impl core::str::FromStr for ScAddress {
311 type Err = Error;
312 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
313 let strkey = stellar_strkey::Strkey::from_str(s)?;
314 match strkey {
315 stellar_strkey::Strkey::PublicKeyEd25519(stellar_strkey::ed25519::PublicKey(k)) => Ok(
316 ScAddress::Account(AccountId(PublicKey::PublicKeyTypeEd25519(Uint256(k)))),
317 ),
318 stellar_strkey::Strkey::Contract(stellar_strkey::Contract(h)) => {
319 Ok(ScAddress::Contract(ContractId(Hash(h))))
320 }
321 stellar_strkey::Strkey::MuxedAccountEd25519(muxed_ed25519) => {
322 Ok(ScAddress::MuxedAccount(MuxedEd25519Account {
323 id: muxed_ed25519.id,
324 ed25519: Uint256(muxed_ed25519.ed25519),
325 }))
326 }
327 stellar_strkey::Strkey::LiquidityPool(liquidity_pool) => {
328 Ok(ScAddress::LiquidityPool(PoolId(Hash(liquidity_pool.0))))
329 }
330 stellar_strkey::Strkey::ClaimableBalance(stellar_strkey::ClaimableBalance::V0(
331 claimable_balance,
332 )) => Ok(ScAddress::ClaimableBalance(
333 ClaimableBalanceId::ClaimableBalanceIdTypeV0(Hash(claimable_balance)),
334 )),
335 stellar_strkey::Strkey::PrivateKeyEd25519(_)
336 | stellar_strkey::Strkey::PreAuthTx(_)
337 | stellar_strkey::Strkey::HashX(_)
338 | stellar_strkey::Strkey::SignedPayloadEd25519(_) => Err(Error::Invalid),
339 }
340 }
341}
342
343impl core::fmt::Display for ScAddress {
344 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
345 match self {
346 ScAddress::Account(a) => a.fmt(f),
347 ScAddress::Contract(ContractId(Hash(h))) => {
348 let k = stellar_strkey::Contract(*h);
349 let s = k.to_string();
350 f.write_str(&s)
351 }
352 ScAddress::MuxedAccount(muxed_ed25519_account) => {
353 let k = stellar_strkey::Strkey::MuxedAccountEd25519(
354 stellar_strkey::ed25519::MuxedAccount {
355 ed25519: muxed_ed25519_account.ed25519.0,
356 id: muxed_ed25519_account.id,
357 },
358 );
359 let s = k.to_string();
360 f.write_str(&s)
361 }
362 ScAddress::ClaimableBalance(claimable_balance_id) => claimable_balance_id.fmt(f),
363 ScAddress::LiquidityPool(pool_id) => pool_id.fmt(f),
364 #[cfg(feature = "cap_0084_muxed_contract")]
370 ScAddress::MuxedContract(_) => Err(core::fmt::Error),
371 }
372 }
373}
374
375impl core::str::FromStr for AssetCode4 {
376 type Err = Error;
377 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
378 let mut code = AssetCode4([0u8; 4]);
379 escape_bytes::unescape_into(&mut code.0, s.as_bytes()).map_err(|_| Error::Invalid)?;
380 Ok(code)
381 }
382}
383
384impl core::fmt::Display for AssetCode4 {
385 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
386 if let Some(last_idx) = self.0.iter().rposition(|c| *c != 0) {
387 for b in escape_bytes::Escape::new(&self.0[..=last_idx]) {
388 write!(f, "{}", b as char)?;
389 }
390 }
391 Ok(())
392 }
393}
394
395impl core::str::FromStr for AssetCode12 {
396 type Err = Error;
397 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
398 let mut code = AssetCode12([0u8; 12]);
399 escape_bytes::unescape_into(&mut code.0, s.as_bytes()).map_err(|_| Error::Invalid)?;
400 Ok(code)
401 }
402}
403
404impl core::fmt::Display for AssetCode12 {
405 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
406 const MIN_LENGTH: usize = 5;
412 let len = MIN_LENGTH
413 + self
414 .0
415 .iter()
416 .skip(MIN_LENGTH)
417 .rposition(|c| *c != 0)
418 .map_or(0, |last_idx| last_idx + 1);
419 for b in escape_bytes::Escape::new(&self.0[..len]) {
420 write!(f, "{}", b as char)?;
421 }
422 Ok(())
423 }
424}
425
426impl core::str::FromStr for AssetCode {
427 type Err = Error;
428 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
429 let mut code = [0u8; 12];
430 let n = escape_bytes::unescape_into(&mut code, s.as_bytes()).map_err(|_| Error::Invalid)?;
431 if n <= 4 {
432 Ok(AssetCode::CreditAlphanum4(AssetCode4([
433 code[0], code[1], code[2], code[3],
434 ])))
435 } else if n <= 12 {
436 Ok(AssetCode::CreditAlphanum12(AssetCode12(code)))
437 } else {
438 Err(Error::Invalid)
439 }
440 }
441}
442
443impl core::fmt::Display for AssetCode {
444 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
445 match self {
446 AssetCode::CreditAlphanum4(c) => c.fmt(f),
447 AssetCode::CreditAlphanum12(c) => c.fmt(f),
448 }
449 }
450}
451
452impl core::str::FromStr for ClaimableBalanceId {
453 type Err = Error;
454 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
455 let stellar_strkey::ClaimableBalance::V0(cb_id) =
456 stellar_strkey::ClaimableBalance::from_str(s)?;
457 Ok(ClaimableBalanceId::ClaimableBalanceIdTypeV0(Hash(cb_id)))
458 }
459}
460
461impl core::fmt::Display for ClaimableBalanceId {
462 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
463 let ClaimableBalanceId::ClaimableBalanceIdTypeV0(Hash(cb_id)) = self.clone();
464 let key =
465 stellar_strkey::Strkey::ClaimableBalance(stellar_strkey::ClaimableBalance::V0(cb_id));
466 key.fmt(f)
467 }
468}
469
470impl core::fmt::Display for UInt128Parts {
471 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
472 let v = u128_str_from_pieces(self.hi, self.lo);
473 write!(f, "{v}")
474 }
475}
476
477impl core::str::FromStr for UInt128Parts {
478 type Err = Error;
479 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
480 let (hi, lo) = u128_str_into_pieces(s).map_err(|_| Error::Invalid)?;
481 Ok(Self { hi, lo })
482 }
483}
484
485impl core::fmt::Display for Int128Parts {
486 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
487 let v = i128_str_from_pieces(self.hi, self.lo);
488 write!(f, "{v}")
489 }
490}
491
492impl core::str::FromStr for Int128Parts {
493 type Err = Error;
494 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
495 let (hi, lo) = i128_str_into_pieces(s).map_err(|_| Error::Invalid)?;
496 Ok(Self { hi, lo })
497 }
498}
499
500impl core::fmt::Display for UInt256Parts {
501 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
502 let u256 = u256_str_from_pieces(self.hi_hi, self.hi_lo, self.lo_hi, self.lo_lo);
503 write!(f, "{u256}")
504 }
505}
506
507impl core::str::FromStr for UInt256Parts {
508 type Err = Error;
509 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
510 let (hi_hi, hi_lo, lo_hi, lo_lo) = u256_str_into_pieces(s).map_err(|_| Error::Invalid)?;
511 Ok(Self {
512 hi_hi,
513 hi_lo,
514 lo_hi,
515 lo_lo,
516 })
517 }
518}
519
520impl core::fmt::Display for Int256Parts {
521 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
522 let i256 = i256_str_from_pieces(self.hi_hi, self.hi_lo, self.lo_hi, self.lo_lo);
523 write!(f, "{i256}")
524 }
525}
526
527impl core::str::FromStr for Int256Parts {
528 type Err = Error;
529 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
530 let (hi_hi, hi_lo, lo_hi, lo_lo) = i256_str_into_pieces(s).map_err(|_| Error::Invalid)?;
531 Ok(Self {
532 hi_hi,
533 hi_lo,
534 lo_hi,
535 lo_lo,
536 })
537 }
538}