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)]
16#[cfg_attr(
17 feature = "serde",
18 derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
19)]
20pub enum Strkey {
21 PublicKeyEd25519(ed25519::PublicKey),
22 PrivateKeyEd25519(ed25519::PrivateKey),
23 PreAuthTx(PreAuthTx),
24 HashX(HashX),
25 MuxedAccountEd25519(ed25519::MuxedAccount),
26 SignedPayloadEd25519(ed25519::SignedPayload),
27 Contract(Contract),
28 LiquidityPool(LiquidityPool),
29 ClaimableBalance(ClaimableBalance),
30}
31
32impl Strkey {
33 const MAX_PAYLOAD_LEN: usize = ed25519::SignedPayload::MAX_PAYLOAD_LEN;
35 const MAX_BINARY_LEN: usize = binary_len(Self::MAX_PAYLOAD_LEN);
36 const MAX_ENCODED_LEN: usize = encode_len(Self::MAX_BINARY_LEN);
37 const _ASSERTS: () = {
38 assert!(Self::MAX_PAYLOAD_LEN == 100);
39 assert!(Self::MAX_BINARY_LEN == 103);
40 assert!(Self::MAX_ENCODED_LEN == 165);
41 assert!(Self::MAX_PAYLOAD_LEN >= ed25519::PrivateKey::PAYLOAD_LEN);
43 assert!(Self::MAX_PAYLOAD_LEN >= ed25519::PublicKey::PAYLOAD_LEN);
44 assert!(Self::MAX_PAYLOAD_LEN >= ed25519::MuxedAccount::PAYLOAD_LEN);
45 assert!(Self::MAX_PAYLOAD_LEN >= ed25519::SignedPayload::MAX_PAYLOAD_LEN);
46 assert!(Self::MAX_PAYLOAD_LEN >= PreAuthTx::PAYLOAD_LEN);
47 assert!(Self::MAX_PAYLOAD_LEN >= HashX::PAYLOAD_LEN);
48 assert!(Self::MAX_PAYLOAD_LEN >= Contract::PAYLOAD_LEN);
49 assert!(Self::MAX_PAYLOAD_LEN >= LiquidityPool::PAYLOAD_LEN);
50 assert!(Self::MAX_PAYLOAD_LEN >= ClaimableBalance::PAYLOAD_LEN);
51 assert!(Self::MAX_BINARY_LEN >= ed25519::PrivateKey::BINARY_LEN);
53 assert!(Self::MAX_BINARY_LEN >= ed25519::PublicKey::BINARY_LEN);
54 assert!(Self::MAX_BINARY_LEN >= ed25519::MuxedAccount::BINARY_LEN);
55 assert!(Self::MAX_BINARY_LEN >= ed25519::SignedPayload::MAX_BINARY_LEN);
56 assert!(Self::MAX_BINARY_LEN >= PreAuthTx::BINARY_LEN);
57 assert!(Self::MAX_BINARY_LEN >= HashX::BINARY_LEN);
58 assert!(Self::MAX_BINARY_LEN >= Contract::BINARY_LEN);
59 assert!(Self::MAX_BINARY_LEN >= LiquidityPool::BINARY_LEN);
60 assert!(Self::MAX_BINARY_LEN >= ClaimableBalance::BINARY_LEN);
61 assert!(Self::MAX_ENCODED_LEN >= ed25519::PrivateKey::ENCODED_LEN);
63 assert!(Self::MAX_ENCODED_LEN >= ed25519::PublicKey::ENCODED_LEN);
64 assert!(Self::MAX_ENCODED_LEN >= ed25519::MuxedAccount::ENCODED_LEN);
65 assert!(Self::MAX_ENCODED_LEN >= ed25519::SignedPayload::MAX_ENCODED_LEN);
66 assert!(Self::MAX_ENCODED_LEN >= PreAuthTx::ENCODED_LEN);
67 assert!(Self::MAX_ENCODED_LEN >= HashX::ENCODED_LEN);
68 assert!(Self::MAX_ENCODED_LEN >= Contract::ENCODED_LEN);
69 assert!(Self::MAX_ENCODED_LEN >= LiquidityPool::ENCODED_LEN);
70 assert!(Self::MAX_ENCODED_LEN >= ClaimableBalance::ENCODED_LEN);
71 };
72
73 pub fn to_string(&self) -> HeaplessString<{ Self::MAX_ENCODED_LEN }> {
74 let mut s: HeaplessString<{ Self::MAX_ENCODED_LEN }> = HeaplessString::new();
75 match self {
76 Self::PublicKeyEd25519(x) => s.push_str(x.to_string().as_str()).unwrap(),
77 Self::PrivateKeyEd25519(x) => s.push_str(x.to_string().as_str()).unwrap(),
78 Self::PreAuthTx(x) => s.push_str(x.to_string().as_str()).unwrap(),
79 Self::HashX(x) => s.push_str(x.to_string().as_str()).unwrap(),
80 Self::MuxedAccountEd25519(x) => s.push_str(x.to_string().as_str()).unwrap(),
81 Self::SignedPayloadEd25519(x) => s.push_str(x.to_string().as_str()).unwrap(),
82 Self::Contract(x) => s.push_str(x.to_string().as_str()).unwrap(),
83 Self::LiquidityPool(x) => s.push_str(x.to_string().as_str()).unwrap(),
84 Self::ClaimableBalance(x) => s.push_str(x.to_string().as_str()).unwrap(),
85 }
86 s
87 }
88
89 pub fn from_string(s: &str) -> Result<Self, DecodeError> {
90 Self::from_slice(s.as_bytes())
91 }
92
93 pub fn from_slice(s: &[u8]) -> Result<Self, DecodeError> {
94 let (ver, payload) = decode::<{ Self::MAX_PAYLOAD_LEN }, { Self::MAX_BINARY_LEN }>(s)?;
95 match ver {
96 version::PUBLIC_KEY_ED25519 => Ok(Self::PublicKeyEd25519(
97 ed25519::PublicKey::from_payload(&payload)?,
98 )),
99 version::PRIVATE_KEY_ED25519 => Ok(Self::PrivateKeyEd25519(
100 ed25519::PrivateKey::from_payload(&payload)?,
101 )),
102 version::PRE_AUTH_TX => Ok(Self::PreAuthTx(PreAuthTx::from_payload(&payload)?)),
103 version::HASH_X => Ok(Self::HashX(HashX::from_payload(&payload)?)),
104 version::MUXED_ACCOUNT_ED25519 => Ok(Self::MuxedAccountEd25519(
105 ed25519::MuxedAccount::from_payload(&payload)?,
106 )),
107 version::SIGNED_PAYLOAD_ED25519 => Ok(Self::SignedPayloadEd25519(
108 ed25519::SignedPayload::from_payload(&payload)?,
109 )),
110 version::CONTRACT => Ok(Self::Contract(Contract::from_payload(&payload)?)),
111 version::LIQUIDITY_POOL => {
112 Ok(Self::LiquidityPool(LiquidityPool::from_payload(&payload)?))
113 }
114 version::CLAIMABLE_BALANCE => Ok(Self::ClaimableBalance(
115 ClaimableBalance::from_payload(&payload)?,
116 )),
117 _ => Err(DecodeError::Invalid),
118 }
119 }
120}
121
122impl Display for Strkey {
123 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
124 write!(f, "{}", self.to_string())
125 }
126}
127
128impl FromStr for Strkey {
129 type Err = DecodeError;
130
131 fn from_str(s: &str) -> Result<Self, Self::Err> {
132 Strkey::from_string(s)
133 }
134}
135
136#[cfg(feature = "serde-decoded")]
137mod strkey_decoded_serde_impl {
138 use super::*;
139 use crate::decoded_json_format::Decoded;
140 use serde::{
141 de::{self, MapAccess, Visitor},
142 ser::SerializeMap,
143 Deserialize, Deserializer, Serialize, Serializer,
144 };
145
146 impl Serialize for Decoded<&Strkey> {
147 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
148 let mut map = serializer.serialize_map(Some(1))?;
149 match self.0 {
150 Strkey::PublicKeyEd25519(key) => {
151 map.serialize_entry("public_key_ed25519", &Decoded(key))?;
152 }
153 Strkey::PrivateKeyEd25519(key) => {
154 map.serialize_entry("private_key_ed25519", &Decoded(key))?;
155 }
156 Strkey::PreAuthTx(key) => {
157 map.serialize_entry("pre_auth_tx", &Decoded(key))?;
158 }
159 Strkey::HashX(key) => {
160 map.serialize_entry("hash_x", &Decoded(key))?;
161 }
162 Strkey::MuxedAccountEd25519(key) => {
163 map.serialize_entry("muxed_account_ed25519", &Decoded(key))?;
164 }
165 Strkey::SignedPayloadEd25519(key) => {
166 map.serialize_entry("signed_payload_ed25519", &Decoded(key))?;
167 }
168 Strkey::Contract(key) => {
169 map.serialize_entry("contract", &Decoded(key))?;
170 }
171 Strkey::LiquidityPool(key) => {
172 map.serialize_entry("liquidity_pool", &Decoded(key))?;
173 }
174 Strkey::ClaimableBalance(key) => {
175 map.serialize_entry("claimable_balance", &Decoded(key))?;
176 }
177 }
178 map.end()
179 }
180 }
181
182 impl<'de> Deserialize<'de> for Decoded<Strkey> {
183 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
184 struct StrkeyVisitor;
185
186 impl<'de> Visitor<'de> for StrkeyVisitor {
187 type Value = Decoded<Strkey>;
188
189 fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
190 formatter.write_str("a strkey object")
191 }
192
193 fn visit_map<M: MapAccess<'de>>(self, mut map: M) -> Result<Self::Value, M::Error> {
194 let key: &str = map
195 .next_key()?
196 .ok_or_else(|| de::Error::custom("expected a variant key"))?;
197
198 let strkey = match key {
199 "public_key_ed25519" => {
200 let Decoded(inner) = map.next_value()?;
201 Strkey::PublicKeyEd25519(inner)
202 }
203 "private_key_ed25519" => {
204 let Decoded(inner) = map.next_value()?;
205 Strkey::PrivateKeyEd25519(inner)
206 }
207 "pre_auth_tx" => {
208 let Decoded(inner) = map.next_value()?;
209 Strkey::PreAuthTx(inner)
210 }
211 "hash_x" => {
212 let Decoded(inner) = map.next_value()?;
213 Strkey::HashX(inner)
214 }
215 "muxed_account_ed25519" => {
216 let Decoded(inner) = map.next_value()?;
217 Strkey::MuxedAccountEd25519(inner)
218 }
219 "signed_payload_ed25519" => {
220 let Decoded(inner) = map.next_value()?;
221 Strkey::SignedPayloadEd25519(inner)
222 }
223 "contract" => {
224 let Decoded(inner) = map.next_value()?;
225 Strkey::Contract(inner)
226 }
227 "liquidity_pool" => {
228 let Decoded(inner) = map.next_value()?;
229 Strkey::LiquidityPool(inner)
230 }
231 "claimable_balance" => {
232 let Decoded(inner) = map.next_value()?;
233 Strkey::ClaimableBalance(inner)
234 }
235 _ => {
236 return Err(de::Error::unknown_variant(
237 key,
238 &[
239 "public_key_ed25519",
240 "private_key_ed25519",
241 "pre_auth_tx",
242 "hash_x",
243 "muxed_account_ed25519",
244 "signed_payload_ed25519",
245 "contract",
246 "liquidity_pool",
247 "claimable_balance",
248 ],
249 ))
250 }
251 };
252
253 Ok(Decoded(strkey))
254 }
255 }
256
257 deserializer.deserialize_map(StrkeyVisitor)
258 }
259 }
260}
261
262#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
263#[cfg_attr(
264 feature = "serde",
265 derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
266)]
267pub struct PreAuthTx(pub [u8; 32]);
268
269impl Debug for PreAuthTx {
270 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
271 write!(f, "PreAuthTx(")?;
272 for b in &self.0 {
273 write!(f, "{b:02x}")?;
274 }
275 write!(f, ")")
276 }
277}
278
279impl PreAuthTx {
280 pub(crate) const PAYLOAD_LEN: usize = 32;
281 pub(crate) const BINARY_LEN: usize = binary_len(Self::PAYLOAD_LEN);
282 pub(crate) const ENCODED_LEN: usize = encode_len(Self::BINARY_LEN);
283 const _ASSERTS: () = {
284 assert!(Self::BINARY_LEN == 35);
285 assert!(Self::ENCODED_LEN == 56);
286 };
287
288 pub fn to_string(&self) -> HeaplessString<{ Self::ENCODED_LEN }> {
289 encode::<{ Self::PAYLOAD_LEN }, { Self::BINARY_LEN }, { Self::ENCODED_LEN }>(
290 version::PRE_AUTH_TX,
291 &self.0,
292 )
293 }
294
295 fn from_payload(payload: &[u8]) -> Result<Self, DecodeError> {
296 Ok(Self(payload.try_into().map_err(|_| DecodeError::Invalid)?))
297 }
298
299 pub fn from_string(s: &str) -> Result<Self, DecodeError> {
300 Self::from_slice(s.as_bytes())
301 }
302
303 pub fn from_slice(s: &[u8]) -> Result<Self, DecodeError> {
304 let (ver, payload) = decode::<{ Self::PAYLOAD_LEN }, { Self::BINARY_LEN }>(s)?;
305 match ver {
306 version::PRE_AUTH_TX => Self::from_payload(&payload),
307 _ => Err(DecodeError::Invalid),
308 }
309 }
310}
311
312impl Display for PreAuthTx {
313 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
314 write!(f, "{}", self.to_string())
315 }
316}
317
318impl FromStr for PreAuthTx {
319 type Err = DecodeError;
320
321 fn from_str(s: &str) -> Result<Self, Self::Err> {
322 PreAuthTx::from_string(s)
323 }
324}
325
326#[cfg(feature = "serde-decoded")]
327mod pre_auth_tx_decoded_serde_impl {
328 use super::*;
329 use crate::decoded_json_format::Decoded;
330 use serde::{Deserialize, Deserializer, Serialize, Serializer};
331 use serde_with::serde_as;
332
333 #[serde_as]
334 #[derive(Serialize)]
335 #[serde(transparent)]
336 struct DecodedBorrowed<'a>(#[serde_as(as = "serde_with::hex::Hex")] &'a [u8; 32]);
337
338 #[serde_as]
339 #[derive(Deserialize)]
340 #[serde(transparent)]
341 struct DecodedOwned(#[serde_as(as = "serde_with::hex::Hex")] [u8; 32]);
342
343 impl Serialize for Decoded<&PreAuthTx> {
344 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
345 let Self(PreAuthTx(bytes)) = self;
346 DecodedBorrowed(bytes).serialize(serializer)
347 }
348 }
349
350 impl<'de> Deserialize<'de> for Decoded<PreAuthTx> {
351 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
352 let DecodedOwned(bytes) = DecodedOwned::deserialize(deserializer)?;
353 Ok(Decoded(PreAuthTx(bytes)))
354 }
355 }
356}
357
358#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
359#[cfg_attr(
360 feature = "serde",
361 derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
362)]
363pub struct HashX(pub [u8; 32]);
364
365impl Debug for HashX {
366 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
367 write!(f, "HashX(")?;
368 for b in &self.0 {
369 write!(f, "{b:02x}")?;
370 }
371 write!(f, ")")
372 }
373}
374
375impl HashX {
376 pub(crate) const PAYLOAD_LEN: usize = 32;
377 pub(crate) const BINARY_LEN: usize = binary_len(Self::PAYLOAD_LEN);
378 pub(crate) const ENCODED_LEN: usize = encode_len(Self::BINARY_LEN);
379 const _ASSERTS: () = {
380 assert!(Self::BINARY_LEN == 35);
381 assert!(Self::ENCODED_LEN == 56);
382 };
383
384 pub fn to_string(&self) -> HeaplessString<{ Self::ENCODED_LEN }> {
385 encode::<{ Self::PAYLOAD_LEN }, { Self::BINARY_LEN }, { Self::ENCODED_LEN }>(
386 version::HASH_X,
387 &self.0,
388 )
389 }
390
391 fn from_payload(payload: &[u8]) -> Result<Self, DecodeError> {
392 Ok(Self(payload.try_into().map_err(|_| DecodeError::Invalid)?))
393 }
394
395 pub fn from_string(s: &str) -> Result<Self, DecodeError> {
396 Self::from_slice(s.as_bytes())
397 }
398
399 pub fn from_slice(s: &[u8]) -> Result<Self, DecodeError> {
400 let (ver, payload) = decode::<{ Self::PAYLOAD_LEN }, { Self::BINARY_LEN }>(s)?;
401 match ver {
402 version::HASH_X => Self::from_payload(&payload),
403 _ => Err(DecodeError::Invalid),
404 }
405 }
406}
407
408impl Display for HashX {
409 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
410 write!(f, "{}", self.to_string())
411 }
412}
413
414impl FromStr for HashX {
415 type Err = DecodeError;
416
417 fn from_str(s: &str) -> Result<Self, Self::Err> {
418 HashX::from_string(s)
419 }
420}
421
422#[cfg(feature = "serde-decoded")]
423mod hash_x_decoded_serde_impl {
424 use super::*;
425 use crate::decoded_json_format::Decoded;
426 use serde::{Deserialize, Deserializer, Serialize, Serializer};
427 use serde_with::serde_as;
428
429 #[serde_as]
430 #[derive(Serialize)]
431 #[serde(transparent)]
432 struct DecodedBorrowed<'a>(#[serde_as(as = "serde_with::hex::Hex")] &'a [u8; 32]);
433
434 #[serde_as]
435 #[derive(Deserialize)]
436 #[serde(transparent)]
437 struct DecodedOwned(#[serde_as(as = "serde_with::hex::Hex")] [u8; 32]);
438
439 impl Serialize for Decoded<&HashX> {
440 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
441 let Self(HashX(bytes)) = self;
442 DecodedBorrowed(bytes).serialize(serializer)
443 }
444 }
445
446 impl<'de> Deserialize<'de> for Decoded<HashX> {
447 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
448 let DecodedOwned(bytes) = DecodedOwned::deserialize(deserializer)?;
449 Ok(Decoded(HashX(bytes)))
450 }
451 }
452}
453
454#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
455#[cfg_attr(
456 feature = "serde",
457 derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
458)]
459pub struct Contract(pub [u8; 32]);
460
461impl Debug for Contract {
462 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
463 write!(f, "Contract(")?;
464 for b in &self.0 {
465 write!(f, "{b:02x}")?;
466 }
467 write!(f, ")")
468 }
469}
470
471impl Contract {
472 pub(crate) const PAYLOAD_LEN: usize = 32;
473 pub(crate) const BINARY_LEN: usize = binary_len(Self::PAYLOAD_LEN);
474 pub(crate) const ENCODED_LEN: usize = encode_len(Self::BINARY_LEN);
475 const _ASSERTS: () = {
476 assert!(Self::BINARY_LEN == 35);
477 assert!(Self::ENCODED_LEN == 56);
478 };
479
480 pub fn to_string(&self) -> HeaplessString<{ Self::ENCODED_LEN }> {
481 encode::<{ Self::PAYLOAD_LEN }, { Self::BINARY_LEN }, { Self::ENCODED_LEN }>(
482 version::CONTRACT,
483 &self.0,
484 )
485 }
486
487 fn from_payload(payload: &[u8]) -> Result<Self, DecodeError> {
488 Ok(Self(payload.try_into().map_err(|_| DecodeError::Invalid)?))
489 }
490
491 pub fn from_string(s: &str) -> Result<Self, DecodeError> {
492 Self::from_slice(s.as_bytes())
493 }
494
495 pub fn from_slice(s: &[u8]) -> Result<Self, DecodeError> {
496 let (ver, payload) = decode::<{ Self::PAYLOAD_LEN }, { Self::BINARY_LEN }>(s)?;
497 match ver {
498 version::CONTRACT => Self::from_payload(&payload),
499 _ => Err(DecodeError::Invalid),
500 }
501 }
502}
503
504impl Display for Contract {
505 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
506 write!(f, "{}", self.to_string())
507 }
508}
509
510impl FromStr for Contract {
511 type Err = DecodeError;
512
513 fn from_str(s: &str) -> Result<Self, Self::Err> {
514 Contract::from_string(s)
515 }
516}
517
518#[cfg(feature = "serde-decoded")]
519mod contract_decoded_serde_impl {
520 use super::*;
521 use crate::decoded_json_format::Decoded;
522 use serde::{Deserialize, Deserializer, Serialize, Serializer};
523 use serde_with::serde_as;
524
525 #[serde_as]
526 #[derive(Serialize)]
527 #[serde(transparent)]
528 struct DecodedBorrowed<'a>(#[serde_as(as = "serde_with::hex::Hex")] &'a [u8; 32]);
529
530 #[serde_as]
531 #[derive(Deserialize)]
532 #[serde(transparent)]
533 struct DecodedOwned(#[serde_as(as = "serde_with::hex::Hex")] [u8; 32]);
534
535 impl Serialize for Decoded<&Contract> {
536 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
537 let Self(Contract(bytes)) = self;
538 DecodedBorrowed(bytes).serialize(serializer)
539 }
540 }
541
542 impl<'de> Deserialize<'de> for Decoded<Contract> {
543 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
544 let DecodedOwned(bytes) = DecodedOwned::deserialize(deserializer)?;
545 Ok(Decoded(Contract(bytes)))
546 }
547 }
548}
549
550#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
551#[cfg_attr(
552 feature = "serde",
553 derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
554)]
555pub struct LiquidityPool(pub [u8; 32]);
556
557impl Debug for LiquidityPool {
558 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
559 write!(f, "LiquidityPool(")?;
560 for b in &self.0 {
561 write!(f, "{b:02x}")?;
562 }
563 write!(f, ")")
564 }
565}
566
567impl LiquidityPool {
568 pub(crate) const PAYLOAD_LEN: usize = 32;
569 pub(crate) const BINARY_LEN: usize = binary_len(Self::PAYLOAD_LEN);
570 pub(crate) const ENCODED_LEN: usize = encode_len(Self::BINARY_LEN);
571 const _ASSERTS: () = {
572 assert!(Self::BINARY_LEN == 35);
573 assert!(Self::ENCODED_LEN == 56);
574 };
575
576 pub fn to_string(&self) -> HeaplessString<{ Self::ENCODED_LEN }> {
577 encode::<{ Self::PAYLOAD_LEN }, { Self::BINARY_LEN }, { Self::ENCODED_LEN }>(
578 version::LIQUIDITY_POOL,
579 &self.0,
580 )
581 }
582
583 fn from_payload(payload: &[u8]) -> Result<Self, DecodeError> {
584 Ok(Self(payload.try_into().map_err(|_| DecodeError::Invalid)?))
585 }
586
587 pub fn from_string(s: &str) -> Result<Self, DecodeError> {
588 Self::from_slice(s.as_bytes())
589 }
590
591 pub fn from_slice(s: &[u8]) -> Result<Self, DecodeError> {
592 let (ver, payload) = decode::<{ Self::PAYLOAD_LEN }, { Self::BINARY_LEN }>(s)?;
593 match ver {
594 version::LIQUIDITY_POOL => Self::from_payload(&payload),
595 _ => Err(DecodeError::Invalid),
596 }
597 }
598}
599
600impl Display for LiquidityPool {
601 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
602 write!(f, "{}", self.to_string())
603 }
604}
605
606impl FromStr for LiquidityPool {
607 type Err = DecodeError;
608
609 fn from_str(s: &str) -> Result<Self, Self::Err> {
610 LiquidityPool::from_string(s)
611 }
612}
613
614#[cfg(feature = "serde-decoded")]
615mod liquidity_pool_decoded_serde_impl {
616 use super::*;
617 use crate::decoded_json_format::Decoded;
618 use serde::{Deserialize, Deserializer, Serialize, Serializer};
619 use serde_with::serde_as;
620
621 #[serde_as]
622 #[derive(Serialize)]
623 #[serde(transparent)]
624 struct DecodedBorrowed<'a>(#[serde_as(as = "serde_with::hex::Hex")] &'a [u8; 32]);
625
626 #[serde_as]
627 #[derive(Deserialize)]
628 #[serde(transparent)]
629 struct DecodedOwned(#[serde_as(as = "serde_with::hex::Hex")] [u8; 32]);
630
631 impl Serialize for Decoded<&LiquidityPool> {
632 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
633 let Self(LiquidityPool(bytes)) = self;
634 DecodedBorrowed(bytes).serialize(serializer)
635 }
636 }
637
638 impl<'de> Deserialize<'de> for Decoded<LiquidityPool> {
639 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
640 let DecodedOwned(bytes) = DecodedOwned::deserialize(deserializer)?;
641 Ok(Decoded(LiquidityPool(bytes)))
642 }
643 }
644}
645
646#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
647#[cfg_attr(
648 feature = "serde",
649 derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
650)]
651pub enum ClaimableBalance {
652 V0([u8; 32]),
653}
654
655impl Debug for ClaimableBalance {
656 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
657 write!(f, "ClaimableBalance(")?;
658 match self {
659 Self::V0(v0) => {
660 write!(f, "V0(")?;
661 for b in v0 {
662 write!(f, "{b:02x}")?;
663 }
664 write!(f, ")")?;
665 }
666 }
667 write!(f, ")")
668 }
669}
670
671impl ClaimableBalance {
672 pub(crate) const PAYLOAD_LEN: usize = 1 + 32;
674 pub(crate) const BINARY_LEN: usize = binary_len(Self::PAYLOAD_LEN);
675 pub(crate) const ENCODED_LEN: usize = encode_len(Self::BINARY_LEN);
676 const _ASSERTS: () = {
677 assert!(Self::PAYLOAD_LEN == 33);
678 assert!(Self::BINARY_LEN == 36);
679 assert!(Self::ENCODED_LEN == 58);
680 };
681
682 pub fn to_string(&self) -> HeaplessString<{ Self::ENCODED_LEN }> {
683 match self {
684 Self::V0(v0) => {
685 let mut payload = [0; Self::PAYLOAD_LEN];
687 payload[1..].copy_from_slice(v0);
688 encode::<{ Self::PAYLOAD_LEN }, { Self::BINARY_LEN }, { Self::ENCODED_LEN }>(
689 version::CLAIMABLE_BALANCE,
690 &payload,
691 )
692 }
693 }
694 }
695
696 fn from_payload(payload: &[u8]) -> Result<Self, DecodeError> {
697 match payload {
698 [0, rest @ ..] => Ok(Self::V0(rest.try_into().map_err(|_| DecodeError::Invalid)?)),
700 _ => Err(DecodeError::Invalid),
701 }
702 }
703
704 pub fn from_string(s: &str) -> Result<Self, DecodeError> {
705 Self::from_slice(s.as_bytes())
706 }
707
708 pub fn from_slice(s: &[u8]) -> Result<Self, DecodeError> {
709 let (ver, payload) = decode::<{ Self::PAYLOAD_LEN }, { Self::BINARY_LEN }>(s)?;
710 match ver {
711 version::CLAIMABLE_BALANCE => Self::from_payload(&payload),
712 _ => Err(DecodeError::Invalid),
713 }
714 }
715}
716
717impl Display for ClaimableBalance {
718 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
719 write!(f, "{}", self.to_string())
720 }
721}
722
723impl FromStr for ClaimableBalance {
724 type Err = DecodeError;
725
726 fn from_str(s: &str) -> Result<Self, Self::Err> {
727 ClaimableBalance::from_string(s)
728 }
729}
730
731#[cfg(feature = "serde-decoded")]
732mod claimable_balance_decoded_serde_impl {
733 use super::*;
734 use crate::decoded_json_format::Decoded;
735 use serde::{Deserialize, Deserializer, Serialize, Serializer};
736 use serde_with::serde_as;
737
738 #[serde_as]
739 #[derive(Serialize)]
740 #[serde(rename_all = "snake_case")]
741 enum DecodedBorrowed<'a> {
742 V0(#[serde_as(as = "serde_with::hex::Hex")] &'a [u8; 32]),
743 }
744
745 #[serde_as]
746 #[derive(Deserialize)]
747 #[serde(rename_all = "snake_case")]
748 enum DecodedOwned {
749 V0(#[serde_as(as = "serde_with::hex::Hex")] [u8; 32]),
750 }
751
752 impl Serialize for Decoded<&ClaimableBalance> {
753 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
754 match self.0 {
755 ClaimableBalance::V0(bytes) => DecodedBorrowed::V0(bytes).serialize(serializer),
756 }
757 }
758 }
759
760 impl<'de> Deserialize<'de> for Decoded<ClaimableBalance> {
761 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
762 let decoded = DecodedOwned::deserialize(deserializer)?;
763 Ok(Decoded(match decoded {
764 DecodedOwned::V0(bytes) => ClaimableBalance::V0(bytes),
765 }))
766 }
767 }
768}