1#![cfg_attr(not(feature = "std"), no_std)]
37
38mod cis2_client;
39pub use cis2_client::{Cis2Client, Cis2ClientError};
40
41use concordium_std::{collections::BTreeMap, schema::SchemaType, *};
42pub use concordium_std::MetadataUrl;
44#[cfg(not(feature = "std"))]
45use core::{fmt, ops, str::FromStr};
46#[cfg(feature = "serde")]
47use serde::{Deserialize as SerdeDeserialize, Serialize as SerdeSerialize};
48#[cfg(feature = "std")]
49use std::{fmt, ops, str::FromStr};
50
51use convert::TryFrom;
52
53pub const CIS0_STANDARD_IDENTIFIER: StandardIdentifier<'static> =
55 StandardIdentifier::new_unchecked("CIS-0");
56
57pub const CIS1_STANDARD_IDENTIFIER: StandardIdentifier<'static> =
59 StandardIdentifier::new_unchecked("CIS-1");
60
61pub const CIS2_STANDARD_IDENTIFIER: StandardIdentifier<'static> =
63 StandardIdentifier::new_unchecked("CIS-2");
64
65pub const TRANSFER_EVENT_TAG: u8 = u8::MAX;
67pub const MINT_EVENT_TAG: u8 = u8::MAX - 1;
69pub const BURN_EVENT_TAG: u8 = u8::MAX - 2;
71pub const UPDATE_OPERATOR_EVENT_TAG: u8 = u8::MAX - 3;
73pub const TOKEN_METADATA_EVENT_TAG: u8 = u8::MAX - 4;
75
76pub trait IsTokenId: Serialize + schema::SchemaType {}
86
87pub trait IsTokenAmount: Serialize + schema::SchemaType {}
96
97#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Hash, Clone, Serialize)]
108#[cfg_attr(
109 feature = "serde",
110 derive(SerdeSerialize, SerdeDeserialize),
111 serde(into = "String", try_from = "String")
112)]
113pub struct TokenIdVec(#[concordium(size_length = 1)] pub Vec<u8>);
114
115impl IsTokenId for TokenIdVec {}
116
117impl schema::SchemaType for TokenIdVec {
118 fn get_type() -> schema::Type { schema::Type::ByteList(schema::SizeLength::U8) }
119}
120
121impl fmt::Display for TokenIdVec {
123 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
124 for byte in &self.0 {
125 write!(f, "{:02X}", byte)?;
126 }
127 Ok(())
128 }
129}
130
131#[cfg(feature = "serde")]
132impl From<TokenIdVec> for String {
133 fn from(id: TokenIdVec) -> Self { id.to_string() }
134}
135
136#[cfg(feature = "serde")]
137impl TryFrom<String> for TokenIdVec {
138 type Error = ParseError;
139
140 fn try_from(s: String) -> Result<Self, Self::Error> { s.parse() }
141}
142
143impl FromStr for TokenIdVec {
145 type Err = ParseError;
146
147 fn from_str(s: &str) -> Result<Self, Self::Err> {
148 if s.len() % 2 != 0 || !s.is_ascii() {
149 return Err(ParseError {});
150 }
151
152 let mut id = Vec::with_capacity(s.len() / 2);
153 for i in (0..s.len()).step_by(2) {
154 let byte = u8::from_str_radix(&s[i..i + 2], 16).map_err(|_| ParseError {})?;
155 id.push(byte);
156 }
157
158 Ok(Self(id))
159 }
160}
161
162#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Hash, Copy, Clone)]
175#[cfg_attr(
176 feature = "serde",
177 derive(SerdeSerialize, SerdeDeserialize),
178 serde(into = "String", try_from = "String")
179)]
180pub struct TokenIdFixed<const N: usize>(pub [u8; N]);
181
182impl<const N: usize> IsTokenId for TokenIdFixed<N> {}
183
184impl<const N: usize> schema::SchemaType for TokenIdFixed<N> {
185 fn get_type() -> schema::Type { schema::Type::ByteList(schema::SizeLength::U8) }
186}
187
188impl<const N: usize> From<[u8; N]> for TokenIdFixed<N> {
189 fn from(id: [u8; N]) -> Self { TokenIdFixed(id) }
190}
191
192impl<const N: usize> Serial for TokenIdFixed<N> {
195 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
196 let len = u8::try_from(N).map_err(|_| W::Err::default())?;
197 out.write_u8(len)?;
198 out.write_all(&self.0)?;
199 Ok(())
200 }
201}
202
203impl<const N: usize> Deserial for TokenIdFixed<N> {
207 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
208 let byte_length = source.read_u8()?;
209 if usize::from(byte_length) != N {
210 return Err(ParseError::default());
211 }
212 let bytes: [u8; N] = source.get()?;
213 Ok(TokenIdFixed(bytes))
214 }
215}
216
217impl<const N: usize> fmt::Display for TokenIdFixed<N> {
219 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
220 for byte in &self.0 {
221 write!(f, "{:02X}", byte)?;
222 }
223 Ok(())
224 }
225}
226
227#[cfg(feature = "serde")]
228impl<const N: usize> From<TokenIdFixed<N>> for String {
229 fn from(id: TokenIdFixed<N>) -> Self { id.to_string() }
230}
231
232#[cfg(feature = "serde")]
233impl<const N: usize> TryFrom<String> for TokenIdFixed<N> {
234 type Error = ParseError;
235
236 fn try_from(s: String) -> Result<Self, Self::Error> { s.parse() }
237}
238
239impl<const N: usize> FromStr for TokenIdFixed<N> {
241 type Err = ParseError;
242
243 fn from_str(s: &str) -> Result<Self, Self::Err> { parse_bytes_exact(s).map(Self) }
244}
245
246#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Hash, Copy, Clone)]
257#[cfg_attr(
258 feature = "serde",
259 derive(SerdeSerialize, SerdeDeserialize),
260 serde(into = "String", try_from = "String")
261)]
262pub struct TokenIdU64(pub u64);
263
264impl IsTokenId for TokenIdU64 {}
265
266impl schema::SchemaType for TokenIdU64 {
267 fn get_type() -> schema::Type { schema::Type::ByteList(schema::SizeLength::U8) }
268}
269
270impl From<u64> for TokenIdU64 {
271 fn from(id: u64) -> Self { TokenIdU64(id) }
272}
273
274impl Serial for TokenIdU64 {
277 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
278 out.write_u8(8)?;
279 out.write_u64(self.0)
280 }
281}
282
283impl Deserial for TokenIdU64 {
287 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
288 let byte_length = source.read_u8()?;
289 if byte_length == 8 {
290 Ok(TokenIdU64(source.read_u64()?))
291 } else {
292 Err(ParseError::default())
293 }
294 }
295}
296
297impl fmt::Display for TokenIdU64 {
299 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
300 for byte in &self.0.to_le_bytes() {
301 write!(f, "{:02X}", byte)?;
302 }
303 Ok(())
304 }
305}
306
307#[cfg(feature = "serde")]
308impl From<TokenIdU64> for String {
309 fn from(id: TokenIdU64) -> Self { id.to_string() }
310}
311
312#[cfg(feature = "serde")]
313impl TryFrom<String> for TokenIdU64 {
314 type Error = ParseError;
315
316 fn try_from(s: String) -> Result<Self, Self::Error> { s.parse() }
317}
318
319impl FromStr for TokenIdU64 {
321 type Err = ParseError;
322
323 fn from_str(s: &str) -> Result<Self, Self::Err> {
324 let bytes = parse_bytes_exact(s)?;
325 Ok(Self(u64::from_le_bytes(bytes)))
326 }
327}
328
329#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Hash, Copy, Clone)]
340#[cfg_attr(
341 feature = "serde",
342 derive(SerdeSerialize, SerdeDeserialize),
343 serde(into = "String", try_from = "String")
344)]
345pub struct TokenIdU32(pub u32);
346
347impl IsTokenId for TokenIdU32 {}
348
349impl schema::SchemaType for TokenIdU32 {
350 fn get_type() -> schema::Type { schema::Type::ByteList(schema::SizeLength::U8) }
351}
352
353impl From<u32> for TokenIdU32 {
354 fn from(id: u32) -> Self { TokenIdU32(id) }
355}
356
357impl Serial for TokenIdU32 {
360 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
361 out.write_u8(4)?;
362 out.write_u32(self.0)
363 }
364}
365
366impl Deserial for TokenIdU32 {
370 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
371 let byte_length = source.read_u8()?;
372 if byte_length == 4 {
373 Ok(TokenIdU32(source.read_u32()?))
374 } else {
375 Err(ParseError::default())
376 }
377 }
378}
379
380impl fmt::Display for TokenIdU32 {
382 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
383 for byte in &self.0.to_le_bytes() {
384 write!(f, "{:02X}", byte)?;
385 }
386 Ok(())
387 }
388}
389
390#[cfg(feature = "serde")]
391impl From<TokenIdU32> for String {
392 fn from(id: TokenIdU32) -> Self { id.to_string() }
393}
394
395#[cfg(feature = "serde")]
396impl TryFrom<String> for TokenIdU32 {
397 type Error = ParseError;
398
399 fn try_from(s: String) -> Result<Self, Self::Error> { s.parse() }
400}
401
402impl FromStr for TokenIdU32 {
404 type Err = ParseError;
405
406 fn from_str(s: &str) -> Result<Self, Self::Err> {
407 let bytes = parse_bytes_exact(s)?;
408 Ok(Self(u32::from_le_bytes(bytes)))
409 }
410}
411
412#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Hash, Copy, Clone)]
423#[cfg_attr(
424 feature = "serde",
425 derive(SerdeSerialize, SerdeDeserialize),
426 serde(into = "String", try_from = "String")
427)]
428pub struct TokenIdU16(pub u16);
429
430impl IsTokenId for TokenIdU16 {}
431
432impl schema::SchemaType for TokenIdU16 {
433 fn get_type() -> schema::Type { schema::Type::ByteList(schema::SizeLength::U8) }
434}
435
436impl From<u16> for TokenIdU16 {
437 fn from(id: u16) -> Self { TokenIdU16(id) }
438}
439
440impl Serial for TokenIdU16 {
443 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
444 out.write_u8(2)?;
445 out.write_u16(self.0)
446 }
447}
448
449impl Deserial for TokenIdU16 {
453 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
454 let byte_length = source.read_u8()?;
455 if byte_length == 2 {
456 Ok(TokenIdU16(source.read_u16()?))
457 } else {
458 Err(ParseError::default())
459 }
460 }
461}
462
463impl fmt::Display for TokenIdU16 {
465 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
466 for byte in &self.0.to_le_bytes() {
467 write!(f, "{:02X}", byte)?;
468 }
469 Ok(())
470 }
471}
472
473#[cfg(feature = "serde")]
474impl From<TokenIdU16> for String {
475 fn from(id: TokenIdU16) -> Self { id.to_string() }
476}
477
478#[cfg(feature = "serde")]
479impl TryFrom<String> for TokenIdU16 {
480 type Error = ParseError;
481
482 fn try_from(s: String) -> Result<Self, Self::Error> { s.parse() }
483}
484
485impl FromStr for TokenIdU16 {
487 type Err = ParseError;
488
489 fn from_str(s: &str) -> Result<Self, Self::Err> {
490 let bytes = parse_bytes_exact(s)?;
491 Ok(Self(u16::from_le_bytes(bytes)))
492 }
493}
494
495#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Hash, Copy, Clone)]
506#[cfg_attr(
507 feature = "serde",
508 derive(SerdeSerialize, SerdeDeserialize),
509 serde(into = "String", try_from = "String")
510)]
511pub struct TokenIdU8(pub u8);
512
513impl IsTokenId for TokenIdU8 {}
514
515impl schema::SchemaType for TokenIdU8 {
516 fn get_type() -> schema::Type { schema::Type::ByteList(schema::SizeLength::U8) }
517}
518
519impl From<u8> for TokenIdU8 {
520 fn from(id: u8) -> Self { TokenIdU8(id) }
521}
522
523impl Serial for TokenIdU8 {
526 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
527 out.write_u8(1)?;
528 out.write_u8(self.0)
529 }
530}
531
532impl Deserial for TokenIdU8 {
536 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
537 let byte_length = source.read_u8()?;
538 if byte_length == 1 {
539 Ok(TokenIdU8(source.read_u8()?))
540 } else {
541 Err(ParseError::default())
542 }
543 }
544}
545
546impl fmt::Display for TokenIdU8 {
548 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
549 for byte in &self.0.to_le_bytes() {
550 write!(f, "{:02X}", byte)?;
551 }
552 Ok(())
553 }
554}
555
556#[cfg(feature = "serde")]
557impl From<TokenIdU8> for String {
558 fn from(id: TokenIdU8) -> Self { id.to_string() }
559}
560
561#[cfg(feature = "serde")]
562impl TryFrom<String> for TokenIdU8 {
563 type Error = ParseError;
564
565 fn try_from(s: String) -> Result<Self, Self::Error> { s.parse() }
566}
567
568impl FromStr for TokenIdU8 {
570 type Err = ParseError;
571
572 fn from_str(s: &str) -> Result<Self, Self::Err> {
573 let bytes = parse_bytes_exact::<1>(s)?;
574 Ok(Self(bytes[0]))
575 }
576}
577
578fn parse_bytes_exact<const N: usize>(s: &str) -> Result<[u8; N], ParseError> {
580 if s.len() != 2 * N || !s.is_ascii() {
581 return Err(ParseError {});
582 }
583
584 let mut bytes = [0; N];
585 for (i, place) in bytes.iter_mut().enumerate() {
586 *place = u8::from_str_radix(&s[(2 * i)..(2 * i + 2)], 16).map_err(|_| ParseError {})?;
587 }
588
589 Ok(bytes)
590}
591
592#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Hash, Copy, Clone)]
603#[cfg_attr(
604 feature = "serde",
605 derive(SerdeSerialize, SerdeDeserialize),
606 serde(into = "String", try_from = "String")
607)]
608pub struct TokenIdUnit();
609
610impl IsTokenId for TokenIdUnit {}
611
612impl schema::SchemaType for TokenIdUnit {
613 fn get_type() -> schema::Type { schema::Type::ByteList(schema::SizeLength::U8) }
614}
615
616impl Serial for TokenIdUnit {
618 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> { out.write_u8(0) }
619}
620
621impl Deserial for TokenIdUnit {
624 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
625 let byte_length = source.read_u8()?;
626 if byte_length == 0 {
627 Ok(TokenIdUnit())
628 } else {
629 Err(ParseError::default())
630 }
631 }
632}
633
634#[cfg(feature = "serde")]
635impl From<TokenIdUnit> for String {
636 fn from(_id: TokenIdUnit) -> Self { String::from("") }
637}
638
639#[cfg(feature = "serde")]
640impl TryFrom<String> for TokenIdUnit {
641 type Error = ParseError;
642
643 fn try_from(s: String) -> Result<Self, Self::Error> {
644 if s == "" {
645 Ok(Self())
646 } else {
647 Err(ParseError {})
648 }
649 }
650}
651
652macro_rules! token_amount_wrapper {
653 ($name:ident, $wrapped:ty) => {
654 #[derive(Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Default)]
655 #[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
656 #[repr(transparent)]
657 pub struct $name(pub $wrapped);
658
659 impl ops::Add<Self> for $name {
660 type Output = Self;
661
662 fn add(self, rhs: Self) -> Self::Output { $name(self.0 + rhs.0) }
663 }
664
665 impl ops::AddAssign for $name {
666 fn add_assign(&mut self, other: Self) { *self = *self + other; }
667 }
668
669 impl ops::Sub<Self> for $name {
670 type Output = Self;
671
672 fn sub(self, rhs: Self) -> Self::Output { $name(self.0 - rhs.0) }
673 }
674
675 impl ops::SubAssign for $name {
676 fn sub_assign(&mut self, other: Self) { *self = *self - other; }
677 }
678
679 impl ops::Mul<$wrapped> for $name {
680 type Output = Self;
681
682 fn mul(self, rhs: $wrapped) -> Self::Output { $name(self.0 * rhs) }
683 }
684
685 impl ops::Mul<$name> for $wrapped {
686 type Output = $name;
687
688 fn mul(self, rhs: $name) -> Self::Output { $name(self * rhs.0) }
689 }
690
691 impl ops::MulAssign<$wrapped> for $name {
692 fn mul_assign(&mut self, other: $wrapped) { *self = *self * other; }
693 }
694
695 impl ops::Rem<$wrapped> for $name {
696 type Output = Self;
697
698 fn rem(self, other: $wrapped) -> Self::Output { $name(self.0 % other) }
699 }
700
701 impl ops::RemAssign<$wrapped> for $name {
702 fn rem_assign(&mut self, other: $wrapped) { *self = *self % other; }
703 }
704
705 impl iter::Sum for $name {
706 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self { iter.fold($name(0), ops::Add::add) }
707 }
708
709 impl IsTokenAmount for $name {}
710
711 impl schema::SchemaType for $name {
714 fn get_type() -> schema::Type { schema::Type::ULeb128(37) }
715 }
716
717 impl Serial for $name {
718 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
719 let mut value = self.0;
720 loop {
721 let mut byte = (value as u8) & 0b0111_1111;
722 value >>= 7;
723 if value != 0 {
724 byte |= 0b1000_0000;
725 }
726 out.write_u8(byte)?;
727
728 if value == 0 {
729 return Ok(());
730 }
731 }
732 }
733 }
734
735 impl Deserial for $name {
736 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
737 let mut result: $wrapped = 0;
738 for i in 0..37 {
739 let byte = source.read_u8()?;
740 let value_byte = (byte & 0b0111_1111) as $wrapped;
741 result = result.checked_add(value_byte << (i * 7)).ok_or(ParseError {})?;
742
743 if byte & 0b1000_0000 == 0 {
744 return Ok($name(result));
745 }
746 }
747 Err(ParseError {})
748 }
749 }
750
751 impl From<$wrapped> for $name {
752 fn from(v: $wrapped) -> $name { $name(v) }
753 }
754
755 impl From<$name> for $wrapped {
756 fn from(v: $name) -> $wrapped { v.0 }
757 }
758 };
759}
760
761token_amount_wrapper!(TokenAmountU128, u128);
762token_amount_wrapper!(TokenAmountU64, u64);
763token_amount_wrapper!(TokenAmountU32, u32);
764token_amount_wrapper!(TokenAmountU16, u16);
765token_amount_wrapper!(TokenAmountU8, u8);
766
767#[cfg(feature = "u256_amount")]
768mod u256_token {
769 use super::*;
770 use primitive_types::U256;
771 #[derive(Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Default)]
772 #[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
773 #[cfg_attr(docsrs, cfg(feature = "u256_amount"))]
774 #[repr(transparent)]
775 pub struct TokenAmountU256(pub U256);
776
777 impl ops::Add<Self> for TokenAmountU256 {
778 type Output = Self;
779
780 fn add(self, rhs: Self) -> Self::Output { TokenAmountU256(self.0 + rhs.0) }
781 }
782
783 impl ops::AddAssign for TokenAmountU256 {
784 fn add_assign(&mut self, other: Self) { *self = *self + other; }
785 }
786
787 impl ops::Sub<Self> for TokenAmountU256 {
788 type Output = Self;
789
790 fn sub(self, rhs: Self) -> Self::Output { TokenAmountU256(self.0 - rhs.0) }
791 }
792
793 impl ops::SubAssign for TokenAmountU256 {
794 fn sub_assign(&mut self, other: Self) { *self = *self - other; }
795 }
796
797 impl ops::Mul<U256> for TokenAmountU256 {
798 type Output = Self;
799
800 fn mul(self, rhs: U256) -> Self::Output { TokenAmountU256(self.0 * rhs) }
801 }
802
803 impl ops::Mul<TokenAmountU256> for U256 {
804 type Output = TokenAmountU256;
805
806 fn mul(self, rhs: TokenAmountU256) -> Self::Output { TokenAmountU256(self * rhs.0) }
807 }
808
809 impl ops::MulAssign<U256> for TokenAmountU256 {
810 fn mul_assign(&mut self, other: U256) { *self = *self * other; }
811 }
812
813 impl ops::Rem<U256> for TokenAmountU256 {
814 type Output = Self;
815
816 fn rem(self, other: U256) -> Self::Output { TokenAmountU256(self.0 % other) }
817 }
818
819 impl ops::RemAssign<U256> for TokenAmountU256 {
820 fn rem_assign(&mut self, other: U256) { *self = *self % other; }
821 }
822
823 impl iter::Sum for TokenAmountU256 {
824 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
825 iter.fold(TokenAmountU256(U256::zero()), ops::Add::add)
826 }
827 }
828
829 impl IsTokenAmount for TokenAmountU256 {}
830
831 impl schema::SchemaType for TokenAmountU256 {
834 fn get_type() -> schema::Type { schema::Type::ULeb128(37) }
835 }
836
837 impl Serial for TokenAmountU256 {
838 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
839 let mut value = self.0;
840 loop {
841 let mut byte = (value.low_u32() as u8) & 0b0111_1111;
842 value >>= 7;
843 if value != U256::zero() {
844 byte |= 0b1000_0000;
845 }
846 out.write_u8(byte)?;
847
848 if value.is_zero() {
849 return Ok(());
850 }
851 }
852 }
853 }
854
855 impl Deserial for TokenAmountU256 {
856 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
857 let mut result: U256 = U256::zero();
858 for i in 0..36 {
859 let byte = source.read_u8()?;
860 let value_byte = <U256>::from(byte & 0b0111_1111);
861 result = result.checked_add(value_byte << (i * 7)).ok_or(ParseError {})?;
862 if byte & 0b1000_0000 == 0 {
863 return Ok(TokenAmountU256(result));
864 }
865 }
866 let byte = source.read_u8()?;
867 let value_byte = byte & 0b0111_1111;
868 if value_byte & 0b1111_0000 != 0 {
869 Err(ParseError {})
870 } else {
871 let value_byte = <U256>::from(value_byte);
872 result = result.checked_add(value_byte << (36 * 7)).ok_or(ParseError {})?;
873 if byte & 0b1000_0000 == 0 {
874 Ok(TokenAmountU256(result))
875 } else {
876 Err(ParseError {})
877 }
878 }
879 }
880 }
881
882 impl From<U256> for TokenAmountU256 {
883 fn from(v: U256) -> TokenAmountU256 { TokenAmountU256(v) }
884 }
885
886 impl From<TokenAmountU256> for U256 {
887 fn from(v: TokenAmountU256) -> U256 { v.0 }
888 }
889
890 #[cfg(test)]
891 mod tests {
892 use super::*;
893 #[test]
894 fn serial_token_amount256_max_test() {
895 let v = TokenAmountU256(U256([u64::MAX; 4]));
896 let bytes = to_bytes(&v);
897 assert_eq!(Ok(v), from_bytes(&bytes));
898 }
899 #[test]
900 fn serial_token_amount256_0_test() {
901 let v = TokenAmountU256(U256([0; 4]));
902 let bytes = to_bytes(&v);
903 assert_eq!(Ok(v), from_bytes(&bytes));
904 }
905 #[test]
906 fn serial_token_amount_test() {
907 let v = TokenAmountU256(U256([u64::MAX, 1, 1, 1]));
908 let bytes = to_bytes(&v);
909 assert_eq!(Ok(v), from_bytes(&bytes));
910 }
911 #[test]
912 fn serial_token_amount_invalid() {
913 let mut max = to_bytes(&TokenAmountU256(U256([u64::MAX; 4])));
915 max[36] |= 0b1000_0000;
916 max.push(0b0000_1111);
917 assert_eq!(Err(ParseError {}), from_bytes::<TokenAmountU256>(&max));
918 }
919 }
920}
921
922#[cfg(feature = "u256_amount")]
923pub use u256_token::*;
924
925#[derive(Debug, Serialize, SchemaType, PartialEq, Eq)]
930pub struct TransferEvent<T: IsTokenId, A: IsTokenAmount> {
931 pub token_id: T,
933 pub amount: A,
935 pub from: Address,
937 pub to: Address,
939}
940
941#[derive(Debug, Serialize, SchemaType, PartialEq, Eq)]
947pub struct MintEvent<T: IsTokenId, A: IsTokenAmount> {
948 pub token_id: T,
950 pub amount: A,
952 pub owner: Address,
954}
955
956#[derive(Debug, Serialize, SchemaType, PartialEq, Eq)]
961pub struct BurnEvent<T: IsTokenId, A: IsTokenAmount> {
962 pub token_id: T,
964 pub amount: A,
966 pub owner: Address,
968}
969
970#[derive(Debug, Serialize, SchemaType, PartialEq, Eq)]
975pub struct UpdateOperatorEvent {
976 pub update: OperatorUpdate,
978 pub owner: Address,
980 pub operator: Address,
982}
983
984#[derive(Debug, Serialize, SchemaType, PartialEq, Eq)]
989pub struct TokenMetadataEvent<T: IsTokenId> {
990 pub token_id: T,
992 pub metadata_url: MetadataUrl,
994}
995
996#[derive(Debug, Serialize, PartialEq, Eq)]
998#[concordium(repr(u8))]
999pub enum Cis2Event<T: IsTokenId, A: IsTokenAmount> {
1000 #[concordium(tag = 255)]
1002 Transfer(TransferEvent<T, A>),
1003 #[concordium(tag = 254)]
1006 Mint(MintEvent<T, A>),
1007 #[concordium(tag = 253)]
1009 Burn(BurnEvent<T, A>),
1010 #[concordium(tag = 252)]
1012 UpdateOperator(UpdateOperatorEvent),
1013 #[concordium(tag = 251)]
1015 TokenMetadata(TokenMetadataEvent<T>),
1016}
1017
1018impl<T: IsTokenId, A: IsTokenAmount> schema::SchemaType for Cis2Event<T, A> {
1021 fn get_type() -> schema::Type {
1022 let mut event_map = BTreeMap::new();
1023 event_map.insert(
1024 TRANSFER_EVENT_TAG,
1025 (
1026 "Transfer".to_string(),
1027 schema::Fields::Named(vec![
1028 (String::from("token_id"), T::get_type()),
1029 (String::from("amount"), A::get_type()),
1030 (String::from("from"), Address::get_type()),
1031 (String::from("to"), Address::get_type()),
1032 ]),
1033 ),
1034 );
1035 event_map.insert(
1036 MINT_EVENT_TAG,
1037 (
1038 "Mint".to_string(),
1039 schema::Fields::Named(vec![
1040 (String::from("token_id"), T::get_type()),
1041 (String::from("amount"), A::get_type()),
1042 (String::from("owner"), Address::get_type()),
1043 ]),
1044 ),
1045 );
1046 event_map.insert(
1047 BURN_EVENT_TAG,
1048 (
1049 "Burn".to_string(),
1050 schema::Fields::Named(vec![
1051 (String::from("token_id"), T::get_type()),
1052 (String::from("amount"), A::get_type()),
1053 (String::from("owner"), Address::get_type()),
1054 ]),
1055 ),
1056 );
1057 event_map.insert(
1058 UPDATE_OPERATOR_EVENT_TAG,
1059 (
1060 "UpdateOperator".to_string(),
1061 schema::Fields::Named(vec![
1062 (String::from("update"), OperatorUpdate::get_type()),
1063 (String::from("owner"), Address::get_type()),
1064 (String::from("operator"), Address::get_type()),
1065 ]),
1066 ),
1067 );
1068 event_map.insert(
1069 TOKEN_METADATA_EVENT_TAG,
1070 (
1071 "TokenMetadata".to_string(),
1072 schema::Fields::Named(vec![
1073 (String::from("token_id"), T::get_type()),
1074 (String::from("metadata_url"), MetadataUrl::get_type()),
1075 ]),
1076 ),
1077 );
1078 schema::Type::TaggedEnum(event_map)
1079 }
1080}
1081
1082#[derive(Debug, PartialEq, Eq, SchemaType, Serial, Deserial)]
1084pub enum Cis2Error<R> {
1085 InvalidTokenId,
1087 InsufficientFunds,
1090 Unauthorized,
1092 Custom(R),
1094}
1095
1096impl<R: Into<Reject> + Serial> From<Cis2Error<R>> for Reject {
1104 fn from(err: Cis2Error<R>) -> Self {
1105 let return_value = Some(to_bytes(&err));
1106 let error_code = match err {
1107 Cis2Error::InvalidTokenId => unsafe {
1108 crate::num::NonZeroI32::new_unchecked(-42000001)
1109 },
1110 Cis2Error::InsufficientFunds => unsafe {
1111 crate::num::NonZeroI32::new_unchecked(-42000002)
1112 },
1113 Cis2Error::Unauthorized => unsafe { crate::num::NonZeroI32::new_unchecked(-42000003) },
1114 Cis2Error::Custom(reject) => reject.into().error_code,
1115 };
1116 Self {
1117 error_code,
1118 return_value,
1119 }
1120 }
1121}
1122
1123impl<X> From<LogError> for Cis2Error<X>
1124where
1125 X: From<LogError>,
1126{
1127 #[inline]
1128 fn from(err: LogError) -> Self { Cis2Error::Custom(X::from(err)) }
1130}
1131
1132impl<X> From<ParseError> for Cis2Error<X>
1133where
1134 X: From<ParseError>,
1135{
1136 #[inline]
1137 fn from(err: ParseError) -> Self { Cis2Error::Custom(X::from(err)) }
1139}
1140
1141impl<T, X> From<CallContractError<T>> for Cis2Error<X>
1142where
1143 X: From<CallContractError<T>>,
1144{
1145 #[inline]
1146 fn from(err: CallContractError<T>) -> Self { Cis2Error::Custom(X::from(err)) }
1148}
1149
1150impl<X> From<TransferError> for Cis2Error<X>
1151where
1152 X: From<TransferError>,
1153{
1154 #[inline]
1155 fn from(err: TransferError) -> Self { Cis2Error::Custom(X::from(err)) }
1157}
1158
1159impl<X> From<UpgradeError> for Cis2Error<X>
1160where
1161 X: From<UpgradeError>,
1162{
1163 #[inline]
1164 fn from(err: UpgradeError) -> Self { Cis2Error::Custom(X::from(err)) }
1166}
1167
1168impl<X> From<QueryAccountBalanceError> for Cis2Error<X>
1169where
1170 X: From<QueryAccountBalanceError>,
1171{
1172 #[inline]
1173 fn from(err: QueryAccountBalanceError) -> Self { Cis2Error::Custom(X::from(err)) }
1175}
1176
1177impl<X> From<QueryContractBalanceError> for Cis2Error<X>
1178where
1179 X: From<QueryContractBalanceError>,
1180{
1181 #[inline]
1182 fn from(err: QueryContractBalanceError) -> Self { Cis2Error::Custom(X::from(err)) }
1184}
1185
1186impl<X> From<NewReceiveNameError> for Cis2Error<X>
1187where
1188 X: From<NewReceiveNameError>,
1189{
1190 #[inline]
1191 fn from(err: NewReceiveNameError) -> Self { Cis2Error::Custom(X::from(err)) }
1193}
1194
1195impl<X> From<CheckAccountSignatureError> for Cis2Error<X>
1196where
1197 X: From<CheckAccountSignatureError>,
1198{
1199 #[inline]
1200 fn from(err: CheckAccountSignatureError) -> Self { Cis2Error::Custom(X::from(err)) }
1202}
1203
1204impl<X> From<QueryAccountPublicKeysError> for Cis2Error<X>
1205where
1206 X: From<QueryAccountPublicKeysError>,
1207{
1208 #[inline]
1209 fn from(err: QueryAccountPublicKeysError) -> Self { Cis2Error::Custom(X::from(err)) }
1211}
1212
1213impl<X> From<NewContractNameError> for Cis2Error<X>
1214where
1215 X: From<NewContractNameError>,
1216{
1217 #[inline]
1218 fn from(err: NewContractNameError) -> Self { Cis2Error::Custom(X::from(err)) }
1220}
1221
1222#[derive(Debug, Serialize, Clone, SchemaType)]
1228#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
1229pub enum Receiver {
1230 Account(
1232 AccountAddress,
1234 ),
1235 Contract(
1237 ContractAddress,
1239 OwnedEntrypointName,
1241 ),
1242}
1243
1244impl Receiver {
1245 pub fn from_account(address: AccountAddress) -> Self { Receiver::Account(address) }
1247
1248 pub fn from_contract(address: ContractAddress, function: OwnedEntrypointName) -> Self {
1250 Receiver::Contract(address, function)
1251 }
1252
1253 pub fn address(&self) -> Address {
1255 match self {
1256 Receiver::Account(address) => Address::Account(*address),
1257 Receiver::Contract(address, ..) => Address::Contract(*address),
1258 }
1259 }
1260}
1261
1262impl From<AccountAddress> for Receiver {
1263 fn from(address: AccountAddress) -> Self { Self::from_account(address) }
1264}
1265
1266#[derive(Debug, Serialize, Clone)]
1268#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
1269#[concordium(transparent)]
1270pub struct AdditionalData(#[concordium(size_length = 2)] Vec<u8>);
1271
1272impl schema::SchemaType for AdditionalData {
1274 fn get_type() -> schema::Type { schema::Type::ByteList(schema::SizeLength::U16) }
1275}
1276
1277impl AdditionalData {
1278 pub fn empty() -> Self { AdditionalData(Vec::new()) }
1280}
1281
1282impl From<Vec<u8>> for AdditionalData {
1283 fn from(data: Vec<u8>) -> Self { AdditionalData(data) }
1284}
1285
1286impl AsRef<[u8]> for AdditionalData {
1287 fn as_ref(&self) -> &[u8] { &self.0 }
1288}
1289
1290#[derive(Debug, Serialize, Clone, SchemaType)]
1294#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
1295pub struct Transfer<T: IsTokenId, A: IsTokenAmount> {
1296 pub token_id: T,
1298 pub amount: A,
1300 pub from: Address,
1302 pub to: Receiver,
1304 pub data: AdditionalData,
1307}
1308
1309#[derive(Debug, Serialize, Clone, SchemaType)]
1311#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
1312#[concordium(transparent)]
1313pub struct TransferParams<T: IsTokenId, A: IsTokenAmount>(
1314 #[concordium(size_length = 2)] pub Vec<Transfer<T, A>>,
1315);
1316
1317impl<T: IsTokenId, A: IsTokenAmount> From<Vec<Transfer<T, A>>> for TransferParams<T, A> {
1318 fn from(transfers: Vec<Transfer<T, A>>) -> Self { TransferParams(transfers) }
1319}
1320
1321impl<T: IsTokenId, A: IsTokenAmount> AsRef<[Transfer<T, A>]> for TransferParams<T, A> {
1322 fn as_ref(&self) -> &[Transfer<T, A>] { &self.0 }
1323}
1324
1325#[derive(Debug, Serialize, Clone, Copy, SchemaType, PartialEq, Eq)]
1329#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
1330pub enum OperatorUpdate {
1331 Remove,
1333 Add,
1335}
1336
1337#[derive(Debug, Serialize, Clone, SchemaType, PartialEq, Eq)]
1341#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
1342pub struct UpdateOperator {
1343 pub update: OperatorUpdate,
1345 pub operator: Address,
1349}
1350
1351#[derive(Debug, Serialize, Clone, SchemaType)]
1353#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
1354#[concordium(transparent)]
1355pub struct UpdateOperatorParams(#[concordium(size_length = 2)] pub Vec<UpdateOperator>);
1356
1357#[derive(Debug, Serialize, SchemaType)]
1361pub struct BalanceOfQuery<T: IsTokenId> {
1362 pub token_id: T,
1364 pub address: Address,
1366}
1367
1368#[derive(Debug, Serialize, SchemaType)]
1372#[concordium(transparent)]
1373pub struct BalanceOfQueryParams<T: IsTokenId> {
1374 #[concordium(size_length = 2)]
1376 pub queries: Vec<BalanceOfQuery<T>>,
1377}
1378
1379#[derive(Debug, Serialize, SchemaType, PartialEq, Eq)]
1383#[concordium(transparent)]
1384pub struct BalanceOfQueryResponse<A: IsTokenAmount>(#[concordium(size_length = 2)] pub Vec<A>);
1385
1386impl<A: IsTokenAmount> From<Vec<A>> for BalanceOfQueryResponse<A> {
1387 fn from(results: Vec<A>) -> Self { BalanceOfQueryResponse(results) }
1388}
1389
1390impl<A: IsTokenAmount> AsRef<[A]> for BalanceOfQueryResponse<A> {
1391 fn as_ref(&self) -> &[A] { &self.0 }
1392}
1393
1394#[derive(Debug, Serialize, SchemaType)]
1398pub struct OperatorOfQuery {
1399 pub owner: Address,
1401 pub address: Address,
1403}
1404
1405#[derive(Debug, Serialize, SchemaType)]
1407#[concordium(transparent)]
1408pub struct OperatorOfQueryParams {
1409 #[concordium(size_length = 2)]
1411 pub queries: Vec<OperatorOfQuery>,
1412}
1413
1414#[derive(Debug, Serialize, SchemaType, PartialEq, Eq)]
1419#[concordium(transparent)]
1420pub struct OperatorOfQueryResponse(#[concordium(size_length = 2)] pub Vec<bool>);
1421
1422impl From<Vec<bool>> for OperatorOfQueryResponse {
1423 fn from(results: Vec<bool>) -> Self { OperatorOfQueryResponse(results) }
1424}
1425
1426impl AsRef<[bool]> for OperatorOfQueryResponse {
1427 fn as_ref(&self) -> &[bool] { &self.0 }
1428}
1429
1430#[derive(Debug, Serialize, SchemaType)]
1434#[concordium(transparent)]
1435pub struct TokenMetadataQueryParams<T: IsTokenId> {
1436 #[concordium(size_length = 2)]
1438 pub queries: Vec<T>,
1439}
1440
1441#[derive(Debug, Serialize, SchemaType)]
1445#[concordium(transparent)]
1446pub struct TokenMetadataQueryResponse(#[concordium(size_length = 2)] pub Vec<MetadataUrl>);
1447
1448impl From<Vec<MetadataUrl>> for TokenMetadataQueryResponse {
1449 fn from(results: Vec<MetadataUrl>) -> Self { TokenMetadataQueryResponse(results) }
1450}
1451
1452impl AsRef<[MetadataUrl]> for TokenMetadataQueryResponse {
1453 fn as_ref(&self) -> &[MetadataUrl] { &self.0 }
1454}
1455
1456#[derive(Debug, Serialize, SchemaType)]
1460#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
1461pub struct OnReceivingCis2Params<T, A> {
1462 pub token_id: T,
1464 pub amount: A,
1466 pub from: Address,
1468 pub data: AdditionalData,
1470}
1471
1472#[derive(Debug)]
1477#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
1478pub struct OnReceivingCis2DataParams<T, A, D> {
1479 pub token_id: T,
1481 pub amount: A,
1483 pub from: Address,
1485 pub data: D,
1487}
1488
1489impl<T: Deserial, A: Deserial, D: Deserial> Deserial for OnReceivingCis2DataParams<T, A, D> {
1491 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
1492 let params: OnReceivingCis2Params<T, A> = source.get()?;
1493 let additional_data_type: D = from_bytes(params.data.as_ref())?;
1494 Ok(OnReceivingCis2DataParams {
1495 token_id: params.token_id,
1496 amount: params.amount,
1497 from: params.from,
1498 data: additional_data_type,
1499 })
1500 }
1501}
1502
1503impl<T: Serial, A: Serial, D: Serial> Serial for OnReceivingCis2DataParams<T, A, D> {
1505 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
1506 self.token_id.serial(out)?;
1507 self.amount.serial(out)?;
1508 self.from.serial(out)?;
1509 let add = AdditionalData(to_bytes(&self.data));
1510 add.serial(out)?;
1511 Ok(())
1512 }
1513}
1514
1515impl<T: SchemaType, A: SchemaType, D> SchemaType for OnReceivingCis2DataParams<T, A, D> {
1517 fn get_type() -> schema::Type {
1518 schema::Type::Struct(schema::Fields::Named(vec![
1519 (String::from("token_id"), T::get_type()),
1520 (String::from("amount"), A::get_type()),
1521 (String::from("from"), Address::get_type()),
1522 (String::from("data"), AdditionalData::get_type()),
1524 ]))
1525 }
1526}
1527
1528#[derive(Debug, Serial, PartialEq, Eq)]
1533pub struct StandardIdentifier<'a> {
1534 #[concordium(size_length = 1)]
1535 id: &'a str,
1536}
1537
1538#[derive(Default)]
1541pub struct InvalidStandardIdentifierError;
1542
1543impl<'a> StandardIdentifier<'a> {
1544 pub fn new(id: &'a str) -> Result<Self, InvalidStandardIdentifierError> {
1546 if id.len() > 255 || !id.is_ascii() {
1547 Err(InvalidStandardIdentifierError)
1548 } else {
1549 Ok(Self {
1550 id,
1551 })
1552 }
1553 }
1554
1555 pub const fn new_unchecked(id: &'a str) -> Self {
1557 Self {
1558 id,
1559 }
1560 }
1561
1562 pub fn to_owned(&self) -> StandardIdentifierOwned {
1564 StandardIdentifierOwned::new_unchecked(self.id.to_string())
1565 }
1566}
1567
1568#[derive(Debug, Serialize, PartialEq, Eq, SchemaType, Clone)]
1573#[concordium(transparent)]
1574pub struct StandardIdentifierOwned {
1575 #[concordium(size_length = 1)]
1576 id: String,
1577}
1578
1579impl StandardIdentifierOwned {
1580 pub fn new(id: String) -> Result<Self, InvalidStandardIdentifierError> {
1582 if id.len() > 255 || !id.is_ascii() {
1583 Err(InvalidStandardIdentifierError)
1584 } else {
1585 Ok(Self {
1586 id,
1587 })
1588 }
1589 }
1590
1591 pub fn new_unchecked(id: String) -> Self {
1593 Self {
1594 id,
1595 }
1596 }
1597
1598 pub fn as_standard_identifier(&self) -> StandardIdentifier {
1600 StandardIdentifier::new_unchecked(&self.id)
1601 }
1602}
1603
1604#[derive(Debug, Serialize, SchemaType)]
1606#[concordium(transparent)]
1607pub struct SupportsQueryParams {
1608 #[concordium(size_length = 2)]
1610 pub queries: Vec<StandardIdentifierOwned>,
1611}
1612
1613#[derive(Debug, Serialize, SchemaType)]
1617pub enum SupportResult {
1618 NoSupport,
1620 Support,
1622 SupportBy(#[concordium(size_length = 1)] Vec<ContractAddress>),
1624}
1625
1626#[derive(Debug, Serialize, SchemaType)]
1630#[concordium(transparent)]
1631pub struct SupportsQueryResponse {
1632 #[concordium(size_length = 2)]
1634 pub results: Vec<SupportResult>,
1635}
1636
1637impl From<Vec<SupportResult>> for SupportsQueryResponse {
1638 fn from(results: Vec<SupportResult>) -> Self {
1639 SupportsQueryResponse {
1640 results,
1641 }
1642 }
1643}
1644
1645impl AsRef<[SupportResult]> for SupportsQueryResponse {
1646 fn as_ref(&self) -> &[SupportResult] { &self.results }
1647}
1648
1649#[cfg(test)]
1650mod test {
1651 use super::*;
1652
1653 #[test]
1654 fn serial_token_amount128_127_test() {
1655 let amount = TokenAmountU128::from(127);
1656 let bytes = to_bytes(&amount);
1657 assert_eq!(bytes, vec![127])
1658 }
1659
1660 #[test]
1661 fn serial_token_amount128_max_test() {
1662 let amount = TokenAmountU128::from(u128::MAX);
1663 let bytes = to_bytes(&amount);
1664 assert_eq!(bytes, vec![
1665 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1666 255, 0b00000011
1667 ])
1668 }
1669
1670 #[test]
1671 fn deserial_token_amount128_127_test() {
1672 let amount: TokenAmountU128 = from_bytes(&[127]).expect("Failed to parse bytes");
1673 assert_eq!(amount, TokenAmountU128::from(127))
1674 }
1675
1676 #[test]
1677 fn deserial_token_amount128_max_test() {
1678 let amount: TokenAmountU128 = from_bytes(&[
1679 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1680 255, 0b00000011,
1681 ])
1682 .expect("Failed to parse bytes");
1683 assert_eq!(amount, TokenAmountU128::from(u128::MAX))
1684 }
1685
1686 #[test]
1687 fn serial_token_amount64_127_test() {
1688 let amount = TokenAmountU64::from(127);
1689 let bytes = to_bytes(&amount);
1690 assert_eq!(bytes, vec![127])
1691 }
1692
1693 #[test]
1694 fn serial_token_amount64_max_test() {
1695 let amount = TokenAmountU64::from(u64::MAX);
1696 let bytes = to_bytes(&amount);
1697 assert_eq!(bytes, vec![255, 255, 255, 255, 255, 255, 255, 255, 255, 0b00000001])
1698 }
1699
1700 #[test]
1701 fn deserial_token_amount64_127_test() {
1702 let amount: TokenAmountU64 = from_bytes(&[127]).expect("Failed to parse bytes");
1703 assert_eq!(amount, TokenAmountU64::from(127))
1704 }
1705
1706 #[test]
1707 fn deserial_token_amount64_max_test() {
1708 let amount: TokenAmountU64 =
1709 from_bytes(&[255, 255, 255, 255, 255, 255, 255, 255, 255, 0b00000001])
1710 .expect("Failed to parse bytes");
1711 assert_eq!(amount, TokenAmountU64::from(u64::MAX))
1712 }
1713
1714 #[test]
1715 fn serial_token_amount32_127_test() {
1716 let amount = TokenAmountU32::from(127);
1717 let bytes = to_bytes(&amount);
1718 assert_eq!(bytes, vec![127])
1719 }
1720
1721 #[test]
1722 fn serial_token_amount32_max_test() {
1723 let amount = TokenAmountU32::from(u32::MAX);
1724 let bytes = to_bytes(&amount);
1725 assert_eq!(bytes, vec![255, 255, 255, 255, 0b00001111])
1726 }
1727
1728 #[test]
1729 fn deserial_token_amount32_127_test() {
1730 let amount: TokenAmountU32 = from_bytes(&[127]).expect("Failed to parse bytes");
1731 assert_eq!(amount, TokenAmountU32::from(127))
1732 }
1733
1734 #[test]
1735 fn deserial_token_amount32_max_test() {
1736 let amount: TokenAmountU32 =
1737 from_bytes(&[255, 255, 255, 255, 0b00001111]).expect("Failed to parse bytes");
1738 assert_eq!(amount, TokenAmountU32::from(u32::MAX))
1739 }
1740
1741 #[test]
1742 fn serial_token_amount16_127_test() {
1743 let amount = TokenAmountU16::from(127);
1744 let bytes = to_bytes(&amount);
1745 assert_eq!(bytes, vec![127])
1746 }
1747
1748 #[test]
1749 fn serial_token_amount16_max_test() {
1750 let amount = TokenAmountU16::from(u16::MAX);
1751 let bytes = to_bytes(&amount);
1752 assert_eq!(bytes, vec![255, 255, 0b00000011])
1753 }
1754
1755 #[test]
1756 fn deserial_token_amount16_127_test() {
1757 let amount: TokenAmountU16 = from_bytes(&[127]).expect("Failed to parse bytes");
1758 assert_eq!(amount, TokenAmountU16::from(127))
1759 }
1760
1761 #[test]
1762 fn deserial_token_amount16_max_test() {
1763 let amount: TokenAmountU16 =
1764 from_bytes(&[255, 255, 0b00000011]).expect("Failed to parse bytes");
1765 assert_eq!(amount, TokenAmountU16::from(u16::MAX))
1766 }
1767
1768 #[test]
1769 fn serial_token_amount8_127_test() {
1770 let amount = TokenAmountU8::from(127);
1771 let bytes = to_bytes(&amount);
1772 assert_eq!(bytes, vec![127])
1773 }
1774
1775 #[test]
1776 fn serial_token_amount8_max_test() {
1777 let amount = TokenAmountU8::from(u8::MAX);
1778 let bytes = to_bytes(&amount);
1779 assert_eq!(bytes, vec![255, 0b00000001])
1780 }
1781
1782 #[test]
1783 fn deserial_token_amount8_127_test() {
1784 let amount: TokenAmountU8 = from_bytes(&[127]).expect("Failed to parse bytes");
1785 assert_eq!(amount, TokenAmountU8::from(127))
1786 }
1787
1788 #[test]
1789 fn deserial_token_amount8_max_test() {
1790 let amount: TokenAmountU8 = from_bytes(&[255, 0b00000001]).expect("Failed to parse bytes");
1791 assert_eq!(amount, TokenAmountU8::from(u8::MAX))
1792 }
1793
1794 #[test]
1795 fn token_id_vec_from_str_test() {
1796 let id = TokenIdVec(vec![1, 2, 3, 255]);
1797 assert_eq!(id.to_string().parse(), Ok(id))
1798 }
1799
1800 #[test]
1801 fn parse_bytes_exact_test() {
1802 assert_eq!(parse_bytes_exact::<4>("deadBEEF"), Ok(0xDEADBEEF_u32.to_be_bytes()));
1806 assert!(parse_bytes_exact::<3>("deadBEE").is_err());
1808 assert!(parse_bytes_exact::<4>("deadBEEK").is_err());
1810 }
1811}