1use std::cmp::Ordering;
5use std::collections::BTreeMap;
6use std::fmt;
7use std::fmt::{Display, Formatter, Write};
8use std::str::FromStr;
9
10use af_sui_types::{
11 Address as SuiAddress,
12 Identifier,
13 MoveObjectType,
14 ObjectArg,
15 ObjectDigest,
16 ObjectId,
17 ObjectRef,
18 Owner,
19 StructTag,
20 TransactionDigest,
21 TypeOrigin,
22 UpgradeInfo,
23};
24use colored::Colorize;
25use serde::{Deserialize, Serialize};
26use serde_json::Value;
27use serde_with::base64::Base64;
28use serde_with::{DisplayFromStr, serde_as};
29use sui_sdk_types::Version;
30
31use super::{Page, SuiMoveStruct, SuiMoveValue};
32use crate::serde::BigInt;
33
34#[derive(thiserror::Error, Clone, Debug, PartialEq, Eq)]
39#[error("Could not get object_id, something went wrong with SuiObjectResponse construction.")]
40pub struct MissingObjectIdError;
41
42#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
43pub struct SuiObjectResponse {
44 #[serde(skip_serializing_if = "Option::is_none")]
45 pub data: Option<SuiObjectData>,
46 #[serde(skip_serializing_if = "Option::is_none")]
47 pub error: Option<SuiObjectResponseError>,
48}
49
50impl SuiObjectResponse {
51 pub fn new(data: Option<SuiObjectData>, error: Option<SuiObjectResponseError>) -> Self {
52 Self { data, error }
53 }
54
55 pub fn new_with_data(data: SuiObjectData) -> Self {
56 Self {
57 data: Some(data),
58 error: None,
59 }
60 }
61
62 pub fn new_with_error(error: SuiObjectResponseError) -> Self {
63 Self {
64 data: None,
65 error: Some(error),
66 }
67 }
68
69 pub fn object(&self) -> Result<&SuiObjectData, SuiObjectResponseError> {
72 if let Some(data) = &self.data {
73 Ok(data)
74 } else if let Some(error) = &self.error {
75 Err(error.clone())
76 } else {
77 Err(SuiObjectResponseError::Unknown)
79 }
80 }
81
82 pub fn into_object(self) -> Result<SuiObjectData, SuiObjectResponseError> {
85 match self.object() {
86 Ok(data) => Ok(data.clone()),
87 Err(error) => Err(error),
88 }
89 }
90
91 pub fn move_object_bcs(&self) -> Option<&Vec<u8>> {
92 match &self.data {
93 Some(SuiObjectData {
94 bcs: Some(SuiRawData::MoveObject(obj)),
95 ..
96 }) => Some(&obj.bcs_bytes),
97 _ => None,
98 }
99 }
100
101 pub fn owner(&self) -> Option<Owner> {
102 if let Some(data) = &self.data {
103 return data.owner.clone();
104 }
105 None
106 }
107
108 pub fn object_id(&self) -> Result<ObjectId, MissingObjectIdError> {
109 match (&self.data, &self.error) {
110 (Some(obj_data), None) => Ok(obj_data.object_id),
111 (None, Some(SuiObjectResponseError::NotExists { object_id })) => Ok(*object_id),
112 (
113 None,
114 Some(SuiObjectResponseError::Deleted {
115 object_id,
116 version: _,
117 digest: _,
118 }),
119 ) => Ok(*object_id),
120 _ => Err(MissingObjectIdError),
121 }
122 }
123
124 pub fn object_ref_if_exists(&self) -> Option<ObjectRef> {
125 match (&self.data, &self.error) {
126 (Some(obj_data), None) => Some(obj_data.object_ref()),
127 _ => None,
128 }
129 }
130}
131
132impl Ord for SuiObjectResponse {
133 fn cmp(&self, other: &Self) -> Ordering {
134 match (&self.data, &other.data) {
135 (Some(data), Some(data_2)) => {
136 if data.object_id.cmp(&data_2.object_id).eq(&Ordering::Greater) {
137 return Ordering::Greater;
138 } else if data.object_id.cmp(&data_2.object_id).eq(&Ordering::Less) {
139 return Ordering::Less;
140 }
141 Ordering::Equal
142 }
143 (Some(_), None) => Ordering::Less,
145 (None, Some(_)) => Ordering::Greater,
146 _ => Ordering::Equal,
148 }
149 }
150}
151
152impl PartialOrd for SuiObjectResponse {
153 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
154 Some(self.cmp(other))
155 }
156}
157
158#[derive(thiserror::Error, Eq, PartialEq, Clone, Debug, Serialize, Deserialize, Hash)]
160#[serde(tag = "code", rename = "ObjectResponseError", rename_all = "camelCase")]
161pub enum SuiObjectResponseError {
162 #[error("Object {:?} does not exist.", object_id)]
163 NotExists { object_id: ObjectId },
164 #[error("Cannot find dynamic field for parent object {:?}.", parent_object_id)]
165 DynamicFieldNotFound { parent_object_id: ObjectId },
166 #[error(
167 "Object has been deleted object_id: {:?} at version: {:?} in digest {:?}",
168 object_id,
169 version,
170 digest
171 )]
172 Deleted {
173 object_id: ObjectId,
174 version: Version,
176 digest: ObjectDigest,
178 },
179 #[error("Unknown Error.")]
180 Unknown,
181 #[error("Display Error: {:?}", error)]
182 DisplayError { error: String },
183}
184
185#[derive(Debug, Clone, Deserialize, Serialize, Eq, PartialEq)]
186pub struct DisplayFieldsResponse {
187 pub data: Option<BTreeMap<String, String>>,
188 pub error: Option<SuiObjectResponseError>,
189}
190
191#[derive(thiserror::Error, Debug)]
196pub enum SuiObjectDataError {
197 #[error("Missing object type")]
198 MissingObjectType,
199 #[error("Missing BCS encoding")]
200 MissingBcs,
201 #[error("Missing object owner")]
202 MissingOwner,
203 #[error("Not a Move object")]
204 NotMoveObject,
205 #[error("Not an immutable or owned object")]
206 NotImmOrOwned,
207 #[error("Not a shared object")]
208 NotShared,
209 #[error(transparent)]
210 ObjectType(#[from] NotMoveStructError),
211}
212
213#[serde_as]
214#[derive(Debug, Clone, Deserialize, Serialize, Eq, PartialEq)]
215#[serde(rename_all = "camelCase", rename = "ObjectData")]
216pub struct SuiObjectData {
217 pub object_id: ObjectId,
218 #[serde_as(as = "BigInt<u64>")]
220 pub version: Version,
221 pub digest: ObjectDigest,
223 #[serde_as(as = "Option<DisplayFromStr>")]
225 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
226 pub type_: Option<ObjectType>,
227 #[serde(skip_serializing_if = "Option::is_none")]
230 pub owner: Option<Owner>,
231 #[serde(skip_serializing_if = "Option::is_none")]
234 pub previous_transaction: Option<TransactionDigest>,
235 #[serde_as(as = "Option<BigInt<u64>>")]
239 #[serde(skip_serializing_if = "Option::is_none")]
240 pub storage_rebate: Option<u64>,
241 #[serde(skip_serializing_if = "Option::is_none")]
245 pub display: Option<DisplayFieldsResponse>,
246 #[serde(skip_serializing_if = "Option::is_none")]
248 pub content: Option<SuiParsedData>,
249 #[serde(skip_serializing_if = "Option::is_none")]
251 pub bcs: Option<SuiRawData>,
252}
253
254impl SuiObjectData {
255 pub fn object_ref(&self) -> ObjectRef {
256 (self.object_id, self.version, self.digest)
257 }
258
259 pub fn object_type(&self) -> Result<ObjectType, SuiObjectDataError> {
260 self.type_
261 .as_ref()
262 .ok_or(SuiObjectDataError::MissingObjectType)
263 .cloned()
264 }
265
266 pub fn is_gas_coin(&self) -> bool {
267 match self.type_.as_ref() {
268 Some(ObjectType::Struct(ty)) if ty.is_gas_coin() => true,
269 Some(_) => false,
270 None => false,
271 }
272 }
273
274 pub fn struct_tag(&self) -> Result<StructTag, SuiObjectDataError> {
275 Ok(self
276 .type_
277 .clone()
278 .ok_or(SuiObjectDataError::MissingObjectType)?
279 .try_into()?)
280 }
281
282 pub fn take_object_type(&mut self) -> Result<ObjectType, SuiObjectDataError> {
283 self.type_
284 .take()
285 .ok_or(SuiObjectDataError::MissingObjectType)
286 }
287
288 pub fn take_raw_object(&mut self) -> Result<SuiRawMoveObject, SuiObjectDataError> {
289 self.take_raw_data()?
290 .try_into_move()
291 .ok_or(SuiObjectDataError::NotMoveObject)
292 }
293
294 pub fn take_raw_data(&mut self) -> Result<SuiRawData, SuiObjectDataError> {
295 self.bcs.take().ok_or(SuiObjectDataError::MissingBcs)
296 }
297
298 pub fn shared_object_arg(&self, mutable: bool) -> Result<ObjectArg, SuiObjectDataError> {
299 let Owner::Shared {
300 initial_shared_version,
301 } = self.owner()?
302 else {
303 return Err(SuiObjectDataError::NotShared);
304 };
305 Ok(ObjectArg::SharedObject {
306 id: self.object_id,
307 initial_shared_version,
308 mutable,
309 })
310 }
311
312 pub fn imm_or_owned_object_arg(&self) -> Result<ObjectArg, SuiObjectDataError> {
313 use Owner::*;
314 if !matches!(self.owner()?, AddressOwner(_) | ObjectOwner(_) | Immutable) {
315 return Err(SuiObjectDataError::NotImmOrOwned);
316 };
317 let (i, v, d) = self.object_ref();
318 Ok(ObjectArg::ImmOrOwnedObject((i, v, d)))
319 }
320
321 pub fn owner(&self) -> Result<Owner, SuiObjectDataError> {
322 self.owner.clone().ok_or(SuiObjectDataError::MissingOwner)
323 }
324}
325
326impl Display for SuiObjectData {
327 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
328 let type_ = if let Some(type_) = &self.type_ {
329 type_.to_string()
330 } else {
331 "Unknown Type".into()
332 };
333 let mut writer = String::new();
334 writeln!(
335 writer,
336 "{}",
337 format!("----- {type_} ({}[{}]) -----", self.object_id, self.version).bold()
338 )?;
339 if let Some(ref owner) = self.owner {
340 writeln!(writer, "{}: {}", "Owner".bold().bright_black(), owner)?;
341 }
342
343 writeln!(
344 writer,
345 "{}: {}",
346 "Version".bold().bright_black(),
347 self.version
348 )?;
349 if let Some(storage_rebate) = self.storage_rebate {
350 writeln!(
351 writer,
352 "{}: {}",
353 "Storage Rebate".bold().bright_black(),
354 storage_rebate
355 )?;
356 }
357
358 if let Some(previous_transaction) = self.previous_transaction {
359 writeln!(
360 writer,
361 "{}: {:?}",
362 "Previous Transaction".bold().bright_black(),
363 previous_transaction
364 )?;
365 }
366 if let Some(content) = self.content.as_ref() {
367 writeln!(writer, "{}", "----- Data -----".bold())?;
368 write!(writer, "{}", content)?;
369 }
370
371 write!(f, "{}", writer)
372 }
373}
374
375const PACKAGE: &str = "package";
380#[derive(Clone, Serialize, Deserialize, Ord, PartialOrd, Eq, PartialEq, Debug)]
384pub enum ObjectType {
385 Package,
387 Struct(MoveObjectType),
389}
390
391impl TryFrom<ObjectType> for StructTag {
392 type Error = NotMoveStructError;
393
394 fn try_from(o: ObjectType) -> Result<Self, Self::Error> {
395 match o {
396 ObjectType::Package => Err(NotMoveStructError),
397 ObjectType::Struct(move_object_type) => Ok(move_object_type.into()),
398 }
399 }
400}
401
402#[derive(thiserror::Error, Clone, Debug, PartialEq, Eq)]
403#[error("Cannot create StructTag from Package")]
404pub struct NotMoveStructError;
405
406impl Display for ObjectType {
407 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
408 match self {
409 ObjectType::Package => write!(f, "{}", PACKAGE),
410 ObjectType::Struct(t) => write!(f, "{}", t),
411 }
412 }
413}
414
415impl FromStr for ObjectType {
416 type Err = <StructTag as FromStr>::Err;
417
418 fn from_str(s: &str) -> Result<Self, Self::Err> {
419 if s.to_lowercase() == PACKAGE {
420 Ok(ObjectType::Package)
421 } else {
422 let tag: StructTag = s.parse()?;
423 Ok(ObjectType::Struct(MoveObjectType::from(tag)))
424 }
425 }
426}
427
428#[derive(Debug, Clone, Deserialize, Serialize, Eq, PartialEq, Default)]
433#[serde(rename_all = "camelCase", rename = "ObjectDataOptions", default)]
434pub struct SuiObjectDataOptions {
435 pub show_type: bool,
437 pub show_owner: bool,
439 pub show_previous_transaction: bool,
441 pub show_display: bool,
443 pub show_content: bool,
446 pub show_bcs: bool,
448 pub show_storage_rebate: bool,
450}
451
452impl SuiObjectDataOptions {
453 pub fn new() -> Self {
454 Self::default()
455 }
456
457 pub fn bcs_lossless() -> Self {
459 Self {
460 show_bcs: true,
461 show_type: true,
462 show_owner: true,
463 show_previous_transaction: true,
464 show_display: false,
465 show_content: false,
466 show_storage_rebate: true,
467 }
468 }
469
470 pub fn full_content() -> Self {
472 Self {
473 show_bcs: false,
474 show_type: true,
475 show_owner: true,
476 show_previous_transaction: true,
477 show_display: false,
478 show_content: true,
479 show_storage_rebate: true,
480 }
481 }
482
483 pub fn with_content(mut self) -> Self {
484 self.show_content = true;
485 self
486 }
487
488 pub fn with_owner(mut self) -> Self {
489 self.show_owner = true;
490 self
491 }
492
493 pub fn with_type(mut self) -> Self {
494 self.show_type = true;
495 self
496 }
497
498 pub fn with_display(mut self) -> Self {
499 self.show_display = true;
500 self
501 }
502
503 pub fn with_bcs(mut self) -> Self {
504 self.show_bcs = true;
505 self
506 }
507
508 pub fn with_previous_transaction(mut self) -> Self {
509 self.show_previous_transaction = true;
510 self
511 }
512
513 pub fn is_not_in_object_info(&self) -> bool {
514 self.show_bcs || self.show_content || self.show_display || self.show_storage_rebate
515 }
516}
517
518#[derive(Debug, Clone, Deserialize, Serialize, Eq, PartialEq, Ord, PartialOrd)]
523#[serde(rename_all = "camelCase", rename = "ObjectRef")]
524pub struct SuiObjectRef {
525 pub object_id: ObjectId,
527 pub version: Version,
529 pub digest: ObjectDigest,
531}
532
533impl SuiObjectRef {
534 pub fn to_object_ref(&self) -> ObjectRef {
535 (self.object_id, self.version, self.digest)
536 }
537}
538
539impl Display for SuiObjectRef {
540 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
541 write!(
542 f,
543 "Object ID: {}, version: {}, digest: {}",
544 self.object_id, self.version, self.digest
545 )
546 }
547}
548
549impl From<ObjectRef> for SuiObjectRef {
550 fn from(oref: ObjectRef) -> Self {
551 Self {
552 object_id: oref.0,
553 version: oref.1,
554 digest: oref.2,
555 }
556 }
557}
558
559pub trait SuiData: Sized {
564 type ObjectType;
565 type PackageType;
566 fn try_as_move(&self) -> Option<&Self::ObjectType>;
567 fn try_into_move(self) -> Option<Self::ObjectType>;
568 fn try_as_package(&self) -> Option<&Self::PackageType>;
569 fn type_(&self) -> Option<&StructTag>;
570}
571
572#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)]
573#[serde(tag = "dataType", rename_all = "camelCase", rename = "RawData")]
574pub enum SuiRawData {
575 MoveObject(SuiRawMoveObject),
577 Package(SuiRawMovePackage),
578}
579
580impl SuiData for SuiRawData {
581 type ObjectType = SuiRawMoveObject;
582 type PackageType = SuiRawMovePackage;
583
584 fn try_as_move(&self) -> Option<&Self::ObjectType> {
585 match self {
586 Self::MoveObject(o) => Some(o),
587 Self::Package(_) => None,
588 }
589 }
590
591 fn try_into_move(self) -> Option<Self::ObjectType> {
592 match self {
593 Self::MoveObject(o) => Some(o),
594 Self::Package(_) => None,
595 }
596 }
597
598 fn try_as_package(&self) -> Option<&Self::PackageType> {
599 match self {
600 Self::MoveObject(_) => None,
601 Self::Package(p) => Some(p),
602 }
603 }
604
605 fn type_(&self) -> Option<&StructTag> {
606 match self {
607 Self::MoveObject(o) => Some(&o.type_),
608 Self::Package(_) => None,
609 }
610 }
611}
612
613#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)]
614#[serde(tag = "dataType", rename_all = "camelCase", rename = "Data")]
615pub enum SuiParsedData {
616 MoveObject(SuiParsedMoveObject),
618 Package(SuiMovePackage),
619}
620
621impl SuiData for SuiParsedData {
622 type ObjectType = SuiParsedMoveObject;
623 type PackageType = SuiMovePackage;
624
625 fn try_as_move(&self) -> Option<&Self::ObjectType> {
626 match self {
627 Self::MoveObject(o) => Some(o),
628 Self::Package(_) => None,
629 }
630 }
631
632 fn try_into_move(self) -> Option<Self::ObjectType> {
633 match self {
634 Self::MoveObject(o) => Some(o),
635 Self::Package(_) => None,
636 }
637 }
638
639 fn try_as_package(&self) -> Option<&Self::PackageType> {
640 match self {
641 Self::MoveObject(_) => None,
642 Self::Package(p) => Some(p),
643 }
644 }
645
646 fn type_(&self) -> Option<&StructTag> {
647 match self {
648 Self::MoveObject(o) => Some(&o.type_),
649 Self::Package(_) => None,
650 }
651 }
652}
653
654impl Display for SuiParsedData {
655 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
656 let mut writer = String::new();
657 match self {
658 SuiParsedData::MoveObject(o) => {
659 writeln!(writer, "{}: {}", "type".bold().bright_black(), o.type_)?;
660 write!(writer, "{}", &o.fields)?;
661 }
662 SuiParsedData::Package(p) => {
663 write!(
664 writer,
665 "{}: {:?}",
666 "Modules".bold().bright_black(),
667 p.disassembled.keys()
668 )?;
669 }
670 }
671 write!(f, "{}", writer)
672 }
673}
674
675pub trait SuiMoveObject: Sized {
676 fn type_(&self) -> &StructTag;
677}
678
679#[serde_as]
680#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)]
681#[serde(rename = "MoveObject", rename_all = "camelCase")]
682pub struct SuiParsedMoveObject {
683 #[serde(rename = "type")]
684 #[serde_as(as = "DisplayFromStr")]
686 pub type_: StructTag,
687 pub has_public_transfer: bool,
688 pub fields: SuiMoveStruct,
689}
690
691impl SuiMoveObject for SuiParsedMoveObject {
692 fn type_(&self) -> &StructTag {
693 &self.type_
694 }
695}
696
697impl SuiParsedMoveObject {
698 pub fn read_dynamic_field_value(&self, field_name: &str) -> Option<SuiMoveValue> {
699 match &self.fields {
700 SuiMoveStruct::WithFields(fields) => fields.get(field_name).cloned(),
701 SuiMoveStruct::WithTypes { fields, .. } => fields.get(field_name).cloned(),
702 _ => None,
703 }
704 }
705}
706
707#[serde_as]
708#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)]
709#[serde(rename = "RawMoveObject", rename_all = "camelCase")]
710pub struct SuiRawMoveObject {
711 #[serde(rename = "type")]
712 #[serde_as(as = "DisplayFromStr")]
714 pub type_: StructTag,
715 pub has_public_transfer: bool,
716 pub version: Version,
717 #[serde_as(as = "Base64")]
718 pub bcs_bytes: Vec<u8>,
719}
720
721impl SuiMoveObject for SuiRawMoveObject {
722 fn type_(&self) -> &StructTag {
723 &self.type_
724 }
725}
726
727impl SuiRawMoveObject {
728 pub fn deserialize<'a, T: Deserialize<'a>>(&'a self) -> Result<T, bcs::Error> {
729 bcs::from_bytes(self.bcs_bytes.as_slice())
730 }
731}
732
733#[serde_as]
734#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)]
735#[serde(rename = "RawMovePackage", rename_all = "camelCase")]
736pub struct SuiRawMovePackage {
737 pub id: ObjectId,
738 pub version: Version,
739 #[serde_as(as = "BTreeMap<_, Base64>")]
740 pub module_map: BTreeMap<String, Vec<u8>>,
741 pub type_origin_table: Vec<TypeOrigin>,
742 pub linkage_table: BTreeMap<ObjectId, UpgradeInfo>,
743}
744
745#[derive(thiserror::Error, Eq, PartialEq, Clone, Debug, Serialize, Deserialize, Hash)]
747pub enum SuiPastObjectResponseError {
748 #[error("Could not find the referenced object {object_id:?} at version {version:?}.")]
749 ObjectNotFound {
750 object_id: ObjectId,
751 version: Option<Version>,
752 },
753
754 #[error(
755 "Could not find the referenced object {object_id:?} \
756 as the asked version {asked_version:?} \
757 is higher than the latest {latest_version:?}"
758 )]
759 ObjectSequenceNumberTooHigh {
760 object_id: ObjectId,
761 asked_version: Version,
762 latest_version: Version,
763 },
764
765 #[error("Object deleted at reference {object_ref:?}.")]
766 ObjectDeleted { object_ref: ObjectRef },
767}
768
769#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
770#[serde(tag = "status", content = "details", rename = "ObjectRead")]
771pub enum SuiPastObjectResponse {
772 VersionFound(SuiObjectData),
774 ObjectNotExists(ObjectId),
776 ObjectDeleted(SuiObjectRef),
778 VersionNotFound(ObjectId, Version),
780 VersionTooHigh {
782 object_id: ObjectId,
783 asked_version: Version,
784 latest_version: Version,
785 },
786}
787
788impl SuiPastObjectResponse {
789 pub fn object(&self) -> Result<&SuiObjectData, SuiPastObjectResponseError> {
791 match &self {
792 Self::ObjectDeleted(oref) => Err(SuiPastObjectResponseError::ObjectDeleted {
793 object_ref: oref.to_object_ref(),
794 }),
795 Self::ObjectNotExists(id) => Err(SuiPastObjectResponseError::ObjectNotFound {
796 object_id: *id,
797 version: None,
798 }),
799 Self::VersionFound(o) => Ok(o),
800 Self::VersionNotFound(id, seq_num) => Err(SuiPastObjectResponseError::ObjectNotFound {
801 object_id: *id,
802 version: Some(*seq_num),
803 }),
804 Self::VersionTooHigh {
805 object_id,
806 asked_version,
807 latest_version,
808 } => Err(SuiPastObjectResponseError::ObjectSequenceNumberTooHigh {
809 object_id: *object_id,
810 asked_version: *asked_version,
811 latest_version: *latest_version,
812 }),
813 }
814 }
815
816 pub fn into_object(self) -> Result<SuiObjectData, SuiPastObjectResponseError> {
818 match self {
819 Self::ObjectDeleted(oref) => Err(SuiPastObjectResponseError::ObjectDeleted {
820 object_ref: oref.to_object_ref(),
821 }),
822 Self::ObjectNotExists(id) => Err(SuiPastObjectResponseError::ObjectNotFound {
823 object_id: id,
824 version: None,
825 }),
826 Self::VersionFound(o) => Ok(o),
827 Self::VersionNotFound(object_id, version) => {
828 Err(SuiPastObjectResponseError::ObjectNotFound {
829 object_id,
830 version: Some(version),
831 })
832 }
833 Self::VersionTooHigh {
834 object_id,
835 asked_version,
836 latest_version,
837 } => Err(SuiPastObjectResponseError::ObjectSequenceNumberTooHigh {
838 object_id,
839 asked_version,
840 latest_version,
841 }),
842 }
843 }
844}
845
846#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)]
847#[serde(rename = "MovePackage", rename_all = "camelCase")]
848pub struct SuiMovePackage {
849 pub disassembled: BTreeMap<String, Value>,
850}
851
852pub type QueryObjectsPage = Page<SuiObjectResponse, CheckpointedObjectId>;
853pub type ObjectsPage = Page<SuiObjectResponse, ObjectId>;
854
855#[serde_as]
856#[derive(Debug, Deserialize, Serialize, Clone, Copy, Eq, PartialEq)]
857#[serde(rename_all = "camelCase")]
858pub struct CheckpointedObjectId {
859 pub object_id: ObjectId,
860 #[serde_as(as = "Option<BigInt<u64>>")]
861 #[serde(skip_serializing_if = "Option::is_none")]
862 pub at_checkpoint: Option<Version>,
863}
864
865#[serde_as]
866#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)]
867#[serde(rename = "GetPastObjectRequest", rename_all = "camelCase")]
868pub struct SuiGetPastObjectRequest {
869 pub object_id: ObjectId,
871 #[serde_as(as = "BigInt<u64>")]
873 pub version: Version,
874}
875
876#[serde_as]
877#[derive(Clone, Debug, Serialize, Deserialize)]
878pub enum SuiObjectDataFilter {
879 MatchAll(Vec<SuiObjectDataFilter>),
880 MatchAny(Vec<SuiObjectDataFilter>),
881 MatchNone(Vec<SuiObjectDataFilter>),
882 Package(ObjectId),
884 MoveModule {
886 package: ObjectId,
888 #[serde_as(as = "DisplayFromStr")]
890 module: Identifier,
891 },
892 StructType(#[serde_as(as = "DisplayFromStr")] StructTag),
895 AddressOwner(SuiAddress),
896 ObjectOwner(ObjectId),
897 ObjectId(ObjectId),
898 ObjectIds(Vec<ObjectId>),
900 Version(#[serde_as(as = "BigInt<u64>")] u64),
901}
902
903impl SuiObjectDataFilter {
904 pub fn gas_coin() -> Self {
905 Self::StructType(StructTag::gas_coin())
906 }
907
908 pub fn and(self, other: Self) -> Self {
909 Self::MatchAll(vec![self, other])
910 }
911 pub fn or(self, other: Self) -> Self {
912 Self::MatchAny(vec![self, other])
913 }
914 pub fn not(self, other: Self) -> Self {
915 Self::MatchNone(vec![self, other])
916 }
917}
918
919#[derive(Debug, Clone, Deserialize, Serialize, Default)]
920#[serde(rename_all = "camelCase", rename = "ObjectResponseQuery", default)]
921pub struct SuiObjectResponseQuery {
922 pub filter: Option<SuiObjectDataFilter>,
924 pub options: Option<SuiObjectDataOptions>,
926}
927
928impl SuiObjectResponseQuery {
929 pub fn new(filter: Option<SuiObjectDataFilter>, options: Option<SuiObjectDataOptions>) -> Self {
930 Self { filter, options }
931 }
932
933 pub fn new_with_filter(filter: SuiObjectDataFilter) -> Self {
934 Self {
935 filter: Some(filter),
936 options: None,
937 }
938 }
939
940 pub fn new_with_options(options: SuiObjectDataOptions) -> Self {
941 Self {
942 filter: None,
943 options: Some(options),
944 }
945 }
946}