1use codec::{Compact, CompactAs, Decode, Encode};
2
3use core::{fmt, str::FromStr};
4
5#[cfg(feature = "serde")]
6use serde::{de, de::DeserializeOwned, ser, Deserialize, Serialize};
7
8#[cfg(all(feature = "std", feature = "type_info"))]
9use scale_info::TypeInfo;
10
11#[cfg(not(feature = "std"))]
12use alloc::{format, string::String};
13use sp_core::crypto::Ss58Codec;
14use sp_std::prelude::*;
15
16pub use frame_metadata;
18
19pub use sp_core;
20
21pub use sp_core::hashing;
22
23pub use sp_weights;
24
25pub use sp_runtime::MultiSignature;
26
27#[derive(
29 Clone, Copy, Debug, Encode, Decode, CompactAs, Default, PartialEq, Eq, PartialOrd, Ord,
30)]
31#[cfg_attr(all(feature = "std", feature = "type_info"), derive(TypeInfo))]
32#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
33#[cfg_attr(feature = "serde", serde(transparent))]
34pub struct OldWeight(pub u64);
35
36pub mod per_things {
38 use super::*;
39
40 #[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, PartialOrd, Ord)]
41 #[cfg_attr(feature = "std", derive(Hash))]
42 #[cfg_attr(all(feature = "std", feature = "type_info"), derive(TypeInfo))]
43 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
44 pub struct Perbill(pub u32);
45
46 impl CompactAs for Perbill {
47 type As = u32;
48
49 fn encode_as(&self) -> &Self::As {
50 &self.0
51 }
52
53 fn decode_from(v: Self::As) -> Result<Self, codec::Error> {
54 Ok(Self(v))
55 }
56 }
57
58 impl From<Compact<Self>> for Perbill {
59 fn from(c: Compact<Self>) -> Self {
60 c.0
61 }
62 }
63
64 impl From<sp_arithmetic::per_things::Perbill> for Perbill {
65 fn from(p: sp_arithmetic::per_things::Perbill) -> Self {
66 Self(p.deconstruct())
67 }
68 }
69
70 #[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, PartialOrd, Ord)]
71 #[cfg_attr(feature = "std", derive(Hash))]
72 #[cfg_attr(all(feature = "std", feature = "type_info"), derive(TypeInfo))]
73 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
74 pub struct PerU16(pub u16);
75
76 impl CompactAs for PerU16 {
77 type As = u16;
78
79 fn encode_as(&self) -> &Self::As {
80 &self.0
81 }
82
83 fn decode_from(v: Self::As) -> Result<Self, codec::Error> {
84 Ok(Self(v))
85 }
86 }
87
88 impl From<Compact<Self>> for PerU16 {
89 fn from(c: Compact<Self>) -> Self {
90 c.0
91 }
92 }
93
94 impl From<sp_arithmetic::per_things::PerU16> for PerU16 {
95 fn from(p: sp_arithmetic::per_things::PerU16) -> Self {
96 Self(p.deconstruct())
97 }
98 }
99
100 #[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, PartialOrd, Ord)]
101 #[cfg_attr(feature = "std", derive(Hash))]
102 #[cfg_attr(all(feature = "std", feature = "type_info"), derive(TypeInfo))]
103 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
104 pub struct Permill(pub u32);
105
106 impl CompactAs for Permill {
107 type As = u32;
108
109 fn encode_as(&self) -> &Self::As {
110 &self.0
111 }
112
113 fn decode_from(v: Self::As) -> Result<Self, codec::Error> {
114 Ok(Self(v))
115 }
116 }
117
118 impl From<Compact<Self>> for Permill {
119 fn from(c: Compact<Self>) -> Self {
120 c.0
121 }
122 }
123
124 impl From<sp_arithmetic::per_things::Permill> for Permill {
125 fn from(p: sp_arithmetic::per_things::Permill) -> Self {
126 Self(p.deconstruct())
127 }
128 }
129
130 #[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, PartialOrd, Ord)]
131 #[cfg_attr(feature = "std", derive(Hash))]
132 #[cfg_attr(all(feature = "std", feature = "type_info"), derive(TypeInfo))]
133 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
134 pub struct Percent(pub u8);
135
136 impl CompactAs for Percent {
137 type As = u8;
138
139 fn encode_as(&self) -> &Self::As {
140 &self.0
141 }
142
143 fn decode_from(v: Self::As) -> Result<Self, codec::Error> {
144 Ok(Self(v))
145 }
146 }
147
148 impl From<Compact<Self>> for Percent {
149 fn from(c: Compact<Self>) -> Self {
150 c.0
151 }
152 }
153
154 impl From<sp_arithmetic::per_things::Percent> for Percent {
155 fn from(p: sp_arithmetic::per_things::Percent) -> Self {
156 Self(p.deconstruct())
157 }
158 }
159}
160
161#[cfg(not(feature = "serde"))]
162pub trait AccountTraits: Clone + Encode + Decode + Default + FromStr {}
163
164#[cfg(not(feature = "serde"))]
165impl<T> AccountTraits for T where T: Clone + Encode + Decode + Default + FromStr {}
166
167#[cfg(feature = "serde")]
168pub trait AccountTraits:
169 Clone + Encode + Decode + Default + FromStr + ser::Serialize + DeserializeOwned
170{
171}
172
173#[cfg(feature = "serde")]
174impl<T> AccountTraits for T where
175 T: Clone + Encode + Decode + Default + FromStr + ser::Serialize + DeserializeOwned
176{
177}
178
179#[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, PartialOrd, Ord)]
181#[cfg_attr(feature = "std", derive(Hash))]
182#[cfg_attr(all(feature = "std", feature = "type_info"), derive(TypeInfo))]
183pub enum MultiAddress<AccountId: AccountTraits, AccountIndex: AccountTraits> {
184 Id(AccountId),
186 Index(#[codec(compact)] AccountIndex),
188 Raw(Vec<u8>),
190 Address32([u8; 32]),
192 Address20([u8; 20]),
194}
195
196#[cfg(feature = "serde")]
197impl<AccountId, AccountIndex> ser::Serialize for MultiAddress<AccountId, AccountIndex>
198where
199 AccountId: AccountTraits,
200 AccountIndex: AccountTraits,
201{
202 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
203 where
204 S: ser::Serializer,
205 {
206 match self {
207 Self::Id(account) => {
208 if serializer.is_human_readable() {
209 account.serialize(serializer)
210 } else {
211 serializer.serialize_newtype_variant("MultiAddress", 0, "Id", account)
212 }
213 }
214 Self::Index(index) => serializer.serialize_newtype_variant("MultiAddress", 1, "Index", index),
215 Self::Raw(data) => {
216 if serializer.is_human_readable() {
217 let h = hex::encode(data.as_slice());
218 serializer.serialize_newtype_variant("MultiAddress", 2, "Raw", &h)
219 } else {
220 serializer.serialize_newtype_variant("MultiAddress", 2, "Raw", data)
221 }
222 }
223 Self::Address32(address) => {
224 if serializer.is_human_readable() {
225 let h = hex::encode(&address[..]);
226 serializer.serialize_newtype_variant("MultiAddress", 3, "Address32", &h)
227 } else {
228 serializer.serialize_newtype_variant("MultiAddress", 3, "Address32", address)
229 }
230 }
231 Self::Address20(address) => {
232 if serializer.is_human_readable() {
233 let h = hex::encode(&address[..]);
234 serializer.serialize_newtype_variant("MultiAddress", 4, "Address20", &h)
235 } else {
236 serializer.serialize_newtype_variant("MultiAddress", 4, "Address20", address)
237 }
238 }
239 }
240 }
241}
242
243#[cfg(feature = "serde")]
244#[derive(Deserialize)]
245#[serde(field_identifier, rename_all = "PascalCase")]
246enum MultiAddressField {
247 Id,
248 Index,
249 Raw,
250 Address32,
251 Address20,
252}
253
254#[cfg(feature = "serde")]
255#[derive(Default)]
256struct MultiAddressVisitor<AccountId: AccountTraits, AccountIndex: AccountTraits> {
257 is_human_readable: bool,
258 _phantom: core::marker::PhantomData<(AccountId, AccountIndex)>,
259}
260
261#[cfg(feature = "serde")]
262impl<AccountId: AccountTraits, AccountIndex: AccountTraits>
263 MultiAddressVisitor<AccountId, AccountIndex>
264{
265 fn new(is_human_readable: bool) -> Self {
266 Self {
267 is_human_readable,
268 _phantom: Default::default(),
269 }
270 }
271}
272
273#[cfg(feature = "serde")]
274impl<'de, AccountId, AccountIndex> de::Visitor<'de> for MultiAddressVisitor<AccountId, AccountIndex>
275where
276 AccountId: AccountTraits,
277 AccountIndex: AccountTraits,
278{
279 type Value = MultiAddress<AccountId, AccountIndex>;
280
281 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
282 formatter.write_str("AccountId or MultiAddress")
283 }
284
285 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
286 where
287 E: de::Error,
288 {
289 let account = AccountId::from_str(v)
290 .map_err(|_e| de::Error::custom(format!("Failed to decode AccountId")))?;
291 Ok(MultiAddress::Id(account))
292 }
293
294 fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
295 where
296 V: de::MapAccess<'de>,
297 {
298 let mut address = None;
299 while let Some(key) = map.next_key()? {
300 match key {
301 MultiAddressField::Id => {
302 if address.is_some() {
303 return Err(de::Error::duplicate_field("Id"));
304 }
305 address = Some(MultiAddress::Id(map.next_value()?));
306 }
307 MultiAddressField::Index => {
308 if address.is_some() {
309 return Err(de::Error::duplicate_field("Index"));
310 }
311 address = Some(MultiAddress::Index(map.next_value()?));
312 }
313 MultiAddressField::Raw => {
314 if address.is_some() {
315 return Err(de::Error::duplicate_field("Raw"));
316 }
317 if self.is_human_readable {
318 let h: &str = map.next_value()?;
319 let off = if h.starts_with("0x") { 2 } else { 0 };
320 let data = hex::decode(&h[off..]).map_err(|e| de::Error::custom(e))?;
321 address = Some(MultiAddress::Raw(data));
322 } else {
323 address = Some(MultiAddress::Raw(map.next_value()?));
324 }
325 }
326 MultiAddressField::Address32 => {
327 if address.is_some() {
328 return Err(de::Error::duplicate_field("Address32"));
329 }
330 if self.is_human_readable {
331 let h: &str = map.next_value()?;
332 let mut data = [0u8; 32];
333 let off = if h.starts_with("0x") { 2 } else { 0 };
334 hex::decode_to_slice(&h[off..], &mut data).map_err(|e| de::Error::custom(e))?;
335 address = Some(MultiAddress::Address32(data));
336 } else {
337 address = Some(MultiAddress::Address32(map.next_value()?));
338 }
339 }
340 MultiAddressField::Address20 => {
341 if address.is_some() {
342 return Err(de::Error::duplicate_field("Address20"));
343 }
344 if self.is_human_readable {
345 let h: &str = map.next_value()?;
346 let mut data = [0u8; 20];
347 let off = if h.starts_with("0x") { 2 } else { 0 };
348 hex::decode_to_slice(&h[off..], &mut data).map_err(|e| de::Error::custom(e))?;
349 address = Some(MultiAddress::Address20(data));
350 } else {
351 address = Some(MultiAddress::Address20(map.next_value()?));
352 }
353 }
354 }
355 }
356 let address =
357 address.ok_or_else(|| de::Error::missing_field("Id, Index, Raw, Address32, or Address20"))?;
358 Ok(address)
359 }
360}
361
362#[cfg(feature = "serde")]
363impl<'de, AccountId, AccountIndex> Deserialize<'de> for MultiAddress<AccountId, AccountIndex>
364where
365 AccountId: AccountTraits,
366 AccountIndex: AccountTraits,
367{
368 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
369 where
370 D: de::Deserializer<'de>,
371 {
372 let visitor = MultiAddressVisitor::new(deserializer.is_human_readable());
373 if deserializer.is_human_readable() {
374 deserializer.deserialize_any(visitor)
375 } else {
376 deserializer.deserialize_enum(
377 "MultiAddress",
378 &["Id", "Index", "Raw", "Address32", "Address20"],
379 visitor,
380 )
381 }
382 }
383}
384
385impl<AccountId: AccountTraits, AccountIndex: AccountTraits> From<&AccountId>
386 for MultiAddress<AccountId, AccountIndex>
387{
388 fn from(other: &AccountId) -> Self {
389 Self::Id(other.clone())
390 }
391}
392
393impl<AccountId: AccountTraits, AccountIndex: AccountTraits> From<AccountId>
394 for MultiAddress<AccountId, AccountIndex>
395{
396 fn from(other: AccountId) -> Self {
397 Self::Id(other)
398 }
399}
400
401impl<AccountIndex: AccountTraits> From<sp_runtime::AccountId32>
402 for MultiAddress<AccountId, AccountIndex>
403{
404 fn from(other: sp_runtime::AccountId32) -> Self {
405 Self::Id(other.into())
406 }
407}
408
409impl<AccountId: AccountTraits, AccountIndex: AccountTraits>
410 From<sp_runtime::MultiAddress<AccountId, AccountIndex>>
411 for MultiAddress<AccountId, AccountIndex>
412{
413 fn from(other: sp_runtime::MultiAddress<AccountId, AccountIndex>) -> Self {
414 match other {
415 sp_runtime::MultiAddress::Id(v) => Self::Id(v),
416 sp_runtime::MultiAddress::Index(v) => Self::Index(v),
417 sp_runtime::MultiAddress::Raw(v) => Self::Raw(v),
418 sp_runtime::MultiAddress::Address32(v) => Self::Address32(v),
419 sp_runtime::MultiAddress::Address20(v) => Self::Address20(v),
420 }
421 }
422}
423
424impl<AccountId: AccountTraits, AccountIndex: AccountTraits>
425 From<&sp_runtime::MultiAddress<AccountId, AccountIndex>>
426 for MultiAddress<AccountId, AccountIndex>
427{
428 fn from(other: &sp_runtime::MultiAddress<AccountId, AccountIndex>) -> Self {
429 Self::from(other.clone())
430 }
431}
432
433#[derive(Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Encode, Decode)]
434#[cfg_attr(all(feature = "std", feature = "type_info"), derive(TypeInfo))]
435pub struct AccountId(pub [u8; 32]);
436
437impl AccountId {
438 pub fn to_hex(&self) -> String {
439 format!("0x{}", hex::encode(&self.0))
440 }
441}
442
443impl FromStr for AccountId {
444 type Err = crate::Error;
445
446 fn from_str(s: &str) -> Result<Self, Self::Err> {
447 match s.len() {
448 66 if s.starts_with("0x") => {
449 let mut id = AccountId::default();
450 hex::decode_to_slice(&s[2..], &mut id.0)?;
451 Ok(id)
452 }
453 64 => {
454 let mut id = AccountId::default();
455 hex::decode_to_slice(&s[0..], &mut id.0)?;
456 Ok(id)
457 }
458 _ => Ok(AccountId::from_ss58check(s)?),
459 }
460 }
461}
462
463#[cfg(not(feature = "serde"))]
464impl AccountId {
465 pub fn to_ss58check(&self) -> String {
466 format!("0x{}", hex::encode(&self.0))
467 }
468}
469
470impl Ss58Codec for AccountId {}
471
472impl fmt::Display for AccountId {
473 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
474 write!(f, "{}", self.to_ss58check())
475 }
476}
477
478impl fmt::Debug for AccountId {
479 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
480 let ss58 = self.to_ss58check();
481 let h = hex::encode(&self.0);
482 write!(f, "0x{} ({}...)", h, &ss58[0..8])
483 }
484}
485
486#[cfg(feature = "serde")]
487impl Serialize for AccountId {
488 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
489 where
490 S: ser::Serializer,
491 {
492 if serializer.is_human_readable() {
493 let ss58 = self.to_ss58check();
494 serializer.serialize_str(&ss58)
495 } else {
496 self.0.serialize(serializer)
497 }
498 }
499}
500
501#[cfg(feature = "serde")]
502impl<'de> Deserialize<'de> for AccountId {
503 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
504 where
505 D: de::Deserializer<'de>,
506 {
507 if deserializer.is_human_readable() {
508 struct StringOrBytesVisitor;
509
510 impl<'de> de::Visitor<'de> for StringOrBytesVisitor {
511 type Value = AccountId;
512
513 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
514 formatter.write_str("a hex string or [u8; 32]")
515 }
516
517 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
518 where
519 E: de::Error,
520 {
521 Ok(AccountId::from_str(s).map_err(|e| de::Error::custom(e))?)
522 }
523
524 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
525 where
526 A: de::SeqAccess<'de>,
527 {
528 let mut id = AccountId::default();
529 for n in 0..32 {
530 id.0[n] = seq
531 .next_element()?
532 .ok_or_else(|| de::Error::invalid_length(n, &self))?;
533 }
534 Ok(id)
535 }
536 }
537 deserializer.deserialize_any(StringOrBytesVisitor)
538 } else {
539 Ok(Self(Deserialize::deserialize(deserializer)?))
540 }
541 }
542}
543
544impl<'a> TryFrom<&'a [u8]> for AccountId {
545 type Error = ();
546
547 fn try_from(x: &'a [u8]) -> Result<Self, ()> {
548 Ok(AccountId(x.try_into().map_err(|_| ())?))
549 }
550}
551
552impl AsMut<[u8; 32]> for AccountId {
553 fn as_mut(&mut self) -> &mut [u8; 32] {
554 &mut self.0
555 }
556}
557
558impl AsMut<[u8]> for AccountId {
559 fn as_mut(&mut self) -> &mut [u8] {
560 &mut self.0[..]
561 }
562}
563
564impl AsRef<[u8; 32]> for AccountId {
565 fn as_ref(&self) -> &[u8; 32] {
566 &self.0
567 }
568}
569
570impl AsRef<[u8]> for AccountId {
571 fn as_ref(&self) -> &[u8] {
572 &self.0[..]
573 }
574}
575
576impl sp_core::ByteArray for AccountId {
577 const LEN: usize = 32;
578}
579
580impl From<[u8; 32]> for AccountId {
581 fn from(p: [u8; 32]) -> Self {
582 Self(p)
583 }
584}
585
586impl From<sp_core::sr25519::Public> for AccountId {
587 fn from(p: sp_core::sr25519::Public) -> Self {
588 p.0.into()
589 }
590}
591
592impl From<sp_core::ed25519::Public> for AccountId {
593 fn from(p: sp_core::ed25519::Public) -> Self {
594 p.0.into()
595 }
596}
597
598impl From<sp_runtime::AccountId32> for AccountId {
599 fn from(id: sp_runtime::AccountId32) -> Self {
600 Self(*id.as_ref())
601 }
602}
603
604impl From<&sp_runtime::AccountId32> for AccountId {
605 fn from(id: &sp_runtime::AccountId32) -> Self {
606 Self(*id.as_ref())
607 }
608}
609
610impl From<AccountId> for sp_runtime::AccountId32 {
611 fn from(id: AccountId) -> Self {
612 Self::new(id.0)
613 }
614}
615
616impl From<&AccountId> for sp_runtime::AccountId32 {
617 fn from(id: &AccountId) -> Self {
618 Self::new(id.0)
619 }
620}
621
622pub type GenericAddress = MultiAddress<AccountId, u32>;
623
624#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Encode, Decode)]
625#[cfg_attr(all(feature = "std", feature = "type_info"), derive(TypeInfo))]
626#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
627pub struct IdentityId(
628 #[cfg_attr(
629 feature = "utoipa",
630 schema(example = "0x0600000000000000000000000000000000000000000000000000000000000000")
631 )]
632 pub [u8; 32],
633);
634
635impl fmt::Display for IdentityId {
636 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
637 let h = hex::encode(&self.0);
638 write!(f, "0x{}", h)
639 }
640}
641
642impl fmt::Debug for IdentityId {
643 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
644 let h = hex::encode(&self.0);
645 write!(f, "0x{}", h)
646 }
647}
648
649#[cfg(feature = "serde")]
650impl Serialize for IdentityId {
651 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
652 where
653 S: ser::Serializer,
654 {
655 if serializer.is_human_readable() {
656 let h = format!("0x{}", hex::encode(&self.0));
657 serializer.serialize_str(&h)
658 } else {
659 self.0.serialize(serializer)
660 }
661 }
662}
663
664#[cfg(feature = "serde")]
665impl<'de> Deserialize<'de> for IdentityId {
666 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
667 where
668 D: de::Deserializer<'de>,
669 {
670 if deserializer.is_human_readable() {
671 struct StringOrBytesVisitor;
672
673 impl<'de> de::Visitor<'de> for StringOrBytesVisitor {
674 type Value = IdentityId;
675
676 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
677 formatter.write_str("a hex string or [u8; 32]")
678 }
679
680 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
681 where
682 E: de::Error,
683 {
684 let mut id = IdentityId::default();
685 let off = if s.starts_with("0x") { 2 } else { 0 };
686 hex::decode_to_slice(&s[off..], &mut id.0).map_err(|e| de::Error::custom(e))?;
687 Ok(id)
688 }
689
690 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
691 where
692 A: de::SeqAccess<'de>,
693 {
694 let mut id = IdentityId::default();
695 for n in 0..32 {
696 id.0[n] = seq
697 .next_element()?
698 .ok_or_else(|| de::Error::invalid_length(n, &self))?;
699 }
700 Ok(id)
701 }
702 }
703 deserializer.deserialize_any(StringOrBytesVisitor)
704 } else {
705 Ok(Self(Deserialize::deserialize(deserializer)?))
706 }
707 }
708}
709
710#[derive(Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Encode, Decode)]
711#[cfg_attr(all(feature = "std", feature = "type_info"), derive(TypeInfo))]
712#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
713pub struct AssetId(
714 #[cfg_attr(
715 feature = "utoipa",
716 schema(example = "67e55044-10b1-426f-9247-bb680e5fe0c8")
717 )]
718 pub [u8; 16],
719);
720
721impl AssetId {
722 pub fn as_uuid(&self) -> uuid::Uuid {
723 uuid::Uuid::from_bytes(self.0)
724 }
725}
726
727impl fmt::Display for AssetId {
728 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
729 self.as_uuid().fmt(f)
730 }
731}
732
733impl fmt::Debug for AssetId {
734 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
735 self.as_uuid().fmt(f)
736 }
737}
738
739impl From<uuid::Uuid> for AssetId {
740 fn from(uuid: uuid::Uuid) -> Self {
741 Self(uuid.into_bytes())
742 }
743}
744
745impl FromStr for AssetId {
746 type Err = uuid::Error;
747
748 fn from_str(uuid_str: &str) -> Result<Self, Self::Err> {
749 let uuid = uuid::Uuid::parse_str(uuid_str)?;
750 Ok(uuid.into())
751 }
752}
753
754impl TryFrom<&'_ str> for AssetId {
755 type Error = uuid::Error;
756
757 fn try_from(uuid_str: &'_ str) -> Result<Self, Self::Error> {
758 let uuid = uuid::Uuid::parse_str(uuid_str)?;
759 Ok(uuid.into())
760 }
761}
762
763#[cfg(feature = "serde")]
764impl Serialize for AssetId {
765 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
766 where
767 S: ser::Serializer,
768 {
769 self.as_uuid().serialize(serializer)
770 }
771}
772
773#[cfg(feature = "serde")]
774impl<'de> Deserialize<'de> for AssetId {
775 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
776 where
777 D: de::Deserializer<'de>,
778 {
779 let uuid: uuid::Uuid = Deserialize::deserialize(deserializer)?;
780 Ok(Self(uuid.into_bytes()))
781 }
782}
783
784#[cfg(test)]
785mod tests {
786 use super::*;
787 use serde_json::json;
788
789 #[test]
790 fn account_id_deserialize() {
791 let json_hex = json!("0x788b804aeea9afcf7042c6ee45ddc2a394f4e225918e3261a9b5ed5069037d09");
792 let json_ss58 = json!("5Enm3VfZioxHVBpZgJcACv7pZPZZeYWymvrZ9cxkXhNHJWe5");
793 let expected = AccountId::from_ss58check("5Enm3VfZioxHVBpZgJcACv7pZPZZeYWymvrZ9cxkXhNHJWe5")
794 .expect("AccountId");
795
796 let decoded: AccountId = serde_json::from_str(&json_hex.to_string()).expect("decode as json");
797 assert_eq!(decoded, expected);
798 let decoded: AccountId = serde_json::from_str(&json_ss58.to_string()).expect("decode as json");
799 assert_eq!(decoded, expected);
800 }
801
802 #[test]
803 fn account_id_roundtrip() {
804 let account = AccountId::from_ss58check("5Enm3VfZioxHVBpZgJcACv7pZPZZeYWymvrZ9cxkXhNHJWe5")
805 .expect("AccountId");
806 let data = serde_json::to_string(&account).expect("encode json");
807 let decoded: AccountId = serde_json::from_str(&data).expect("decode as json");
808 assert_eq!(decoded, account);
809 }
810
811 #[test]
812 fn asset_id_roundtrip() {
813 let asset: AssetId = "67e55044-10b1-426f-9247-bb680e5fe0c8"
814 .parse()
815 .expect("AssetId");
816 let data = serde_json::to_string(&asset).expect("encode json");
817 let decoded: AssetId = serde_json::from_str(&data).expect("decode as json");
818 assert_eq!(decoded, asset);
819 }
820
821 #[test]
822 fn asset_id_display() {
823 let str_id = "67e55044-10b1-426f-9247-bb680e5fe0c8";
824 let asset: AssetId = str_id.parse().expect("AssetId");
825 let display_id = format!("{asset}");
826 assert_eq!(display_id, str_id);
827 }
828
829 #[test]
830 fn multi_address_roundtrip() {
831 let account = AccountId::from_ss58check("5Enm3VfZioxHVBpZgJcACv7pZPZZeYWymvrZ9cxkXhNHJWe5")
832 .expect("AccountId");
833 let address = GenericAddress::Id(account);
835 let data = serde_json::to_string(&address).expect("encode json");
836 eprintln!("MultiAddress::Id = {data}");
837 let decoded: GenericAddress = serde_json::from_str(&data).expect("decode as json");
838 assert_eq!(decoded, address);
839 let address = GenericAddress::Index(1234);
841 let data = serde_json::to_string(&address).expect("encode json");
842 eprintln!("MultiAddress::Index = {data}");
843 let decoded: GenericAddress = serde_json::from_str(&data).expect("decode as json");
844 assert_eq!(decoded, address);
845 let address = GenericAddress::Raw(vec![0, 1, 2, 3, 4, 5]);
847 let data = serde_json::to_string(&address).expect("encode json");
848 eprintln!("MultiAddress::Raw = {data}");
849 let decoded: GenericAddress = serde_json::from_str(&data).expect("decode as json");
850 assert_eq!(decoded, address);
851 let address = GenericAddress::Address32([1; 32]);
853 let data = serde_json::to_string(&address).expect("encode json");
854 eprintln!("MultiAddress::Address32 = {data}");
855 let decoded: GenericAddress = serde_json::from_str(&data).expect("decode as json");
856 assert_eq!(decoded, address);
857 let address = GenericAddress::Address20([2; 20]);
859 let data = serde_json::to_string(&address).expect("encode json");
860 eprintln!("MultiAddress::Address20 = {data}");
861 let decoded: GenericAddress = serde_json::from_str(&data).expect("decode as json");
862 assert_eq!(decoded, address);
863 }
864}