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