1use core::{
2 fmt::{Debug, Display},
3 str::FromStr,
4};
5
6use heapless::String as HeaplessString;
7
8use crate::{
9 convert::{binary_len, decode, encode, encode_len},
10 ed25519,
11 error::DecodeError,
12 version,
13};
14
15#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
20#[cfg_attr(
21 feature = "serde",
22 derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
23)]
24pub enum Strkey {
25 PublicKeyEd25519(ed25519::PublicKey),
26 PreAuthTx(PreAuthTx),
27 HashX(HashX),
28 MuxedAccountEd25519(ed25519::MuxedAccount),
29 SignedPayloadEd25519(ed25519::SignedPayload),
30 Contract(Contract),
31 LiquidityPool(LiquidityPool),
32 ClaimableBalance(ClaimableBalance),
33 MuxedContract(MuxedContract),
34}
35
36impl Strkey {
37 const MAX_PAYLOAD_LEN: usize = ed25519::SignedPayload::MAX_PAYLOAD_LEN;
39 const MAX_BINARY_LEN: usize = binary_len(Self::MAX_PAYLOAD_LEN);
40 pub const MAX_ENCODED_LEN: usize = encode_len(Self::MAX_BINARY_LEN);
41 const _ASSERTS: () = {
42 assert!(Self::MAX_PAYLOAD_LEN == 100);
43 assert!(Self::MAX_BINARY_LEN == 103);
44 assert!(Self::MAX_ENCODED_LEN == 165);
45 assert!(Self::MAX_PAYLOAD_LEN >= ed25519::PrivateKey::PAYLOAD_LEN);
47 assert!(Self::MAX_PAYLOAD_LEN >= ed25519::PublicKey::PAYLOAD_LEN);
48 assert!(Self::MAX_PAYLOAD_LEN >= ed25519::MuxedAccount::PAYLOAD_LEN);
49 assert!(Self::MAX_PAYLOAD_LEN >= ed25519::SignedPayload::MAX_PAYLOAD_LEN);
50 assert!(Self::MAX_PAYLOAD_LEN >= PreAuthTx::PAYLOAD_LEN);
51 assert!(Self::MAX_PAYLOAD_LEN >= HashX::PAYLOAD_LEN);
52 assert!(Self::MAX_PAYLOAD_LEN >= Contract::PAYLOAD_LEN);
53 assert!(Self::MAX_PAYLOAD_LEN >= LiquidityPool::PAYLOAD_LEN);
54 assert!(Self::MAX_PAYLOAD_LEN >= ClaimableBalance::PAYLOAD_LEN);
55 assert!(Self::MAX_PAYLOAD_LEN >= MuxedContract::PAYLOAD_LEN);
56 assert!(Self::MAX_BINARY_LEN >= ed25519::PrivateKey::BINARY_LEN);
58 assert!(Self::MAX_BINARY_LEN >= ed25519::PublicKey::BINARY_LEN);
59 assert!(Self::MAX_BINARY_LEN >= ed25519::MuxedAccount::BINARY_LEN);
60 assert!(Self::MAX_BINARY_LEN >= ed25519::SignedPayload::MAX_BINARY_LEN);
61 assert!(Self::MAX_BINARY_LEN >= PreAuthTx::BINARY_LEN);
62 assert!(Self::MAX_BINARY_LEN >= HashX::BINARY_LEN);
63 assert!(Self::MAX_BINARY_LEN >= Contract::BINARY_LEN);
64 assert!(Self::MAX_BINARY_LEN >= LiquidityPool::BINARY_LEN);
65 assert!(Self::MAX_BINARY_LEN >= ClaimableBalance::BINARY_LEN);
66 assert!(Self::MAX_BINARY_LEN >= MuxedContract::BINARY_LEN);
67 assert!(Self::MAX_ENCODED_LEN >= ed25519::PrivateKey::ENCODED_LEN);
69 assert!(Self::MAX_ENCODED_LEN >= ed25519::PublicKey::ENCODED_LEN);
70 assert!(Self::MAX_ENCODED_LEN >= ed25519::MuxedAccount::ENCODED_LEN);
71 assert!(Self::MAX_ENCODED_LEN >= ed25519::SignedPayload::MAX_ENCODED_LEN);
72 assert!(Self::MAX_ENCODED_LEN >= PreAuthTx::ENCODED_LEN);
73 assert!(Self::MAX_ENCODED_LEN >= HashX::ENCODED_LEN);
74 assert!(Self::MAX_ENCODED_LEN >= Contract::ENCODED_LEN);
75 assert!(Self::MAX_ENCODED_LEN >= LiquidityPool::ENCODED_LEN);
76 assert!(Self::MAX_ENCODED_LEN >= ClaimableBalance::ENCODED_LEN);
77 assert!(Self::MAX_ENCODED_LEN >= MuxedContract::ENCODED_LEN);
78 };
79
80 pub fn to_string(&self) -> HeaplessString<{ Self::MAX_ENCODED_LEN }> {
81 let mut s: HeaplessString<{ Self::MAX_ENCODED_LEN }> = HeaplessString::new();
82 match self {
83 Self::PublicKeyEd25519(x) => s.push_str(x.to_string().as_str()).unwrap(),
84 Self::PreAuthTx(x) => s.push_str(x.to_string().as_str()).unwrap(),
85 Self::HashX(x) => s.push_str(x.to_string().as_str()).unwrap(),
86 Self::MuxedAccountEd25519(x) => s.push_str(x.to_string().as_str()).unwrap(),
87 Self::SignedPayloadEd25519(x) => s.push_str(x.to_string().as_str()).unwrap(),
88 Self::Contract(x) => s.push_str(x.to_string().as_str()).unwrap(),
89 Self::LiquidityPool(x) => s.push_str(x.to_string().as_str()).unwrap(),
90 Self::ClaimableBalance(x) => s.push_str(x.to_string().as_str()).unwrap(),
91 Self::MuxedContract(x) => s.push_str(x.to_string().as_str()).unwrap(),
92 }
93 s
94 }
95
96 pub fn from_string(s: &str) -> Result<Self, DecodeError> {
97 Self::from_slice(s.as_bytes())
98 }
99
100 pub fn from_slice(s: &[u8]) -> Result<Self, DecodeError> {
101 if s.first() == Some(&b'S') {
105 return Err(DecodeError::PrivateKey);
106 }
107 let (ver, payload) = decode::<{ Self::MAX_PAYLOAD_LEN }, { Self::MAX_BINARY_LEN }>(s)?;
108 match ver {
109 version::PUBLIC_KEY_ED25519 => Ok(Self::PublicKeyEd25519(
110 ed25519::PublicKey::from_payload(&payload)?,
111 )),
112 version::PRE_AUTH_TX => Ok(Self::PreAuthTx(PreAuthTx::from_payload(&payload)?)),
113 version::HASH_X => Ok(Self::HashX(HashX::from_payload(&payload)?)),
114 version::MUXED_ACCOUNT_ED25519 => Ok(Self::MuxedAccountEd25519(
115 ed25519::MuxedAccount::from_payload(&payload)?,
116 )),
117 version::SIGNED_PAYLOAD_ED25519 => Ok(Self::SignedPayloadEd25519(
118 ed25519::SignedPayload::from_payload(&payload)?,
119 )),
120 version::CONTRACT => Ok(Self::Contract(Contract::from_payload(&payload)?)),
121 version::LIQUIDITY_POOL => {
122 Ok(Self::LiquidityPool(LiquidityPool::from_payload(&payload)?))
123 }
124 version::CLAIMABLE_BALANCE => Ok(Self::ClaimableBalance(
125 ClaimableBalance::from_payload(&payload)?,
126 )),
127 version::MUXED_CONTRACT => {
128 Ok(Self::MuxedContract(MuxedContract::from_payload(&payload)?))
129 }
130 _ => Err(DecodeError::UnsupportedVersion),
131 }
132 }
133}
134
135impl Display for Strkey {
136 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
137 write!(f, "{}", self.to_string())
138 }
139}
140
141impl FromStr for Strkey {
142 type Err = DecodeError;
143
144 fn from_str(s: &str) -> Result<Self, Self::Err> {
145 Strkey::from_string(s)
146 }
147}
148
149#[cfg(feature = "serde-decoded")]
150mod strkey_decoded_serde_impl {
151 use super::*;
152 use crate::decoded_json_format::Decoded;
153 use serde::{
154 de::{self, MapAccess, Visitor},
155 ser::SerializeMap,
156 Deserialize, Deserializer, Serialize, Serializer,
157 };
158
159 impl Serialize for Decoded<&Strkey> {
160 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
161 let mut map = serializer.serialize_map(Some(1))?;
162 match self.0 {
163 Strkey::PublicKeyEd25519(key) => {
164 map.serialize_entry("public_key_ed25519", &Decoded(key))?;
165 }
166 Strkey::PreAuthTx(key) => {
167 map.serialize_entry("pre_auth_tx", &Decoded(key))?;
168 }
169 Strkey::HashX(key) => {
170 map.serialize_entry("hash_x", &Decoded(key))?;
171 }
172 Strkey::MuxedAccountEd25519(key) => {
173 map.serialize_entry("muxed_account_ed25519", &Decoded(key))?;
174 }
175 Strkey::SignedPayloadEd25519(key) => {
176 map.serialize_entry("signed_payload_ed25519", &Decoded(key))?;
177 }
178 Strkey::Contract(key) => {
179 map.serialize_entry("contract", &Decoded(key))?;
180 }
181 Strkey::LiquidityPool(key) => {
182 map.serialize_entry("liquidity_pool", &Decoded(key))?;
183 }
184 Strkey::ClaimableBalance(key) => {
185 map.serialize_entry("claimable_balance", &Decoded(key))?;
186 }
187 Strkey::MuxedContract(key) => {
188 map.serialize_entry("muxed_contract", &Decoded(key))?;
189 }
190 }
191 map.end()
192 }
193 }
194
195 impl<'de> Deserialize<'de> for Decoded<Strkey> {
196 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
197 struct StrkeyVisitor;
198
199 impl<'de> Visitor<'de> for StrkeyVisitor {
200 type Value = Decoded<Strkey>;
201
202 fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
203 formatter.write_str("a strkey object")
204 }
205
206 fn visit_map<M: MapAccess<'de>>(self, mut map: M) -> Result<Self::Value, M::Error> {
207 let key: alloc::string::String = map
213 .next_key()?
214 .ok_or_else(|| de::Error::custom("expected a variant key"))?;
215
216 let strkey = match key.as_str() {
217 "public_key_ed25519" => {
218 let Decoded(inner) = map.next_value()?;
219 Strkey::PublicKeyEd25519(inner)
220 }
221 "pre_auth_tx" => {
222 let Decoded(inner) = map.next_value()?;
223 Strkey::PreAuthTx(inner)
224 }
225 "hash_x" => {
226 let Decoded(inner) = map.next_value()?;
227 Strkey::HashX(inner)
228 }
229 "muxed_account_ed25519" => {
230 let Decoded(inner) = map.next_value()?;
231 Strkey::MuxedAccountEd25519(inner)
232 }
233 "signed_payload_ed25519" => {
234 let Decoded(inner) = map.next_value()?;
235 Strkey::SignedPayloadEd25519(inner)
236 }
237 "contract" => {
238 let Decoded(inner) = map.next_value()?;
239 Strkey::Contract(inner)
240 }
241 "liquidity_pool" => {
242 let Decoded(inner) = map.next_value()?;
243 Strkey::LiquidityPool(inner)
244 }
245 "claimable_balance" => {
246 let Decoded(inner) = map.next_value()?;
247 Strkey::ClaimableBalance(inner)
248 }
249 "muxed_contract" => {
250 let Decoded(inner) = map.next_value()?;
251 Strkey::MuxedContract(inner)
252 }
253 _ => {
254 return Err(de::Error::unknown_variant(
255 &key,
256 &[
257 "public_key_ed25519",
258 "pre_auth_tx",
259 "hash_x",
260 "muxed_account_ed25519",
261 "signed_payload_ed25519",
262 "contract",
263 "liquidity_pool",
264 "claimable_balance",
265 "muxed_contract",
266 ],
267 ))
268 }
269 };
270
271 if map.next_key::<de::IgnoredAny>()?.is_some() {
272 return Err(de::Error::custom("expected exactly one variant key"));
273 }
274
275 Ok(Decoded(strkey))
276 }
277 }
278
279 deserializer.deserialize_map(StrkeyVisitor)
280 }
281 }
282}
283
284#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
286#[cfg_attr(
287 feature = "serde",
288 derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
289)]
290pub struct PreAuthTx(pub [u8; 32]);
291
292impl Debug for PreAuthTx {
293 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
294 write!(f, "PreAuthTx(")?;
295 for b in &self.0 {
296 write!(f, "{b:02x}")?;
297 }
298 write!(f, ")")
299 }
300}
301
302impl PreAuthTx {
303 pub(crate) const PAYLOAD_LEN: usize = 32;
304 pub(crate) const BINARY_LEN: usize = binary_len(Self::PAYLOAD_LEN);
305 pub const ENCODED_LEN: usize = encode_len(Self::BINARY_LEN);
306 const _ASSERTS: () = {
307 assert!(Self::BINARY_LEN == 35);
308 assert!(Self::ENCODED_LEN == 56);
309 };
310
311 pub fn to_string(&self) -> HeaplessString<{ Self::ENCODED_LEN }> {
312 encode::<{ Self::PAYLOAD_LEN }, { Self::BINARY_LEN }, { Self::ENCODED_LEN }>(
313 version::PRE_AUTH_TX,
314 &self.0,
315 )
316 }
317
318 fn from_payload(payload: &[u8]) -> Result<Self, DecodeError> {
319 Ok(Self(
320 payload
321 .try_into()
322 .map_err(|_| DecodeError::InvalidPayloadLength)?,
323 ))
324 }
325
326 pub fn from_string(s: &str) -> Result<Self, DecodeError> {
327 Self::from_slice(s.as_bytes())
328 }
329
330 pub fn from_slice(s: &[u8]) -> Result<Self, DecodeError> {
331 let (ver, payload) = decode::<{ Self::PAYLOAD_LEN }, { Self::BINARY_LEN }>(s)?;
332 match ver {
333 version::PRE_AUTH_TX => Self::from_payload(&payload),
334 _ => Err(DecodeError::UnsupportedVersion),
335 }
336 }
337}
338
339impl Display for PreAuthTx {
340 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
341 write!(f, "{}", self.to_string())
342 }
343}
344
345impl FromStr for PreAuthTx {
346 type Err = DecodeError;
347
348 fn from_str(s: &str) -> Result<Self, Self::Err> {
349 PreAuthTx::from_string(s)
350 }
351}
352
353#[cfg(feature = "serde-decoded")]
354mod pre_auth_tx_decoded_serde_impl {
355 use super::*;
356 use crate::decoded_json_format::Decoded;
357 use serde::{Deserialize, Deserializer, Serialize, Serializer};
358 use serde_with::serde_as;
359
360 #[serde_as]
361 #[derive(Serialize)]
362 #[serde(transparent)]
363 struct DecodedBorrowed<'a>(#[serde_as(as = "serde_with::hex::Hex")] &'a [u8; 32]);
364
365 #[serde_as]
366 #[derive(Deserialize)]
367 #[serde(transparent)]
368 struct DecodedOwned(#[serde_as(as = "serde_with::hex::Hex")] [u8; 32]);
369
370 impl Serialize for Decoded<&PreAuthTx> {
371 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
372 let Self(PreAuthTx(bytes)) = self;
373 DecodedBorrowed(bytes).serialize(serializer)
374 }
375 }
376
377 impl<'de> Deserialize<'de> for Decoded<PreAuthTx> {
378 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
379 let DecodedOwned(bytes) = DecodedOwned::deserialize(deserializer)?;
380 Ok(Decoded(PreAuthTx(bytes)))
381 }
382 }
383}
384
385#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
387#[cfg_attr(
388 feature = "serde",
389 derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
390)]
391pub struct HashX(pub [u8; 32]);
392
393impl Debug for HashX {
394 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
395 write!(f, "HashX(")?;
396 for b in &self.0 {
397 write!(f, "{b:02x}")?;
398 }
399 write!(f, ")")
400 }
401}
402
403impl HashX {
404 pub(crate) const PAYLOAD_LEN: usize = 32;
405 pub(crate) const BINARY_LEN: usize = binary_len(Self::PAYLOAD_LEN);
406 pub const ENCODED_LEN: usize = encode_len(Self::BINARY_LEN);
407 const _ASSERTS: () = {
408 assert!(Self::BINARY_LEN == 35);
409 assert!(Self::ENCODED_LEN == 56);
410 };
411
412 pub fn to_string(&self) -> HeaplessString<{ Self::ENCODED_LEN }> {
413 encode::<{ Self::PAYLOAD_LEN }, { Self::BINARY_LEN }, { Self::ENCODED_LEN }>(
414 version::HASH_X,
415 &self.0,
416 )
417 }
418
419 fn from_payload(payload: &[u8]) -> Result<Self, DecodeError> {
420 Ok(Self(
421 payload
422 .try_into()
423 .map_err(|_| DecodeError::InvalidPayloadLength)?,
424 ))
425 }
426
427 pub fn from_string(s: &str) -> Result<Self, DecodeError> {
428 Self::from_slice(s.as_bytes())
429 }
430
431 pub fn from_slice(s: &[u8]) -> Result<Self, DecodeError> {
432 let (ver, payload) = decode::<{ Self::PAYLOAD_LEN }, { Self::BINARY_LEN }>(s)?;
433 match ver {
434 version::HASH_X => Self::from_payload(&payload),
435 _ => Err(DecodeError::UnsupportedVersion),
436 }
437 }
438}
439
440impl Display for HashX {
441 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
442 write!(f, "{}", self.to_string())
443 }
444}
445
446impl FromStr for HashX {
447 type Err = DecodeError;
448
449 fn from_str(s: &str) -> Result<Self, Self::Err> {
450 HashX::from_string(s)
451 }
452}
453
454#[cfg(feature = "serde-decoded")]
455mod hash_x_decoded_serde_impl {
456 use super::*;
457 use crate::decoded_json_format::Decoded;
458 use serde::{Deserialize, Deserializer, Serialize, Serializer};
459 use serde_with::serde_as;
460
461 #[serde_as]
462 #[derive(Serialize)]
463 #[serde(transparent)]
464 struct DecodedBorrowed<'a>(#[serde_as(as = "serde_with::hex::Hex")] &'a [u8; 32]);
465
466 #[serde_as]
467 #[derive(Deserialize)]
468 #[serde(transparent)]
469 struct DecodedOwned(#[serde_as(as = "serde_with::hex::Hex")] [u8; 32]);
470
471 impl Serialize for Decoded<&HashX> {
472 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
473 let Self(HashX(bytes)) = self;
474 DecodedBorrowed(bytes).serialize(serializer)
475 }
476 }
477
478 impl<'de> Deserialize<'de> for Decoded<HashX> {
479 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
480 let DecodedOwned(bytes) = DecodedOwned::deserialize(deserializer)?;
481 Ok(Decoded(HashX(bytes)))
482 }
483 }
484}
485
486#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
488#[cfg_attr(
489 feature = "serde",
490 derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
491)]
492pub struct Contract(pub [u8; 32]);
493
494impl Debug for Contract {
495 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
496 write!(f, "Contract(")?;
497 for b in &self.0 {
498 write!(f, "{b:02x}")?;
499 }
500 write!(f, ")")
501 }
502}
503
504impl Contract {
505 pub(crate) const PAYLOAD_LEN: usize = 32;
506 pub(crate) const BINARY_LEN: usize = binary_len(Self::PAYLOAD_LEN);
507 pub const ENCODED_LEN: usize = encode_len(Self::BINARY_LEN);
508 const _ASSERTS: () = {
509 assert!(Self::BINARY_LEN == 35);
510 assert!(Self::ENCODED_LEN == 56);
511 };
512
513 pub fn to_string(&self) -> HeaplessString<{ Self::ENCODED_LEN }> {
514 encode::<{ Self::PAYLOAD_LEN }, { Self::BINARY_LEN }, { Self::ENCODED_LEN }>(
515 version::CONTRACT,
516 &self.0,
517 )
518 }
519
520 fn from_payload(payload: &[u8]) -> Result<Self, DecodeError> {
521 Ok(Self(
522 payload
523 .try_into()
524 .map_err(|_| DecodeError::InvalidPayloadLength)?,
525 ))
526 }
527
528 pub fn from_string(s: &str) -> Result<Self, DecodeError> {
529 Self::from_slice(s.as_bytes())
530 }
531
532 pub fn from_slice(s: &[u8]) -> Result<Self, DecodeError> {
533 let (ver, payload) = decode::<{ Self::PAYLOAD_LEN }, { Self::BINARY_LEN }>(s)?;
534 match ver {
535 version::CONTRACT => Self::from_payload(&payload),
536 _ => Err(DecodeError::UnsupportedVersion),
537 }
538 }
539}
540
541impl Display for Contract {
542 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
543 write!(f, "{}", self.to_string())
544 }
545}
546
547impl FromStr for Contract {
548 type Err = DecodeError;
549
550 fn from_str(s: &str) -> Result<Self, Self::Err> {
551 Contract::from_string(s)
552 }
553}
554
555#[cfg(feature = "serde-decoded")]
556mod contract_decoded_serde_impl {
557 use super::*;
558 use crate::decoded_json_format::Decoded;
559 use serde::{Deserialize, Deserializer, Serialize, Serializer};
560 use serde_with::serde_as;
561
562 #[serde_as]
563 #[derive(Serialize)]
564 #[serde(transparent)]
565 struct DecodedBorrowed<'a>(#[serde_as(as = "serde_with::hex::Hex")] &'a [u8; 32]);
566
567 #[serde_as]
568 #[derive(Deserialize)]
569 #[serde(transparent)]
570 struct DecodedOwned(#[serde_as(as = "serde_with::hex::Hex")] [u8; 32]);
571
572 impl Serialize for Decoded<&Contract> {
573 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
574 let Self(Contract(bytes)) = self;
575 DecodedBorrowed(bytes).serialize(serializer)
576 }
577 }
578
579 impl<'de> Deserialize<'de> for Decoded<Contract> {
580 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
581 let DecodedOwned(bytes) = DecodedOwned::deserialize(deserializer)?;
582 Ok(Decoded(Contract(bytes)))
583 }
584 }
585}
586
587#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
589#[cfg_attr(
590 feature = "serde",
591 derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
592)]
593pub struct LiquidityPool(pub [u8; 32]);
594
595impl Debug for LiquidityPool {
596 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
597 write!(f, "LiquidityPool(")?;
598 for b in &self.0 {
599 write!(f, "{b:02x}")?;
600 }
601 write!(f, ")")
602 }
603}
604
605impl LiquidityPool {
606 pub(crate) const PAYLOAD_LEN: usize = 32;
607 pub(crate) const BINARY_LEN: usize = binary_len(Self::PAYLOAD_LEN);
608 pub const ENCODED_LEN: usize = encode_len(Self::BINARY_LEN);
609 const _ASSERTS: () = {
610 assert!(Self::BINARY_LEN == 35);
611 assert!(Self::ENCODED_LEN == 56);
612 };
613
614 pub fn to_string(&self) -> HeaplessString<{ Self::ENCODED_LEN }> {
615 encode::<{ Self::PAYLOAD_LEN }, { Self::BINARY_LEN }, { Self::ENCODED_LEN }>(
616 version::LIQUIDITY_POOL,
617 &self.0,
618 )
619 }
620
621 fn from_payload(payload: &[u8]) -> Result<Self, DecodeError> {
622 Ok(Self(
623 payload
624 .try_into()
625 .map_err(|_| DecodeError::InvalidPayloadLength)?,
626 ))
627 }
628
629 pub fn from_string(s: &str) -> Result<Self, DecodeError> {
630 Self::from_slice(s.as_bytes())
631 }
632
633 pub fn from_slice(s: &[u8]) -> Result<Self, DecodeError> {
634 let (ver, payload) = decode::<{ Self::PAYLOAD_LEN }, { Self::BINARY_LEN }>(s)?;
635 match ver {
636 version::LIQUIDITY_POOL => Self::from_payload(&payload),
637 _ => Err(DecodeError::UnsupportedVersion),
638 }
639 }
640}
641
642impl Display for LiquidityPool {
643 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
644 write!(f, "{}", self.to_string())
645 }
646}
647
648impl FromStr for LiquidityPool {
649 type Err = DecodeError;
650
651 fn from_str(s: &str) -> Result<Self, Self::Err> {
652 LiquidityPool::from_string(s)
653 }
654}
655
656#[cfg(feature = "serde-decoded")]
657mod liquidity_pool_decoded_serde_impl {
658 use super::*;
659 use crate::decoded_json_format::Decoded;
660 use serde::{Deserialize, Deserializer, Serialize, Serializer};
661 use serde_with::serde_as;
662
663 #[serde_as]
664 #[derive(Serialize)]
665 #[serde(transparent)]
666 struct DecodedBorrowed<'a>(#[serde_as(as = "serde_with::hex::Hex")] &'a [u8; 32]);
667
668 #[serde_as]
669 #[derive(Deserialize)]
670 #[serde(transparent)]
671 struct DecodedOwned(#[serde_as(as = "serde_with::hex::Hex")] [u8; 32]);
672
673 impl Serialize for Decoded<&LiquidityPool> {
674 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
675 let Self(LiquidityPool(bytes)) = self;
676 DecodedBorrowed(bytes).serialize(serializer)
677 }
678 }
679
680 impl<'de> Deserialize<'de> for Decoded<LiquidityPool> {
681 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
682 let DecodedOwned(bytes) = DecodedOwned::deserialize(deserializer)?;
683 Ok(Decoded(LiquidityPool(bytes)))
684 }
685 }
686}
687
688#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
690#[cfg_attr(
691 feature = "serde",
692 derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
693)]
694pub enum ClaimableBalance {
695 V0([u8; 32]),
696}
697
698impl Debug for ClaimableBalance {
699 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
700 write!(f, "ClaimableBalance(")?;
701 match self {
702 Self::V0(v0) => {
703 write!(f, "V0(")?;
704 for b in v0 {
705 write!(f, "{b:02x}")?;
706 }
707 write!(f, ")")?;
708 }
709 }
710 write!(f, ")")
711 }
712}
713
714impl ClaimableBalance {
715 pub(crate) const PAYLOAD_LEN: usize = 1 + 32;
717 pub(crate) const BINARY_LEN: usize = binary_len(Self::PAYLOAD_LEN);
718 pub const ENCODED_LEN: usize = encode_len(Self::BINARY_LEN);
719 const _ASSERTS: () = {
720 assert!(Self::PAYLOAD_LEN == 33);
721 assert!(Self::BINARY_LEN == 36);
722 assert!(Self::ENCODED_LEN == 58);
723 };
724
725 pub fn to_string(&self) -> HeaplessString<{ Self::ENCODED_LEN }> {
726 match self {
727 Self::V0(v0) => {
728 let mut payload = [0; Self::PAYLOAD_LEN];
730 payload[1..].copy_from_slice(v0);
731 encode::<{ Self::PAYLOAD_LEN }, { Self::BINARY_LEN }, { Self::ENCODED_LEN }>(
732 version::CLAIMABLE_BALANCE,
733 &payload,
734 )
735 }
736 }
737 }
738
739 fn from_payload(payload: &[u8]) -> Result<Self, DecodeError> {
740 match payload {
741 [0, rest @ ..] => Ok(Self::V0(
743 rest.try_into()
744 .map_err(|_| DecodeError::InvalidPayloadLength)?,
745 )),
746 [_, ..] => Err(DecodeError::UnsupportedClaimableBalanceVersion),
747 [] => Err(DecodeError::InvalidPayloadLength),
748 }
749 }
750
751 pub fn from_string(s: &str) -> Result<Self, DecodeError> {
752 Self::from_slice(s.as_bytes())
753 }
754
755 pub fn from_slice(s: &[u8]) -> Result<Self, DecodeError> {
756 let (ver, payload) = decode::<{ Self::PAYLOAD_LEN }, { Self::BINARY_LEN }>(s)?;
757 match ver {
758 version::CLAIMABLE_BALANCE => Self::from_payload(&payload),
759 _ => Err(DecodeError::UnsupportedVersion),
760 }
761 }
762}
763
764impl Display for ClaimableBalance {
765 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
766 write!(f, "{}", self.to_string())
767 }
768}
769
770impl FromStr for ClaimableBalance {
771 type Err = DecodeError;
772
773 fn from_str(s: &str) -> Result<Self, Self::Err> {
774 ClaimableBalance::from_string(s)
775 }
776}
777
778#[cfg(feature = "serde-decoded")]
779mod claimable_balance_decoded_serde_impl {
780 use super::*;
781 use crate::decoded_json_format::Decoded;
782 use serde::{Deserialize, Deserializer, Serialize, Serializer};
783 use serde_with::serde_as;
784
785 #[serde_as]
786 #[derive(Serialize)]
787 #[serde(rename_all = "snake_case")]
788 enum DecodedBorrowed<'a> {
789 V0(#[serde_as(as = "serde_with::hex::Hex")] &'a [u8; 32]),
790 }
791
792 #[serde_as]
793 #[derive(Deserialize)]
794 #[serde(rename_all = "snake_case")]
795 enum DecodedOwned {
796 V0(#[serde_as(as = "serde_with::hex::Hex")] [u8; 32]),
797 }
798
799 impl Serialize for Decoded<&ClaimableBalance> {
800 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
801 match self.0 {
802 ClaimableBalance::V0(bytes) => DecodedBorrowed::V0(bytes).serialize(serializer),
803 }
804 }
805 }
806
807 impl<'de> Deserialize<'de> for Decoded<ClaimableBalance> {
808 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
809 let decoded = DecodedOwned::deserialize(deserializer)?;
810 Ok(Decoded(match decoded {
811 DecodedOwned::V0(bytes) => ClaimableBalance::V0(bytes),
812 }))
813 }
814 }
815}
816
817#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
820#[cfg_attr(
821 feature = "serde",
822 derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
823)]
824pub struct MuxedContract {
825 pub contract_id: [u8; 32],
826 pub id: u64,
827}
828
829impl Debug for MuxedContract {
830 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
831 write!(f, "MuxedContract(")?;
832 for b in &self.contract_id {
833 write!(f, "{b:02x}")?;
834 }
835 write!(f, ", {}", self.id)?;
836 write!(f, ")")
837 }
838}
839
840impl MuxedContract {
841 pub(crate) const PAYLOAD_LEN: usize = 32 + 8; pub(crate) const BINARY_LEN: usize = binary_len(Self::PAYLOAD_LEN);
843 pub const ENCODED_LEN: usize = encode_len(Self::BINARY_LEN);
844 const _ASSERTS: () = {
845 assert!(Self::BINARY_LEN == 43);
846 assert!(Self::ENCODED_LEN == 69);
847 };
848
849 pub fn to_string(&self) -> HeaplessString<{ Self::ENCODED_LEN }> {
850 let mut payload: [u8; Self::PAYLOAD_LEN] = [0; Self::PAYLOAD_LEN];
851 let (contract_id, id) = payload.split_at_mut(32);
852 contract_id.copy_from_slice(&self.contract_id);
853 id.copy_from_slice(&self.id.to_be_bytes());
854 encode::<{ Self::PAYLOAD_LEN }, { Self::BINARY_LEN }, { Self::ENCODED_LEN }>(
855 version::MUXED_CONTRACT,
856 &payload,
857 )
858 }
859
860 fn from_payload(payload: &[u8]) -> Result<Self, DecodeError> {
861 if payload.len() != Self::PAYLOAD_LEN {
862 return Err(DecodeError::InvalidPayloadLength);
863 }
864 let (contract_id, id) = payload.split_at(32);
865 Ok(Self {
866 contract_id: contract_id
867 .try_into()
868 .map_err(|_| DecodeError::InvalidPayloadLength)?,
869 id: u64::from_be_bytes(
870 id.try_into()
871 .map_err(|_| DecodeError::InvalidPayloadLength)?,
872 ),
873 })
874 }
875
876 pub fn from_string(s: &str) -> Result<Self, DecodeError> {
877 Self::from_slice(s.as_bytes())
878 }
879
880 pub fn from_slice(s: &[u8]) -> Result<Self, DecodeError> {
881 let (ver, payload) = decode::<{ Self::PAYLOAD_LEN }, { Self::BINARY_LEN }>(s)?;
882 match ver {
883 version::MUXED_CONTRACT => Self::from_payload(&payload),
884 _ => Err(DecodeError::UnsupportedVersion),
885 }
886 }
887}
888
889impl Display for MuxedContract {
890 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
891 write!(f, "{}", self.to_string())
892 }
893}
894
895impl FromStr for MuxedContract {
896 type Err = DecodeError;
897
898 fn from_str(s: &str) -> Result<Self, Self::Err> {
899 MuxedContract::from_string(s)
900 }
901}
902
903#[cfg(feature = "serde-decoded")]
904mod muxed_contract_decoded_serde_impl {
905 use super::*;
906 use crate::decoded_json_format::Decoded;
907 use serde::{Deserialize, Deserializer, Serialize, Serializer};
908 use serde_with::serde_as;
909
910 #[serde_as]
911 #[derive(Serialize)]
912 struct DecodedBorrowed<'a> {
913 #[serde_as(as = "serde_with::hex::Hex")]
914 contract_id: &'a [u8; 32],
915 id: u64,
916 }
917
918 #[serde_as]
919 #[derive(Deserialize)]
920 struct DecodedOwned {
921 #[serde_as(as = "serde_with::hex::Hex")]
922 contract_id: [u8; 32],
923 id: u64,
924 }
925
926 impl Serialize for Decoded<&MuxedContract> {
927 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
928 let Self(MuxedContract { contract_id, id }) = self;
929 DecodedBorrowed {
930 contract_id,
931 id: *id,
932 }
933 .serialize(serializer)
934 }
935 }
936
937 impl<'de> Deserialize<'de> for Decoded<MuxedContract> {
938 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
939 let DecodedOwned { contract_id, id } = DecodedOwned::deserialize(deserializer)?;
940 Ok(Decoded(MuxedContract { contract_id, id }))
941 }
942 }
943}