1use std::collections::BTreeMap;
2
3use super::Address;
4use super::Identifier;
5use super::ObjectDigest;
6use super::ObjectId;
7use super::StructTag;
8use super::TransactionDigest;
9
10pub type Version = u64;
11
12#[derive(Clone, Debug, PartialEq, Eq)]
24#[cfg_attr(
25 feature = "serde",
26 derive(serde_derive::Serialize, serde_derive::Deserialize)
27)]
28#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
29pub struct ObjectReference {
30 object_id: ObjectId,
32 #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
34 version: Version,
35 digest: ObjectDigest,
37}
38
39impl ObjectReference {
40 pub fn new(object_id: ObjectId, version: Version, digest: ObjectDigest) -> Self {
42 Self {
43 object_id,
44 version,
45 digest,
46 }
47 }
48
49 pub fn object_id(&self) -> &ObjectId {
51 &self.object_id
52 }
53
54 pub fn version(&self) -> Version {
56 self.version
57 }
58
59 pub fn digest(&self) -> &ObjectDigest {
61 &self.digest
62 }
63
64 pub fn into_parts(self) -> (ObjectId, Version, ObjectDigest) {
66 let Self {
67 object_id,
68 version,
69 digest,
70 } = self;
71
72 (object_id, version, digest)
73 }
74}
75
76#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
91#[cfg_attr(
92 feature = "serde",
93 derive(serde_derive::Serialize, serde_derive::Deserialize),
94 serde(rename_all = "lowercase")
95)]
96#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
97pub enum Owner {
98 Address(Address),
100 Object(ObjectId),
102 Shared(
104 #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
106 Version,
107 ),
108 Immutable,
110
111 ConsensusAddress {
113 #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
117 start_version: Version,
118
119 owner: Address,
121 },
122}
123
124#[derive(Clone, Debug, PartialEq, Eq, Hash)]
137#[cfg_attr(
138 feature = "serde",
139 derive(serde_derive::Serialize, serde_derive::Deserialize)
140)]
141#[allow(clippy::large_enum_variant)]
142#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
143pub enum ObjectData {
145 Struct(MoveStruct),
147 Package(MovePackage),
149 }
151
152#[derive(Eq, PartialEq, Debug, Clone, Hash)]
166#[cfg_attr(
167 feature = "serde",
168 derive(serde_derive::Serialize, serde_derive::Deserialize)
169)]
170#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
171pub struct MovePackage {
172 pub id: ObjectId,
174
175 #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
186 pub version: Version,
187
188 #[cfg_attr(
190 feature = "serde",
191 serde(with = "::serde_with::As::<BTreeMap<::serde_with::Same, ::serde_with::Bytes>>")
192 )]
193 #[cfg_attr(
194 feature = "proptest",
195 strategy(
196 proptest::collection::btree_map(proptest::arbitrary::any::<Identifier>(), proptest::collection::vec(proptest::arbitrary::any::<u8>(), 0..=1024), 0..=5)
197 )
198 )]
199 pub modules: BTreeMap<Identifier, Vec<u8>>,
200
201 pub type_origin_table: Vec<TypeOrigin>,
204
205 #[cfg_attr(
208 feature = "proptest",
209 strategy(
210 proptest::collection::btree_map(proptest::arbitrary::any::<ObjectId>(), proptest::arbitrary::any::<UpgradeInfo>(), 0..=5)
211 )
212 )]
213 pub linkage_table: BTreeMap<ObjectId, UpgradeInfo>,
214}
215
216#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
226#[cfg_attr(
227 feature = "serde",
228 derive(serde_derive::Serialize, serde_derive::Deserialize)
229)]
230#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
231pub struct TypeOrigin {
232 pub module_name: Identifier,
233 pub struct_name: Identifier,
234 pub package: ObjectId,
235}
236
237#[derive(Eq, PartialEq, Debug, Clone, Hash)]
247#[cfg_attr(
248 feature = "serde",
249 derive(serde_derive::Serialize, serde_derive::Deserialize)
250)]
251#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
252pub struct UpgradeInfo {
253 pub upgraded_id: ObjectId,
255 #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
257 pub upgraded_version: Version,
258}
259
260#[derive(Eq, PartialEq, Debug, Clone, Hash)]
279#[cfg_attr(
281 feature = "serde",
282 derive(serde_derive::Serialize, serde_derive::Deserialize)
283)]
284#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
285pub struct MoveStruct {
286 #[cfg_attr(
288 feature = "serde",
289 serde(with = "::serde_with::As::<serialization::BinaryMoveStructType>")
290 )]
291 pub(crate) type_: StructTag,
292
293 has_public_transfer: bool,
296
297 #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
300 version: Version,
301
302 #[cfg_attr(
304 feature = "serde",
305 serde(with = "::serde_with::As::<::serde_with::Bytes>")
306 )]
307 #[cfg_attr(feature = "proptest", any(proptest::collection::size_range(32..=1024).lift()))]
308 pub(crate) contents: Vec<u8>,
309}
310
311impl MoveStruct {
312 pub fn new(
314 type_: StructTag,
315 has_public_transfer: bool,
316 version: Version,
317 contents: Vec<u8>,
318 ) -> Option<Self> {
319 id_opt(&contents).map(|_| Self {
320 type_,
321 has_public_transfer,
322 version,
323 contents,
324 })
325 }
326
327 pub fn object_type(&self) -> &StructTag {
329 &self.type_
330 }
331
332 #[doc(hidden)]
339 pub fn has_public_transfer(&self) -> bool {
340 self.has_public_transfer
341 }
342
343 pub fn version(&self) -> Version {
345 self.version
346 }
347
348 pub fn contents(&self) -> &[u8] {
350 &self.contents
351 }
352
353 pub fn object_id(&self) -> ObjectId {
355 id_opt(self.contents()).unwrap()
356 }
357}
358
359#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
361pub enum ObjectType {
362 Package,
364 Struct(StructTag),
366}
367
368#[derive(Clone, Debug, PartialEq, Eq)]
378#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
379pub struct Object {
380 pub(crate) data: ObjectData,
382
383 owner: Owner,
385
386 previous_transaction: TransactionDigest,
388
389 storage_rebate: u64,
393}
394
395impl Object {
396 pub fn new(
398 data: ObjectData,
399 owner: Owner,
400 previous_transaction: TransactionDigest,
401 storage_rebate: u64,
402 ) -> Self {
403 Self {
404 data,
405 owner,
406 previous_transaction,
407 storage_rebate,
408 }
409 }
410
411 pub fn object_id(&self) -> ObjectId {
413 match &self.data {
414 ObjectData::Struct(struct_) => id_opt(&struct_.contents).unwrap(),
415 ObjectData::Package(package) => package.id,
416 }
417 }
418
419 pub fn version(&self) -> Version {
421 match &self.data {
422 ObjectData::Struct(struct_) => struct_.version,
423 ObjectData::Package(package) => package.version,
424 }
425 }
426
427 pub fn object_type(&self) -> ObjectType {
429 match &self.data {
430 ObjectData::Struct(struct_) => ObjectType::Struct(struct_.type_.clone()),
431 ObjectData::Package(_) => ObjectType::Package,
432 }
433 }
434
435 pub fn as_struct(&self) -> Option<&MoveStruct> {
437 match &self.data {
438 ObjectData::Struct(struct_) => Some(struct_),
439 _ => None,
440 }
441 }
442
443 pub fn owner(&self) -> &Owner {
445 &self.owner
446 }
447
448 pub fn data(&self) -> &ObjectData {
450 &self.data
451 }
452
453 pub fn previous_transaction(&self) -> TransactionDigest {
455 self.previous_transaction
456 }
457
458 pub fn storage_rebate(&self) -> u64 {
463 self.storage_rebate
464 }
465}
466
467fn id_opt(contents: &[u8]) -> Option<ObjectId> {
468 if ObjectId::LENGTH > contents.len() {
469 return None;
470 }
471
472 Some(ObjectId::from(
473 Address::from_bytes(&contents[..ObjectId::LENGTH]).unwrap(),
474 ))
475}
476
477#[derive(Clone, Debug, PartialEq, Eq)]
490#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
491pub struct GenesisObject {
492 data: ObjectData,
493 owner: Owner,
494}
495
496impl GenesisObject {
497 pub fn new(data: ObjectData, owner: Owner) -> Self {
498 Self { data, owner }
499 }
500
501 pub fn object_id(&self) -> ObjectId {
502 match &self.data {
503 ObjectData::Struct(struct_) => id_opt(&struct_.contents).unwrap(),
504 ObjectData::Package(package) => package.id,
505 }
506 }
507
508 pub fn version(&self) -> Version {
509 match &self.data {
510 ObjectData::Struct(struct_) => struct_.version,
511 ObjectData::Package(package) => package.version,
512 }
513 }
514
515 pub fn object_type(&self) -> ObjectType {
516 match &self.data {
517 ObjectData::Struct(struct_) => ObjectType::Struct(struct_.type_.clone()),
518 ObjectData::Package(_) => ObjectType::Package,
519 }
520 }
521
522 pub fn owner(&self) -> &Owner {
523 &self.owner
524 }
525
526 pub fn data(&self) -> &ObjectData {
527 &self.data
528 }
529}
530
531#[cfg(feature = "serde")]
533#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
534mod serialization {
535 use std::borrow::Cow;
536 use std::str::FromStr;
537
538 use serde::Deserialize;
539 use serde::Deserializer;
540 use serde::Serialize;
541 use serde::Serializer;
542 use serde_with::DeserializeAs;
543 use serde_with::SerializeAs;
544
545 use super::*;
546 use crate::TypeTag;
547
548 #[test]
549 fn obj() {
550 let o = Object {
551 data: ObjectData::Struct(MoveStruct {
552 type_: StructTag {
553 address: Address::TWO,
554 module: Identifier::new("bar").unwrap(),
555 name: Identifier::new("foo").unwrap(),
556 type_params: Vec::new(),
557 },
558 has_public_transfer: true,
559 version: 12,
560 contents: ObjectId::ZERO.into(),
561 }),
562 owner: Owner::Object(ObjectId::ZERO),
564 previous_transaction: TransactionDigest::ZERO,
569 storage_rebate: 100,
570 };
571
572 println!("{}", serde_json::to_string_pretty(&o).unwrap());
573 println!(
574 "{}",
575 serde_json::to_string_pretty(&ObjectReference {
576 object_id: ObjectId::ZERO,
577 version: 1,
578 digest: ObjectDigest::ZERO,
579 })
580 .unwrap()
581 );
582 }
583
584 #[derive(serde_derive::Deserialize)]
589 enum MoveStructType {
590 Other(StructTag),
592 GasCoin,
594 StakedSui,
596 Coin(TypeTag),
598 }
602
603 #[derive(serde_derive::Serialize)]
605 enum MoveStructTypeRef<'a> {
606 Other(&'a StructTag),
608 GasCoin,
610 StakedSui,
612 Coin(&'a TypeTag),
614 }
618
619 impl MoveStructType {
620 fn into_struct_tag(self) -> StructTag {
621 match self {
622 MoveStructType::Other(tag) => tag,
623 MoveStructType::GasCoin => StructTag::gas_coin(),
624 MoveStructType::StakedSui => StructTag::staked_sui(),
625 MoveStructType::Coin(type_tag) => StructTag::coin(type_tag),
626 }
627 }
628 }
629
630 impl<'a> MoveStructTypeRef<'a> {
631 fn from_struct_tag(s: &'a StructTag) -> Self {
632 let StructTag {
633 address,
634 module,
635 name,
636 type_params,
637 } = s;
638
639 if let Some(coin_type) = s.is_coin() {
640 if let TypeTag::Struct(s_inner) = coin_type {
641 let StructTag {
642 address,
643 module,
644 name,
645 type_params,
646 } = s_inner.as_ref();
647
648 if address == &Address::TWO
649 && module == "sui"
650 && name == "SUI"
651 && type_params.is_empty()
652 {
653 return Self::GasCoin;
654 }
655 }
656
657 Self::Coin(coin_type)
658 } else if address == &Address::THREE
659 && module == "staking_pool"
660 && name == "StakedSui"
661 && type_params.is_empty()
662 {
663 Self::StakedSui
664 } else {
665 Self::Other(s)
666 }
667 }
668 }
669
670 pub(super) struct BinaryMoveStructType;
671
672 impl SerializeAs<StructTag> for BinaryMoveStructType {
673 fn serialize_as<S>(source: &StructTag, serializer: S) -> Result<S::Ok, S::Error>
674 where
675 S: Serializer,
676 {
677 let move_object_type = MoveStructTypeRef::from_struct_tag(source);
678 move_object_type.serialize(serializer)
679 }
680 }
681
682 impl<'de> DeserializeAs<'de, StructTag> for BinaryMoveStructType {
683 fn deserialize_as<D>(deserializer: D) -> Result<StructTag, D::Error>
684 where
685 D: Deserializer<'de>,
686 {
687 let struct_type = MoveStructType::deserialize(deserializer)?;
688 Ok(struct_type.into_struct_tag())
689 }
690 }
691
692 struct ReadableObjectType;
693
694 impl SerializeAs<ObjectType> for ReadableObjectType {
695 fn serialize_as<S>(source: &ObjectType, serializer: S) -> Result<S::Ok, S::Error>
696 where
697 S: Serializer,
698 {
699 match source {
700 ObjectType::Package => "package".serialize(serializer),
701 ObjectType::Struct(s) => s.serialize(serializer),
702 }
703 }
704 }
705
706 impl<'de> DeserializeAs<'de, ObjectType> for ReadableObjectType {
707 fn deserialize_as<D>(deserializer: D) -> Result<ObjectType, D::Error>
708 where
709 D: Deserializer<'de>,
710 {
711 let s: Cow<'de, str> = Deserialize::deserialize(deserializer)?;
712 if s == "package" {
713 Ok(ObjectType::Package)
714 } else {
715 let struct_tag = StructTag::from_str(&s)
716 .map_err(|_| serde::de::Error::custom("invalid object type"))?;
717 Ok(ObjectType::Struct(struct_tag))
718 }
719 }
720 }
721
722 #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
723 #[serde(rename = "Object")]
724 struct ReadableObject {
725 object_id: ObjectId,
726 #[serde(with = "crate::_serde::ReadableDisplay")]
727 version: Version,
728 owner: Owner,
729
730 #[serde(with = "::serde_with::As::<ReadableObjectType>")]
731 #[serde(rename = "type")]
732 type_: ObjectType,
733
734 #[serde(flatten)]
735 data: ReadableObjectData,
736
737 previous_transaction: TransactionDigest,
738 #[serde(with = "crate::_serde::ReadableDisplay")]
739 storage_rebate: u64,
740 }
741
742 #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
743 #[serde(untagged)]
744 enum ReadableObjectData {
745 Move(ReadableMoveStruct),
746 Package(ReadablePackage),
747 }
748
749 #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
750 struct ReadablePackage {
751 #[serde(
752 with = "::serde_with::As::<BTreeMap<::serde_with::Same, crate::_serde::Base64Encoded>>"
753 )]
754 modules: BTreeMap<Identifier, Vec<u8>>,
755 type_origin_table: Vec<TypeOrigin>,
756 linkage_table: BTreeMap<ObjectId, UpgradeInfo>,
757 }
758
759 #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
760 struct ReadableMoveStruct {
761 has_public_transfer: bool,
762 #[serde(with = "::serde_with::As::<crate::_serde::Base64Encoded>")]
763 contents: Vec<u8>,
764 }
765
766 impl Object {
767 fn readable_object_data(&self) -> ReadableObjectData {
768 match &self.data {
769 ObjectData::Struct(struct_) => ReadableObjectData::Move(ReadableMoveStruct {
770 has_public_transfer: struct_.has_public_transfer,
771 contents: struct_.contents.clone(),
772 }),
773 ObjectData::Package(package) => ReadableObjectData::Package(ReadablePackage {
774 modules: package.modules.clone(),
775 type_origin_table: package.type_origin_table.clone(),
776 linkage_table: package.linkage_table.clone(),
777 }),
778 }
779 }
780 }
781
782 impl Serialize for Object {
783 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
784 where
785 S: Serializer,
786 {
787 if serializer.is_human_readable() {
788 let readable = ReadableObject {
789 object_id: self.object_id(),
790 version: self.version(),
791 owner: self.owner,
793 previous_transaction: self.previous_transaction,
794 storage_rebate: self.storage_rebate,
795 type_: self.object_type(),
796 data: self.readable_object_data(),
797 };
798 readable.serialize(serializer)
799 } else {
800 let binary = BinaryObject {
801 data: self.data.clone(),
802 owner: self.owner,
803 previous_transaction: self.previous_transaction,
804 storage_rebate: self.storage_rebate,
805 };
806 binary.serialize(serializer)
807 }
808 }
809 }
810
811 impl<'de> Deserialize<'de> for Object {
812 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
813 where
814 D: Deserializer<'de>,
815 {
816 if deserializer.is_human_readable() {
817 let ReadableObject {
818 object_id,
819 version,
820 owner,
821 previous_transaction,
822 storage_rebate,
823 type_,
824 data,
825 } = Deserialize::deserialize(deserializer)?;
826
827 let data = match (type_, data) {
829 (
830 ObjectType::Package,
831 ReadableObjectData::Package(ReadablePackage {
832 modules,
833 type_origin_table,
834 linkage_table,
835 }),
836 ) => ObjectData::Package(MovePackage {
837 id: object_id,
838 version,
839 modules,
840 type_origin_table,
841 linkage_table,
842 }),
843 (
844 ObjectType::Struct(type_),
845 ReadableObjectData::Move(ReadableMoveStruct {
846 has_public_transfer,
847 contents,
848 }),
849 ) => {
850 #[allow(clippy::nonminimal_bool)]
854 if !id_opt(&contents).is_some_and(|id| id == object_id) {
855 return Err(serde::de::Error::custom("id from contents doesn't match"));
856 }
857
858 ObjectData::Struct(MoveStruct {
859 type_,
860 has_public_transfer,
861 version,
862 contents,
863 })
864 }
865 _ => return Err(serde::de::Error::custom("type and data don't match")),
866 };
867
868 Ok(Object {
869 data,
870 owner,
871 previous_transaction,
872 storage_rebate,
873 })
874 } else {
875 let BinaryObject {
876 data,
877 owner,
878 previous_transaction,
879 storage_rebate,
880 } = Deserialize::deserialize(deserializer)?;
881
882 Ok(Object {
883 data,
884 owner,
885 previous_transaction,
886 storage_rebate,
887 })
888 }
889 }
890 }
891
892 #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
893 struct BinaryObject {
894 data: ObjectData,
895 owner: Owner,
896 previous_transaction: TransactionDigest,
897 storage_rebate: u64,
898 }
899
900 #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
901 #[serde(rename = "GenesisObject")]
902 struct ReadableGenesisObject {
903 object_id: ObjectId,
904 #[serde(with = "crate::_serde::ReadableDisplay")]
905 version: Version,
906 owner: Owner,
907
908 #[serde(with = "::serde_with::As::<ReadableObjectType>")]
909 #[serde(rename = "type")]
910 type_: ObjectType,
911
912 #[serde(flatten)]
913 data: ReadableObjectData,
914 }
915
916 #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
917 enum BinaryGenesisObject {
918 RawObject { data: ObjectData, owner: Owner },
919 }
920
921 impl GenesisObject {
922 fn readable_object_data(&self) -> ReadableObjectData {
923 match &self.data {
924 ObjectData::Struct(struct_) => ReadableObjectData::Move(ReadableMoveStruct {
925 has_public_transfer: struct_.has_public_transfer,
926 contents: struct_.contents.clone(),
927 }),
928 ObjectData::Package(package) => ReadableObjectData::Package(ReadablePackage {
929 modules: package.modules.clone(),
930 type_origin_table: package.type_origin_table.clone(),
931 linkage_table: package.linkage_table.clone(),
932 }),
933 }
934 }
935 }
936
937 impl Serialize for GenesisObject {
938 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
939 where
940 S: Serializer,
941 {
942 if serializer.is_human_readable() {
943 let readable = ReadableGenesisObject {
944 object_id: self.object_id(),
945 version: self.version(),
946 owner: self.owner,
947 type_: self.object_type(),
948 data: self.readable_object_data(),
949 };
950 readable.serialize(serializer)
951 } else {
952 let binary = BinaryGenesisObject::RawObject {
953 data: self.data.clone(),
954 owner: self.owner,
955 };
956 binary.serialize(serializer)
957 }
958 }
959 }
960
961 impl<'de> Deserialize<'de> for GenesisObject {
962 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
963 where
964 D: Deserializer<'de>,
965 {
966 if deserializer.is_human_readable() {
967 let ReadableGenesisObject {
968 object_id,
969 version,
970 owner,
971 type_,
972 data,
973 } = Deserialize::deserialize(deserializer)?;
974
975 let data = match (type_, data) {
977 (
978 ObjectType::Package,
979 ReadableObjectData::Package(ReadablePackage {
980 modules,
981 type_origin_table,
982 linkage_table,
983 }),
984 ) => ObjectData::Package(MovePackage {
985 id: object_id,
986 version,
987 modules,
988 type_origin_table,
989 linkage_table,
990 }),
991 (
992 ObjectType::Struct(type_),
993 ReadableObjectData::Move(ReadableMoveStruct {
994 has_public_transfer,
995 contents,
996 }),
997 ) => {
998 #[allow(clippy::nonminimal_bool)]
1002 if !id_opt(&contents).is_some_and(|id| id == object_id) {
1003 return Err(serde::de::Error::custom("id from contents doesn't match"));
1004 }
1005
1006 ObjectData::Struct(MoveStruct {
1007 type_,
1008 has_public_transfer,
1009 version,
1010 contents,
1011 })
1012 }
1013 _ => return Err(serde::de::Error::custom("type and data don't match")),
1014 };
1015
1016 Ok(GenesisObject { data, owner })
1017 } else {
1018 let BinaryGenesisObject::RawObject { data, owner } =
1019 Deserialize::deserialize(deserializer)?;
1020
1021 Ok(GenesisObject { data, owner })
1022 }
1023 }
1024 }
1025
1026 #[cfg(test)]
1027 mod test {
1028 use crate::object::Object;
1029
1030 #[cfg(target_arch = "wasm32")]
1031 use wasm_bindgen_test::wasm_bindgen_test as test;
1032
1033 #[test]
1034 fn object_fixture() {
1035 const SUI_COIN: &[u8] = &[
1036 0, 1, 1, 32, 79, 43, 0, 0, 0, 0, 0, 40, 35, 95, 175, 213, 151, 87, 206, 190, 35,
1037 131, 79, 35, 254, 22, 15, 181, 40, 108, 28, 77, 68, 229, 107, 254, 191, 160, 196,
1038 186, 42, 2, 122, 53, 52, 133, 199, 58, 0, 0, 0, 0, 0, 79, 255, 208, 0, 85, 34, 190,
1039 75, 192, 41, 114, 76, 127, 15, 110, 215, 9, 58, 107, 243, 160, 155, 144, 230, 47,
1040 97, 220, 21, 24, 30, 26, 62, 32, 17, 197, 192, 38, 64, 173, 142, 143, 49, 111, 15,
1041 211, 92, 84, 48, 160, 243, 102, 229, 253, 251, 137, 210, 101, 119, 173, 228, 51,
1042 141, 20, 15, 85, 96, 19, 15, 0, 0, 0, 0, 0,
1043 ];
1044
1045 const SUI_STAKE: &[u8] = &[
1046 0, 2, 1, 154, 1, 52, 5, 0, 0, 0, 0, 80, 3, 112, 71, 231, 166, 234, 205, 164, 99,
1047 237, 29, 56, 97, 170, 21, 96, 105, 158, 227, 122, 22, 251, 60, 162, 12, 97, 151,
1048 218, 71, 253, 231, 239, 116, 138, 12, 233, 128, 195, 128, 77, 33, 38, 122, 77, 53,
1049 154, 197, 198, 75, 212, 12, 182, 163, 224, 42, 82, 123, 69, 248, 40, 207, 143, 211,
1050 13, 106, 1, 0, 0, 0, 0, 0, 0, 59, 81, 183, 246, 112, 0, 0, 0, 0, 79, 255, 208, 0,
1051 85, 34, 190, 75, 192, 41, 114, 76, 127, 15, 110, 215, 9, 58, 107, 243, 160, 155,
1052 144, 230, 47, 97, 220, 21, 24, 30, 26, 62, 32, 247, 239, 248, 71, 247, 102, 190,
1053 149, 232, 153, 138, 67, 169, 209, 203, 29, 255, 215, 223, 57, 159, 44, 40, 218,
1054 166, 13, 80, 71, 14, 188, 232, 68, 0, 0, 0, 0, 0, 0, 0, 0,
1055 ];
1056
1057 const NFT: &[u8] = &[
1058 0, 0, 97, 201, 195, 159, 216, 97, 133, 173, 96, 215, 56, 212, 229, 43, 208, 139,
1059 218, 7, 29, 54, 106, 205, 224, 126, 7, 195, 145, 106, 45, 117, 168, 22, 12, 100,
1060 105, 115, 116, 114, 105, 98, 117, 116, 105, 111, 110, 11, 68, 69, 69, 80, 87, 114,
1061 97, 112, 112, 101, 114, 0, 0, 124, 24, 223, 4, 0, 0, 0, 0, 40, 31, 8, 18, 84, 38,
1062 164, 252, 84, 115, 250, 246, 137, 132, 128, 186, 156, 36, 62, 18, 140, 21, 4, 90,
1063 209, 105, 85, 84, 92, 214, 97, 81, 207, 64, 194, 198, 208, 21, 0, 0, 0, 0, 79, 255,
1064 208, 0, 85, 34, 190, 75, 192, 41, 114, 76, 127, 15, 110, 215, 9, 58, 107, 243, 160,
1065 155, 144, 230, 47, 97, 220, 21, 24, 30, 26, 62, 32, 170, 4, 94, 114, 207, 155, 31,
1066 80, 62, 254, 220, 206, 240, 218, 83, 54, 204, 197, 255, 239, 41, 66, 199, 150, 56,
1067 189, 86, 217, 166, 216, 128, 241, 64, 205, 21, 0, 0, 0, 0, 0,
1068 ];
1069
1070 const FUD_COIN: &[u8] = &[
1071 0, 3, 7, 118, 203, 129, 155, 1, 171, 237, 80, 43, 238, 138, 112, 43, 76, 45, 84,
1072 117, 50, 193, 47, 37, 0, 28, 157, 234, 121, 90, 94, 99, 28, 38, 241, 3, 102, 117,
1073 100, 3, 70, 85, 68, 0, 1, 193, 89, 252, 3, 0, 0, 0, 0, 40, 33, 214, 90, 11, 56,
1074 243, 115, 10, 250, 121, 250, 28, 34, 237, 104, 130, 148, 40, 130, 29, 248, 137,
1075 244, 27, 138, 94, 150, 28, 182, 104, 162, 185, 0, 152, 247, 62, 93, 1, 0, 0, 0, 42,
1076 95, 32, 226, 13, 31, 128, 91, 188, 127, 235, 12, 75, 73, 116, 112, 3, 227, 244,
1077 126, 59, 81, 214, 118, 144, 243, 195, 17, 82, 216, 119, 170, 32, 239, 247, 71, 249,
1078 241, 98, 133, 53, 46, 37, 100, 242, 94, 231, 241, 184, 8, 69, 192, 69, 67, 1, 116,
1079 251, 229, 226, 99, 119, 79, 255, 71, 43, 64, 242, 19, 0, 0, 0, 0, 0,
1080 ];
1081
1082 const BULLSHARK_PACKAGE: &[u8] = &[
1083 1, 135, 35, 29, 28, 138, 126, 114, 145, 204, 122, 145, 8, 244, 199, 188, 26, 10,
1084 28, 14, 182, 55, 91, 91, 97, 10, 245, 202, 35, 223, 14, 140, 86, 1, 0, 0, 0, 0, 0,
1085 0, 0, 1, 9, 98, 117, 108, 108, 115, 104, 97, 114, 107, 162, 6, 161, 28, 235, 11, 6,
1086 0, 0, 0, 10, 1, 0, 12, 2, 12, 36, 3, 48, 61, 4, 109, 12, 5, 121, 137, 1, 7, 130, 2,
1087 239, 1, 8, 241, 3, 96, 6, 209, 4, 82, 10, 163, 5, 5, 12, 168, 5, 75, 0, 7, 1, 16,
1088 2, 9, 2, 21, 2, 22, 2, 23, 0, 0, 2, 0, 1, 3, 7, 1, 0, 0, 2, 1, 12, 1, 0, 1, 2, 2,
1089 12, 1, 0, 1, 2, 4, 12, 1, 0, 1, 4, 5, 2, 0, 5, 6, 7, 0, 0, 12, 0, 1, 0, 0, 13, 2,
1090 1, 0, 0, 8, 3, 1, 0, 1, 20, 7, 8, 1, 0, 2, 8, 18, 19, 1, 0, 2, 10, 10, 11, 1, 2, 2,
1091 14, 17, 1, 1, 0, 3, 17, 7, 1, 1, 12, 3, 18, 16, 1, 1, 12, 4, 19, 13, 14, 0, 5, 15,
1092 5, 6, 0, 3, 6, 5, 9, 7, 12, 8, 15, 6, 9, 4, 9, 2, 8, 0, 7, 8, 5, 0, 4, 7, 11, 4, 1,
1093 8, 0, 3, 5, 7, 8, 5, 2, 7, 11, 4, 1, 8, 0, 11, 2, 1, 8, 0, 2, 11, 3, 1, 8, 0, 11,
1094 4, 1, 8, 0, 1, 10, 2, 1, 8, 6, 1, 9, 0, 1, 11, 1, 1, 9, 0, 1, 8, 0, 7, 9, 0, 2, 10,
1095 2, 10, 2, 10, 2, 11, 1, 1, 8, 6, 7, 8, 5, 2, 11, 4, 1, 9, 0, 11, 3, 1, 9, 0, 1, 11,
1096 3, 1, 8, 0, 1, 6, 8, 5, 1, 5, 1, 11, 4, 1, 8, 0, 2, 9, 0, 5, 4, 7, 11, 4, 1, 9, 0,
1097 3, 5, 7, 8, 5, 2, 7, 11, 4, 1, 9, 0, 11, 2, 1, 9, 0, 1, 3, 9, 66, 85, 76, 76, 83,
1098 72, 65, 82, 75, 4, 67, 111, 105, 110, 12, 67, 111, 105, 110, 77, 101, 116, 97, 100,
1099 97, 116, 97, 6, 79, 112, 116, 105, 111, 110, 11, 84, 114, 101, 97, 115, 117, 114,
1100 121, 67, 97, 112, 9, 84, 120, 67, 111, 110, 116, 101, 120, 116, 3, 85, 114, 108, 9,
1101 98, 117, 108, 108, 115, 104, 97, 114, 107, 4, 98, 117, 114, 110, 4, 99, 111, 105,
1102 110, 15, 99, 114, 101, 97, 116, 101, 95, 99, 117, 114, 114, 101, 110, 99, 121, 11,
1103 100, 117, 109, 109, 121, 95, 102, 105, 101, 108, 100, 4, 105, 110, 105, 116, 4,
1104 109, 105, 110, 116, 17, 109, 105, 110, 116, 95, 97, 110, 100, 95, 116, 114, 97,
1105 110, 115, 102, 101, 114, 21, 110, 101, 119, 95, 117, 110, 115, 97, 102, 101, 95,
1106 102, 114, 111, 109, 95, 98, 121, 116, 101, 115, 6, 111, 112, 116, 105, 111, 110,
1107 20, 112, 117, 98, 108, 105, 99, 95, 102, 114, 101, 101, 122, 101, 95, 111, 98, 106,
1108 101, 99, 116, 15, 112, 117, 98, 108, 105, 99, 95, 116, 114, 97, 110, 115, 102, 101,
1109 114, 6, 115, 101, 110, 100, 101, 114, 4, 115, 111, 109, 101, 8, 116, 114, 97, 110,
1110 115, 102, 101, 114, 10, 116, 120, 95, 99, 111, 110, 116, 101, 120, 116, 3, 117,
1111 114, 108, 135, 35, 29, 28, 138, 126, 114, 145, 204, 122, 145, 8, 244, 199, 188, 26,
1112 10, 28, 14, 182, 55, 91, 91, 97, 10, 245, 202, 35, 223, 14, 140, 86, 0, 0, 0, 0, 0,
1113 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
1114 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1115 0, 0, 2, 10, 2, 10, 9, 66, 85, 76, 76, 83, 72, 65, 82, 75, 10, 2, 20, 19, 66, 117,
1116 108, 108, 32, 83, 104, 97, 114, 107, 32, 83, 117, 105, 70, 114, 101, 110, 115, 10,
1117 2, 1, 0, 10, 2, 39, 38, 104, 116, 116, 112, 115, 58, 47, 47, 105, 46, 105, 98, 98,
1118 46, 99, 111, 47, 104, 87, 89, 50, 87, 53, 120, 47, 98, 117, 108, 108, 115, 104, 97,
1119 114, 107, 46, 112, 110, 103, 0, 2, 1, 11, 1, 0, 0, 0, 0, 4, 20, 11, 0, 49, 6, 7, 0,
1120 7, 1, 7, 2, 7, 3, 17, 10, 56, 0, 10, 1, 56, 1, 12, 2, 12, 3, 11, 2, 56, 2, 11, 3,
1121 11, 1, 46, 17, 9, 56, 3, 2, 1, 1, 4, 0, 1, 6, 11, 0, 11, 1, 11, 2, 11, 3, 56, 4, 2,
1122 2, 1, 4, 0, 1, 5, 11, 0, 11, 1, 56, 5, 1, 2, 0, 1, 9, 98, 117, 108, 108, 115, 104,
1123 97, 114, 107, 9, 66, 85, 76, 76, 83, 72, 65, 82, 75, 135, 35, 29, 28, 138, 126,
1124 114, 145, 204, 122, 145, 8, 244, 199, 188, 26, 10, 28, 14, 182, 55, 91, 91, 97, 10,
1125 245, 202, 35, 223, 14, 140, 86, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1126 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1127 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
1128 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1129 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1130 0, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 3, 32, 87, 145, 191, 231, 147, 185,
1131 46, 159, 240, 181, 95, 126, 236, 65, 154, 55, 16, 196, 229, 218, 47, 59, 99, 197,
1132 13, 89, 18, 159, 205, 129, 112, 131, 112, 192, 126, 0, 0, 0, 0, 0,
1133 ];
1134
1135 for fixture in [SUI_COIN, SUI_STAKE, NFT, FUD_COIN, BULLSHARK_PACKAGE] {
1136 let object: Object = bcs::from_bytes(fixture).unwrap();
1137 assert_eq!(bcs::to_bytes(&object).unwrap(), fixture);
1138
1139 let json = serde_json::to_string_pretty(&object).unwrap();
1140 println!("{json}");
1141 assert_eq!(object, serde_json::from_str(&json).unwrap());
1142 }
1143 }
1144 }
1145}