sui_rpc/proto/sui/rpc/v2beta2/
object.rs1use super::*;
2use crate::field::FieldMaskTree;
3use crate::merge::Merge;
4use crate::proto::TryFromProtoError;
5use tap::Pipe;
6
7pub const PACKAGE_TYPE: &str = "package";
12
13impl From<sui_sdk_types::Object> for Object {
14 fn from(value: sui_sdk_types::Object) -> Self {
15 Self::merge_from(value, &FieldMaskTree::new_wildcard())
16 }
17}
18
19impl Merge<&Object> for Object {
20 fn merge(&mut self, source: &Object, mask: &FieldMaskTree) {
21 let Object {
22 bcs,
23 object_id,
24 version,
25 digest,
26 owner,
27 object_type,
28 has_public_transfer,
29 contents,
30 package,
31 previous_transaction,
32 storage_rebate,
33 json,
34 balance,
35 } = source;
36
37 if mask.contains(Self::BCS_FIELD.name) {
38 self.bcs = bcs.clone();
39 }
40
41 if mask.contains(Self::DIGEST_FIELD.name) {
42 self.digest = digest.clone();
43 }
44
45 if mask.contains(Self::OBJECT_ID_FIELD.name) {
46 self.object_id = object_id.clone();
47 }
48
49 if mask.contains(Self::VERSION_FIELD.name) {
50 self.version = *version;
51 }
52
53 if mask.contains(Self::OWNER_FIELD.name) {
54 self.owner = owner.clone();
55 }
56
57 if mask.contains(Self::PREVIOUS_TRANSACTION_FIELD.name) {
58 self.previous_transaction = previous_transaction.clone();
59 }
60
61 if mask.contains(Self::STORAGE_REBATE_FIELD.name) {
62 self.storage_rebate = *storage_rebate;
63 }
64
65 if mask.contains(Self::OBJECT_TYPE_FIELD.name) {
66 self.object_type = object_type.clone();
67 }
68
69 if mask.contains(Self::HAS_PUBLIC_TRANSFER_FIELD.name) {
70 self.has_public_transfer = *has_public_transfer;
71 }
72
73 if mask.contains(Self::CONTENTS_FIELD.name) {
74 self.contents = contents.clone();
75 }
76
77 if mask.contains(Self::PACKAGE_FIELD.name) {
78 self.package = package.clone();
79 }
80
81 if mask.contains(Self::JSON_FIELD.name) {
82 self.json = json.clone();
83 }
84
85 if mask.contains(Self::BALANCE_FIELD) {
86 self.balance = *balance;
87 }
88 }
89}
90
91impl Merge<sui_sdk_types::Object> for Object {
92 fn merge(&mut self, source: sui_sdk_types::Object, mask: &FieldMaskTree) {
93 if mask.contains(Self::BCS_FIELD.name) {
94 let mut bcs = Bcs::serialize(&source).unwrap();
95 bcs.name = Some("Object".to_owned());
96 self.bcs = Some(bcs);
97 }
98
99 if mask.contains(Self::DIGEST_FIELD.name) {
100 self.digest = Some(source.digest().to_string());
101 }
102
103 if mask.contains(Self::OBJECT_ID_FIELD.name) {
104 self.object_id = Some(source.object_id().to_string());
105 }
106
107 if mask.contains(Self::VERSION_FIELD.name) {
108 self.version = Some(source.version());
109 }
110
111 if mask.contains(Self::OWNER_FIELD.name) {
112 self.owner = Some(source.owner().to_owned().into());
113 }
114
115 if mask.contains(Self::PREVIOUS_TRANSACTION_FIELD.name) {
116 self.previous_transaction = Some(source.previous_transaction().to_string());
117 }
118
119 if mask.contains(Self::STORAGE_REBATE_FIELD.name) {
120 self.storage_rebate = Some(source.storage_rebate());
121 }
122
123 match source.data() {
124 sui_sdk_types::ObjectData::Struct(move_struct) => {
125 self.merge(move_struct, mask);
126 }
127 sui_sdk_types::ObjectData::Package(move_package) => {
128 self.merge(move_package, mask);
129 }
130 }
131 }
132}
133
134impl Merge<&sui_sdk_types::MoveStruct> for Object {
135 fn merge(&mut self, source: &sui_sdk_types::MoveStruct, mask: &FieldMaskTree) {
136 if mask.contains(Self::OBJECT_TYPE_FIELD.name) {
137 self.object_type = Some(source.object_type().to_string());
138 }
139
140 if mask.contains(Self::HAS_PUBLIC_TRANSFER_FIELD.name) {
141 self.has_public_transfer = Some(source.has_public_transfer());
142 }
143
144 if mask.contains(Self::CONTENTS_FIELD.name) {
145 self.contents = Some(Bcs {
146 name: Some(source.object_type().to_string()),
147 value: Some(source.contents().to_vec().into()),
148 });
149 }
150 }
151}
152
153impl Merge<&sui_sdk_types::MovePackage> for Object {
154 fn merge(&mut self, source: &sui_sdk_types::MovePackage, mask: &FieldMaskTree) {
155 if mask.contains(Self::OBJECT_TYPE_FIELD.name) {
156 self.object_type = Some(PACKAGE_TYPE.to_owned());
157 }
158
159 if mask.contains(Self::PACKAGE_FIELD.name) {
160 self.package = Some(Package {
161 modules: source
162 .modules
163 .iter()
164 .map(|(name, contents)| Module {
165 name: Some(name.to_string()),
166 contents: Some(contents.clone().into()),
167 ..Default::default()
168 })
169 .collect(),
170 type_origins: source
171 .type_origin_table
172 .clone()
173 .into_iter()
174 .map(Into::into)
175 .collect(),
176 linkage: source
177 .linkage_table
178 .iter()
179 .map(
180 |(
181 original_id,
182 sui_sdk_types::UpgradeInfo {
183 upgraded_id,
184 upgraded_version,
185 },
186 )| {
187 Linkage {
188 original_id: Some(original_id.to_string()),
189 upgraded_id: Some(upgraded_id.to_string()),
190 upgraded_version: Some(*upgraded_version),
191 }
192 },
193 )
194 .collect(),
195
196 ..Default::default()
197 })
198 }
199 }
200}
201
202#[allow(clippy::result_large_err)]
203fn try_extract_struct(value: &Object) -> Result<sui_sdk_types::MoveStruct, TryFromProtoError> {
204 let version = value
205 .version
206 .ok_or_else(|| TryFromProtoError::missing("version"))?;
207
208 let object_type = value
209 .object_type()
210 .parse()
211 .map_err(|e| TryFromProtoError::invalid(Object::OBJECT_TYPE_FIELD, e))?;
212
213 let has_public_transfer = value
214 .has_public_transfer
215 .ok_or_else(|| TryFromProtoError::missing("has_public_transfer"))?;
216 let contents = value
217 .contents
218 .as_ref()
219 .ok_or_else(|| TryFromProtoError::missing("contents"))?
220 .value()
221 .to_vec();
222
223 sui_sdk_types::MoveStruct::new(object_type, has_public_transfer, version, contents).ok_or_else(
224 || TryFromProtoError::invalid(Object::CONTENTS_FIELD, "contents missing object_id"),
225 )
226}
227
228#[allow(clippy::result_large_err)]
229fn try_extract_package(value: &Object) -> Result<sui_sdk_types::MovePackage, TryFromProtoError> {
230 if value.object_type() != PACKAGE_TYPE {
231 return Err(TryFromProtoError::invalid(
232 Object::OBJECT_TYPE_FIELD,
233 format!(
234 "expected type {}, found {}",
235 PACKAGE_TYPE,
236 value.object_type()
237 ),
238 ));
239 }
240
241 let version = value
242 .version
243 .ok_or_else(|| TryFromProtoError::missing("version"))?;
244 let id = value
245 .object_id
246 .as_ref()
247 .ok_or_else(|| TryFromProtoError::missing("object_id"))?
248 .parse()
249 .map_err(|e| TryFromProtoError::invalid(Object::OBJECT_ID_FIELD, e))?;
250
251 let package = value
252 .package
253 .as_ref()
254 .ok_or_else(|| TryFromProtoError::missing("package"))?;
255 let modules = package
256 .modules
257 .iter()
258 .map(|module| {
259 let name = module
260 .name
261 .as_ref()
262 .ok_or_else(|| TryFromProtoError::missing("name"))?
263 .parse()
264 .map_err(|e| TryFromProtoError::invalid(Module::NAME_FIELD, e))?;
265
266 let contents = module
267 .contents
268 .as_ref()
269 .ok_or_else(|| TryFromProtoError::missing("contents"))?
270 .to_vec();
271
272 Ok((name, contents))
273 })
274 .collect::<Result<_, TryFromProtoError>>()?;
275
276 let type_origin_table = package
277 .type_origins
278 .iter()
279 .map(TryInto::try_into)
280 .collect::<Result<_, _>>()?;
281
282 let linkage_table = package
283 .linkage
284 .iter()
285 .map(|upgrade_info| {
286 let original_id = upgrade_info
287 .original_id
288 .as_ref()
289 .ok_or_else(|| TryFromProtoError::missing("original_id"))?
290 .parse()
291 .map_err(|e| TryFromProtoError::invalid(Linkage::ORIGINAL_ID_FIELD, e))?;
292
293 let upgraded_id = upgrade_info
294 .upgraded_id
295 .as_ref()
296 .ok_or_else(|| TryFromProtoError::missing("upgraded_id"))?
297 .parse()
298 .map_err(|e| TryFromProtoError::invalid(Linkage::UPGRADED_ID_FIELD, e))?;
299 let upgraded_version = upgrade_info
300 .upgraded_version
301 .ok_or_else(|| TryFromProtoError::missing("upgraded_version"))?;
302
303 Ok((
304 original_id,
305 sui_sdk_types::UpgradeInfo {
306 upgraded_id,
307 upgraded_version,
308 },
309 ))
310 })
311 .collect::<Result<_, TryFromProtoError>>()?;
312
313 Ok(sui_sdk_types::MovePackage {
314 id,
315 version,
316 modules,
317 type_origin_table,
318 linkage_table,
319 })
320}
321
322impl TryFrom<&Object> for sui_sdk_types::Object {
323 type Error = TryFromProtoError;
324
325 fn try_from(value: &Object) -> Result<Self, Self::Error> {
326 let owner = value
327 .owner
328 .as_ref()
329 .ok_or_else(|| TryFromProtoError::missing("owner"))?
330 .try_into()?;
331
332 let previous_transaction = value
333 .previous_transaction
334 .as_ref()
335 .ok_or_else(|| TryFromProtoError::missing("previous_transaction"))?
336 .parse()
337 .map_err(|e| TryFromProtoError::invalid(Object::PREVIOUS_TRANSACTION_FIELD, e))?;
338 let storage_rebate = value
339 .storage_rebate
340 .ok_or_else(|| TryFromProtoError::missing("storage_rebate"))?;
341
342 let object_data = if value.object_type() == PACKAGE_TYPE {
343 sui_sdk_types::ObjectData::Package(try_extract_package(value)?)
345 } else {
346 sui_sdk_types::ObjectData::Struct(try_extract_struct(value)?)
348 };
349
350 Ok(Self::new(
351 object_data,
352 owner,
353 previous_transaction,
354 storage_rebate,
355 ))
356 }
357}
358
359impl From<sui_sdk_types::TypeOrigin> for TypeOrigin {
364 fn from(value: sui_sdk_types::TypeOrigin) -> Self {
365 Self {
366 module_name: Some(value.module_name.to_string()),
367 datatype_name: Some(value.struct_name.to_string()),
368 package_id: Some(value.package.to_string()),
369 }
370 }
371}
372
373impl TryFrom<&TypeOrigin> for sui_sdk_types::TypeOrigin {
374 type Error = TryFromProtoError;
375
376 fn try_from(value: &TypeOrigin) -> Result<Self, Self::Error> {
377 let module_name = value
378 .module_name
379 .as_ref()
380 .ok_or_else(|| TryFromProtoError::missing("module_name"))?
381 .parse()
382 .map_err(|e| TryFromProtoError::invalid(TypeOrigin::MODULE_NAME_FIELD, e))?;
383
384 let struct_name = value
385 .datatype_name
386 .as_ref()
387 .ok_or_else(|| TryFromProtoError::missing("datatype_name"))?
388 .parse()
389 .map_err(|e| TryFromProtoError::invalid(TypeOrigin::DATATYPE_NAME_FIELD, e))?;
390
391 let package = value
392 .package_id
393 .as_ref()
394 .ok_or_else(|| TryFromProtoError::missing("package_id"))?
395 .parse()
396 .map_err(|e| TryFromProtoError::invalid(TypeOrigin::PACKAGE_ID_FIELD, e))?;
397
398 Ok(Self {
399 module_name,
400 struct_name,
401 package,
402 })
403 }
404}
405
406impl From<sui_sdk_types::GenesisObject> for Object {
411 fn from(value: sui_sdk_types::GenesisObject) -> Self {
412 let mut message = Self {
413 object_id: Some(value.object_id().to_string()),
414 version: Some(value.version()),
415 owner: Some(value.owner().to_owned().into()),
416 ..Default::default()
417 };
418
419 match value.data() {
420 sui_sdk_types::ObjectData::Struct(move_struct) => {
421 message.merge(move_struct, &FieldMaskTree::new_wildcard());
422 }
423 sui_sdk_types::ObjectData::Package(move_package) => {
424 message.merge(move_package, &FieldMaskTree::new_wildcard());
425 }
426 }
427
428 message
429 }
430}
431
432impl TryFrom<&Object> for sui_sdk_types::GenesisObject {
433 type Error = TryFromProtoError;
434
435 fn try_from(value: &Object) -> Result<Self, Self::Error> {
436 let object_data = if value.object_type() == PACKAGE_TYPE {
437 sui_sdk_types::ObjectData::Package(try_extract_package(value)?)
439 } else {
440 sui_sdk_types::ObjectData::Struct(try_extract_struct(value)?)
442 };
443
444 let owner = value
445 .owner
446 .as_ref()
447 .ok_or_else(|| TryFromProtoError::missing("owner"))?
448 .try_into()?;
449
450 Ok(Self::new(object_data, owner))
451 }
452}
453
454impl From<sui_sdk_types::ObjectReference> for ObjectReference {
459 fn from(value: sui_sdk_types::ObjectReference) -> Self {
460 let (object_id, version, digest) = value.into_parts();
461 Self {
462 object_id: Some(object_id.to_string()),
463 version: Some(version),
464 digest: Some(digest.to_string()),
465 }
466 }
467}
468
469impl TryFrom<&ObjectReference> for sui_sdk_types::ObjectReference {
470 type Error = TryFromProtoError;
471
472 fn try_from(value: &ObjectReference) -> Result<Self, Self::Error> {
473 let object_id = value
474 .object_id
475 .as_ref()
476 .ok_or_else(|| TryFromProtoError::missing("object_id"))?
477 .parse()
478 .map_err(|e| TryFromProtoError::invalid(ObjectReference::OBJECT_ID_FIELD, e))?;
479
480 let version = value
481 .version
482 .ok_or_else(|| TryFromProtoError::missing("version"))?;
483
484 let digest = value
485 .digest
486 .as_ref()
487 .ok_or_else(|| TryFromProtoError::missing("digest"))?
488 .parse()
489 .map_err(|e| TryFromProtoError::invalid(ObjectReference::DIGEST_FIELD, e))?;
490
491 Ok(Self::new(object_id, version, digest))
492 }
493}
494
495impl From<sui_sdk_types::Owner> for Owner {
500 fn from(value: sui_sdk_types::Owner) -> Self {
501 use owner::OwnerKind;
502 use sui_sdk_types::Owner::*;
503
504 let mut message = Self::default();
505
506 let kind = match value {
507 Address(address) => {
508 message.address = Some(address.to_string());
509 OwnerKind::Address
510 }
511 Object(object) => {
512 message.address = Some(object.to_string());
513 OwnerKind::Object
514 }
515 Shared(version) => {
516 message.version = Some(version);
517 OwnerKind::Shared
518 }
519 Immutable => OwnerKind::Immutable,
520 ConsensusAddress {
521 start_version,
522 owner,
523 } => {
524 message.version = Some(start_version);
525 message.address = Some(owner.to_string());
526 OwnerKind::ConsensusAddress
527 }
528 _ => OwnerKind::Unknown,
529 };
530
531 message.set_kind(kind);
532 message
533 }
534}
535
536impl TryFrom<&Owner> for sui_sdk_types::Owner {
537 type Error = TryFromProtoError;
538
539 fn try_from(value: &Owner) -> Result<Self, Self::Error> {
540 use owner::OwnerKind;
541
542 match value.kind() {
543 OwnerKind::Unknown => {
544 return Err(TryFromProtoError::invalid(
545 Owner::KIND_FIELD,
546 "unknown OwnerKind",
547 ))
548 }
549 OwnerKind::Address => Self::Address(
550 value
551 .address()
552 .parse()
553 .map_err(|e| TryFromProtoError::invalid(Owner::ADDRESS_FIELD, e))?,
554 ),
555 OwnerKind::Object => Self::Object(
556 value
557 .address()
558 .parse()
559 .map_err(|e| TryFromProtoError::invalid(Owner::ADDRESS_FIELD, e))?,
560 ),
561 OwnerKind::Shared => Self::Shared(value.version()),
562 OwnerKind::Immutable => Self::Immutable,
563 OwnerKind::ConsensusAddress => Self::ConsensusAddress {
564 start_version: value.version(),
565 owner: value
566 .address()
567 .parse()
568 .map_err(|e| TryFromProtoError::invalid(Owner::ADDRESS_FIELD, e))?,
569 },
570 }
571 .pipe(Ok)
572 }
573}