sui_rpc/proto/sui/rpc/v2/
effects.rs1use super::*;
2use crate::field::FieldMaskTree;
3use crate::merge::Merge;
4use crate::proto::TryFromProtoError;
5use tap::Pipe;
6
7impl From<sui_sdk_types::TransactionEffects> for TransactionEffects {
12 fn from(value: sui_sdk_types::TransactionEffects) -> Self {
13 Self::merge_from(&value, &FieldMaskTree::new_wildcard())
14 }
15}
16
17impl Merge<&sui_sdk_types::TransactionEffects> for TransactionEffects {
18 fn merge(&mut self, source: &sui_sdk_types::TransactionEffects, mask: &FieldMaskTree) {
19 if mask.contains(Self::BCS_FIELD.name) {
20 let mut bcs = Bcs::serialize(&source).unwrap();
21 bcs.name = Some("TransactionEffects".to_owned());
22 self.bcs = Some(bcs);
23 }
24
25 if mask.contains(Self::DIGEST_FIELD.name) {
26 self.digest = Some(source.digest().to_string());
27 }
28
29 match source {
30 sui_sdk_types::TransactionEffects::V1(v1) => self.merge(v1.as_ref(), mask),
31 sui_sdk_types::TransactionEffects::V2(v2) => self.merge(v2.as_ref(), mask),
32 }
33 }
34}
35
36impl Merge<&TransactionEffects> for TransactionEffects {
37 fn merge(
38 &mut self,
39 TransactionEffects {
40 bcs,
41 digest,
42 version,
43 status,
44 epoch,
45 gas_used,
46 transaction_digest,
47 gas_object,
48 events_digest,
49 dependencies,
50 lamport_version,
51 changed_objects,
52 unchanged_consensus_objects,
53 auxiliary_data_digest,
54 unchanged_loaded_runtime_objects,
55 }: &TransactionEffects,
56 mask: &FieldMaskTree,
57 ) {
58 if mask.contains(Self::BCS_FIELD.name) {
59 self.bcs = bcs.clone();
60 }
61
62 if mask.contains(Self::DIGEST_FIELD.name) {
63 self.digest = digest.clone();
64 }
65 if mask.contains(Self::VERSION_FIELD.name) {
66 self.version = *version;
67 }
68
69 if mask.contains(Self::STATUS_FIELD.name) {
70 self.status = status.clone();
71 }
72
73 if mask.contains(Self::EPOCH_FIELD.name) {
74 self.epoch = *epoch;
75 }
76
77 if mask.contains(Self::GAS_USED_FIELD.name) {
78 self.gas_used = *gas_used;
79 }
80
81 if mask.contains(Self::TRANSACTION_DIGEST_FIELD.name) {
82 self.transaction_digest = transaction_digest.clone();
83 }
84
85 if mask.contains(Self::GAS_OBJECT_FIELD.name) {
86 self.gas_object = gas_object.clone();
87 }
88
89 if mask.contains(Self::EVENTS_DIGEST_FIELD.name) {
90 self.events_digest = events_digest.clone();
91 }
92
93 if mask.contains(Self::DEPENDENCIES_FIELD.name) {
94 self.dependencies = dependencies.clone();
95 }
96
97 if mask.contains(Self::LAMPORT_VERSION_FIELD.name) {
98 self.lamport_version = *lamport_version;
99 }
100
101 if mask.contains(Self::CHANGED_OBJECTS_FIELD.name) {
102 self.changed_objects = changed_objects.clone();
103 }
104
105 if mask.contains(Self::UNCHANGED_CONSENSUS_OBJECTS_FIELD.name) {
106 self.unchanged_consensus_objects = unchanged_consensus_objects.clone();
107 }
108
109 if mask.contains(Self::AUXILIARY_DATA_DIGEST_FIELD.name) {
110 self.auxiliary_data_digest = auxiliary_data_digest.clone();
111 }
112
113 if mask.contains(Self::UNCHANGED_LOADED_RUNTIME_OBJECTS_FIELD.name) {
114 self.unchanged_loaded_runtime_objects = unchanged_loaded_runtime_objects.clone();
115 }
116 }
117}
118
119impl TryFrom<&TransactionEffects> for sui_sdk_types::TransactionEffects {
120 type Error = TryFromProtoError;
121
122 fn try_from(value: &TransactionEffects) -> Result<Self, Self::Error> {
123 value
124 .bcs
125 .as_ref()
126 .ok_or_else(|| TryFromProtoError::missing("bcs"))?
127 .deserialize()
128 .map_err(|e| TryFromProtoError::invalid(TransactionEffects::BCS_FIELD, e))
129 }
130}
131
132impl Merge<&sui_sdk_types::TransactionEffectsV1> for TransactionEffects {
137 fn merge(
138 &mut self,
139 sui_sdk_types::TransactionEffectsV1 {
140 status,
141 epoch,
142 gas_used,
143 modified_at_versions,
144 consensus_objects,
145 transaction_digest,
146 created,
147 mutated,
148 unwrapped,
149 deleted,
150 unwrapped_then_deleted,
151 wrapped,
152 gas_object,
153 events_digest,
154 dependencies,
155 }: &sui_sdk_types::TransactionEffectsV1,
156 mask: &FieldMaskTree,
157 ) {
158 if mask.contains(Self::VERSION_FIELD.name) {
159 self.version = Some(1);
160 }
161
162 if mask.contains(Self::STATUS_FIELD.name) {
163 self.status = Some(status.clone().into());
164 }
165
166 if mask.contains(Self::EPOCH_FIELD.name) {
167 self.epoch = Some(*epoch);
168 }
169
170 if mask.contains(Self::GAS_USED_FIELD.name) {
171 self.gas_used = Some(gas_used.clone().into());
172 }
173
174 if mask.contains(Self::TRANSACTION_DIGEST_FIELD.name) {
175 self.transaction_digest = Some(transaction_digest.to_string());
176 }
177
178 if mask.contains(Self::EVENTS_DIGEST_FIELD.name) {
179 self.events_digest = events_digest.map(|d| d.to_string());
180 }
181
182 if mask.contains(Self::DEPENDENCIES_FIELD.name) {
183 self.dependencies = dependencies.iter().map(ToString::to_string).collect();
184 }
185
186 if mask.contains(Self::CHANGED_OBJECTS_FIELD.name)
187 || mask.contains(Self::UNCHANGED_CONSENSUS_OBJECTS_FIELD.name)
188 || mask.contains(Self::GAS_OBJECT_FIELD.name)
189 {
190 let mut changed_objects = Vec::new();
191 let mut unchanged_consensus_objects = Vec::new();
192
193 for object in created {
194 let change = ChangedObject {
195 object_id: Some(object.reference.object_id().to_string()),
196 input_state: Some(changed_object::InputObjectState::DoesNotExist.into()),
197 input_version: None,
198 input_digest: None,
199 input_owner: None,
200 output_state: Some(changed_object::OutputObjectState::ObjectWrite.into()),
201 output_version: Some(object.reference.version()),
202 output_digest: Some(object.reference.digest().to_string()),
203 output_owner: Some(object.owner.into()),
204 id_operation: Some(changed_object::IdOperation::Created.into()),
205 object_type: None,
206 accumulator_write: None,
207 };
208
209 changed_objects.push(change);
210 }
211
212 for object in mutated {
213 let change = ChangedObject {
214 object_id: Some(object.reference.object_id().to_string()),
215 input_state: Some(changed_object::InputObjectState::Exists.into()),
216 input_version: None,
217 input_digest: None,
218 input_owner: None,
219 output_state: Some(changed_object::OutputObjectState::ObjectWrite.into()),
220 output_version: Some(object.reference.version()),
221 output_digest: Some(object.reference.digest().to_string()),
222 output_owner: Some(object.owner.into()),
223 id_operation: Some(changed_object::IdOperation::None.into()),
224 object_type: None,
225 accumulator_write: None,
226 };
227
228 changed_objects.push(change);
229 }
230
231 for object in unwrapped {
232 let change = ChangedObject {
233 object_id: Some(object.reference.object_id().to_string()),
234 input_state: Some(changed_object::InputObjectState::DoesNotExist.into()),
235 input_version: None,
236 input_digest: None,
237 input_owner: None,
238 output_state: Some(changed_object::OutputObjectState::ObjectWrite.into()),
239 output_version: Some(object.reference.version()),
240 output_digest: Some(object.reference.digest().to_string()),
241 output_owner: Some(object.owner.into()),
242 id_operation: Some(changed_object::IdOperation::None.into()),
243 object_type: None,
244 accumulator_write: None,
245 };
246
247 changed_objects.push(change);
248 }
249
250 for object in deleted {
251 let change = ChangedObject {
252 object_id: Some(object.object_id().to_string()),
253 input_state: Some(changed_object::InputObjectState::Exists.into()),
254 input_version: None,
255 input_digest: None,
256 input_owner: None,
257 output_state: Some(changed_object::OutputObjectState::DoesNotExist.into()),
258 output_version: Some(object.version()),
259 output_digest: Some(object.digest().to_string()),
260 output_owner: None,
261 id_operation: Some(changed_object::IdOperation::Deleted.into()),
262 object_type: None,
263 accumulator_write: None,
264 };
265
266 changed_objects.push(change);
267 }
268
269 for object in unwrapped_then_deleted {
270 let change = ChangedObject {
271 object_id: Some(object.object_id().to_string()),
272 input_state: Some(changed_object::InputObjectState::DoesNotExist.into()),
273 input_version: None,
274 input_digest: None,
275 input_owner: None,
276 output_state: Some(changed_object::OutputObjectState::DoesNotExist.into()),
277 output_version: Some(object.version()),
278 output_digest: Some(object.digest().to_string()),
279 output_owner: None,
280 id_operation: Some(changed_object::IdOperation::Deleted.into()),
281 object_type: None,
282 accumulator_write: None,
283 };
284
285 changed_objects.push(change);
286 }
287
288 for object in wrapped {
289 let change = ChangedObject {
290 object_id: Some(object.object_id().to_string()),
291 input_state: Some(changed_object::InputObjectState::Exists.into()),
292 input_version: None,
293 input_digest: None,
294 input_owner: None,
295 output_state: Some(changed_object::OutputObjectState::DoesNotExist.into()),
296 output_version: Some(object.version()),
297 output_digest: Some(object.digest().to_string()),
298 output_owner: None,
299 id_operation: Some(changed_object::IdOperation::Deleted.into()),
300 object_type: None,
301 accumulator_write: None,
302 };
303
304 changed_objects.push(change);
305 }
306
307 for modified_at_version in modified_at_versions {
308 let object_id = modified_at_version.object_id.to_string();
309 let version = modified_at_version.version;
310 if let Some(changed_object) = changed_objects
311 .iter_mut()
312 .find(|object| object.object_id() == object_id)
313 {
314 changed_object.input_version = Some(version);
315 }
316 }
317
318 for object in consensus_objects {
319 let object_id = object.object_id().to_string();
320 let version = object.version();
321 let digest = object.digest().to_string();
322
323 if let Some(changed_object) = changed_objects
324 .iter_mut()
325 .find(|object| object.object_id() == object_id)
326 {
327 changed_object.input_version = Some(version);
328 changed_object.input_digest = Some(digest);
329 } else {
330 let unchanged_consensus_object = UnchangedConsensusObject {
331 kind: Some(
332 unchanged_consensus_object::UnchangedConsensusObjectKind::ReadOnlyRoot
333 .into(),
334 ),
335 object_id: Some(object_id),
336 version: Some(version),
337 digest: Some(digest),
338 object_type: None,
339 };
340
341 unchanged_consensus_objects.push(unchanged_consensus_object);
342 }
343 }
344
345 if mask.contains(Self::GAS_OBJECT_FIELD.name) {
346 let gas_object_id = gas_object.reference.object_id().to_string();
347 self.gas_object = changed_objects
348 .iter()
349 .find(|object| object.object_id() == gas_object_id)
350 .cloned();
351 }
352
353 if mask.contains(Self::CHANGED_OBJECTS_FIELD.name) {
354 self.changed_objects = changed_objects;
355 }
356
357 if mask.contains(Self::UNCHANGED_CONSENSUS_OBJECTS_FIELD.name) {
358 self.unchanged_consensus_objects = unchanged_consensus_objects;
359 }
360 }
361 }
362}
363
364impl Merge<&sui_sdk_types::TransactionEffectsV2> for TransactionEffects {
369 fn merge(
370 &mut self,
371 sui_sdk_types::TransactionEffectsV2 {
372 status,
373 epoch,
374 gas_used,
375 transaction_digest,
376 gas_object_index,
377 events_digest,
378 dependencies,
379 lamport_version,
380 changed_objects,
381 unchanged_consensus_objects,
382 auxiliary_data_digest,
383 }: &sui_sdk_types::TransactionEffectsV2,
384 mask: &FieldMaskTree,
385 ) {
386 if mask.contains(Self::VERSION_FIELD.name) {
387 self.version = Some(2);
388 }
389
390 if mask.contains(Self::STATUS_FIELD.name) {
391 self.status = Some(status.clone().into());
392 }
393
394 if mask.contains(Self::EPOCH_FIELD.name) {
395 self.epoch = Some(*epoch);
396 }
397
398 if mask.contains(Self::GAS_USED_FIELD.name) {
399 self.gas_used = Some(gas_used.clone().into());
400 }
401
402 if mask.contains(Self::TRANSACTION_DIGEST_FIELD.name) {
403 self.transaction_digest = Some(transaction_digest.to_string());
404 }
405
406 if mask.contains(Self::GAS_OBJECT_FIELD.name) {
407 self.gas_object = gas_object_index
408 .map(|index| changed_objects.get(index as usize).cloned().map(Into::into))
409 .flatten();
410 }
411
412 if mask.contains(Self::EVENTS_DIGEST_FIELD.name) {
413 self.events_digest = events_digest.map(|d| d.to_string());
414 }
415
416 if mask.contains(Self::DEPENDENCIES_FIELD.name) {
417 self.dependencies = dependencies.iter().map(ToString::to_string).collect();
418 }
419
420 if mask.contains(Self::LAMPORT_VERSION_FIELD.name) {
421 self.lamport_version = Some(*lamport_version);
422 }
423
424 if mask.contains(Self::CHANGED_OBJECTS_FIELD.name) {
425 self.changed_objects = changed_objects
426 .clone()
427 .into_iter()
428 .map(Into::into)
429 .collect();
430 }
431
432 for object in self.changed_objects.iter_mut().chain(&mut self.gas_object) {
433 if object.output_digest.is_some() && object.output_version.is_none() {
434 object.output_version = Some(*lamport_version);
435 }
436 }
437
438 if mask.contains(Self::UNCHANGED_CONSENSUS_OBJECTS_FIELD.name) {
439 self.unchanged_consensus_objects = unchanged_consensus_objects
440 .clone()
441 .into_iter()
442 .map(Into::into)
443 .collect();
444 }
445
446 if mask.contains(Self::AUXILIARY_DATA_DIGEST_FIELD.name) {
447 self.auxiliary_data_digest = auxiliary_data_digest.map(|d| d.to_string());
448 }
449 }
450}
451
452impl From<sui_sdk_types::ChangedObject> for ChangedObject {
457 fn from(value: sui_sdk_types::ChangedObject) -> Self {
458 use changed_object::InputObjectState;
459 use changed_object::OutputObjectState;
460
461 let mut message = Self {
462 object_id: Some(value.object_id.to_string()),
463 ..Default::default()
464 };
465
466 let input_state = match value.input_state {
468 sui_sdk_types::ObjectIn::NotExist => InputObjectState::DoesNotExist,
469 sui_sdk_types::ObjectIn::Exist {
470 version,
471 digest,
472 owner,
473 } => {
474 message.input_version = Some(version);
475 message.input_digest = Some(digest.to_string());
476 message.input_owner = Some(owner.into());
477 InputObjectState::Exists
478 }
479 _ => InputObjectState::Unknown,
480 };
481 message.set_input_state(input_state);
482
483 let output_state = match value.output_state {
485 sui_sdk_types::ObjectOut::NotExist => OutputObjectState::DoesNotExist,
486 sui_sdk_types::ObjectOut::ObjectWrite { digest, owner } => {
487 message.output_digest = Some(digest.to_string());
488 message.output_owner = Some(owner.into());
489 OutputObjectState::ObjectWrite
490 }
491 sui_sdk_types::ObjectOut::PackageWrite { version, digest } => {
492 message.output_version = Some(version);
493 message.output_digest = Some(digest.to_string());
494 OutputObjectState::PackageWrite
495 }
496 sui_sdk_types::ObjectOut::AccumulatorWrite(accumulator_write) => {
497 message.set_accumulator_write(accumulator_write);
498 OutputObjectState::AccumulatorWrite
499 }
500 _ => OutputObjectState::Unknown,
501 };
502 message.set_output_state(output_state);
503
504 message.set_id_operation(value.id_operation.into());
505 message
506 }
507}
508
509impl TryFrom<&ChangedObject> for sui_sdk_types::ChangedObject {
510 type Error = TryFromProtoError;
511
512 fn try_from(value: &ChangedObject) -> Result<Self, Self::Error> {
513 use changed_object::InputObjectState;
514 use changed_object::OutputObjectState;
515
516 let object_id = value
517 .object_id
518 .as_ref()
519 .ok_or_else(|| TryFromProtoError::missing("object_id"))?
520 .parse()
521 .map_err(|e| TryFromProtoError::invalid(ChangedObject::OBJECT_ID_FIELD, e))?;
522
523 let input_state = match value.input_state() {
524 InputObjectState::Unknown => {
525 return Err(TryFromProtoError::invalid(
526 ChangedObject::INPUT_STATE_FIELD,
527 "unknown InputObjectState",
528 ));
529 }
530 InputObjectState::DoesNotExist => sui_sdk_types::ObjectIn::NotExist,
531 InputObjectState::Exists => sui_sdk_types::ObjectIn::Exist {
532 version: value
533 .input_version
534 .ok_or_else(|| TryFromProtoError::missing("version"))?,
535 digest: value
536 .input_digest
537 .as_ref()
538 .ok_or_else(|| TryFromProtoError::missing("digest"))?
539 .parse()
540 .map_err(|e| {
541 TryFromProtoError::invalid(ChangedObject::INPUT_DIGEST_FIELD, e)
542 })?,
543 owner: value
544 .input_owner
545 .as_ref()
546 .ok_or_else(|| TryFromProtoError::missing("owner"))?
547 .try_into()?,
548 },
549 };
550
551 let output_state = match value.output_state() {
552 OutputObjectState::Unknown => {
553 return Err(TryFromProtoError::invalid(
554 ChangedObject::OUTPUT_STATE_FIELD,
555 "unknown OutputObjectState",
556 ));
557 }
558 OutputObjectState::DoesNotExist => sui_sdk_types::ObjectOut::NotExist,
559 OutputObjectState::ObjectWrite => sui_sdk_types::ObjectOut::ObjectWrite {
560 digest: value
561 .output_digest
562 .as_ref()
563 .ok_or_else(|| TryFromProtoError::missing("digest"))?
564 .parse()
565 .map_err(|e| {
566 TryFromProtoError::invalid(ChangedObject::OUTPUT_DIGEST_FIELD, e)
567 })?,
568
569 owner: value
570 .output_owner
571 .as_ref()
572 .ok_or_else(|| TryFromProtoError::missing("owner"))?
573 .try_into()?,
574 },
575 OutputObjectState::PackageWrite => sui_sdk_types::ObjectOut::PackageWrite {
576 version: value
577 .output_version
578 .ok_or_else(|| TryFromProtoError::missing("version"))?,
579 digest: value
580 .output_digest
581 .as_ref()
582 .ok_or_else(|| TryFromProtoError::missing("digest"))?
583 .parse()
584 .map_err(|e| {
585 TryFromProtoError::invalid(ChangedObject::OUTPUT_DIGEST_FIELD, e)
586 })?,
587 },
588 OutputObjectState::AccumulatorWrite => sui_sdk_types::ObjectOut::AccumulatorWrite(
589 value
590 .accumulator_write_opt()
591 .ok_or_else(|| TryFromProtoError::missing("accumulator_write"))?
592 .try_into()?,
593 ),
594 };
595
596 let id_operation = value.id_operation().try_into()?;
597
598 Ok(Self {
599 object_id,
600 input_state,
601 output_state,
602 id_operation,
603 })
604 }
605}
606
607impl From<sui_sdk_types::IdOperation> for changed_object::IdOperation {
612 fn from(value: sui_sdk_types::IdOperation) -> Self {
613 use sui_sdk_types::IdOperation::*;
614
615 match value {
616 None => Self::None,
617 Created => Self::Created,
618 Deleted => Self::Deleted,
619 _ => Self::Unknown,
620 }
621 }
622}
623
624impl TryFrom<changed_object::IdOperation> for sui_sdk_types::IdOperation {
625 type Error = TryFromProtoError;
626
627 fn try_from(value: changed_object::IdOperation) -> Result<Self, Self::Error> {
628 use changed_object::IdOperation;
629
630 match value {
631 IdOperation::Unknown => {
632 return Err(TryFromProtoError::invalid(
633 "id_operation",
634 "unknown IdOperation",
635 ));
636 }
637 IdOperation::None => Self::None,
638 IdOperation::Created => Self::Created,
639 IdOperation::Deleted => Self::Deleted,
640 }
641 .pipe(Ok)
642 }
643}
644
645impl From<sui_sdk_types::AccumulatorWrite> for AccumulatorWrite {
650 fn from(value: sui_sdk_types::AccumulatorWrite) -> Self {
651 use accumulator_write::AccumulatorOperation;
652
653 let mut message = Self::default();
654
655 message.set_address(value.address());
656 message.set_accumulator_type(value.accumulator_type());
657
658 message.set_operation(match value.operation() {
659 sui_sdk_types::AccumulatorOperation::Merge => AccumulatorOperation::Merge,
660 sui_sdk_types::AccumulatorOperation::Split => AccumulatorOperation::Split,
661 _ => AccumulatorOperation::Unknown,
662 });
663
664 message.set_value(value.value());
665
666 message
667 }
668}
669
670impl TryFrom<&AccumulatorWrite> for sui_sdk_types::AccumulatorWrite {
671 type Error = TryFromProtoError;
672
673 fn try_from(value: &AccumulatorWrite) -> Result<Self, Self::Error> {
674 let address = value
675 .address_opt()
676 .ok_or_else(|| TryFromProtoError::missing("address"))?
677 .parse()
678 .map_err(|e| TryFromProtoError::invalid("address", e))?;
679 let accumulator_type = value
680 .accumulator_type_opt()
681 .ok_or_else(|| TryFromProtoError::missing("accumulator_type"))?
682 .parse()
683 .map_err(|e| TryFromProtoError::invalid("accumulator_type", e))?;
684
685 let operation = match value.operation() {
686 accumulator_write::AccumulatorOperation::Unknown => {
687 return Err(TryFromProtoError::invalid("operation", "unknown operation"));
688 }
689 accumulator_write::AccumulatorOperation::Merge => {
690 sui_sdk_types::AccumulatorOperation::Merge
691 }
692 accumulator_write::AccumulatorOperation::Split => {
693 sui_sdk_types::AccumulatorOperation::Split
694 }
695 };
696
697 let value = value
698 .value_opt()
699 .ok_or_else(|| TryFromProtoError::missing("value"))?;
700
701 Ok(Self::new(address, accumulator_type, operation, value))
702 }
703}
704
705impl From<sui_sdk_types::UnchangedConsensusObject> for UnchangedConsensusObject {
710 fn from(value: sui_sdk_types::UnchangedConsensusObject) -> Self {
711 use sui_sdk_types::UnchangedConsensusKind::*;
712 use unchanged_consensus_object::UnchangedConsensusObjectKind;
713
714 let mut message = Self {
715 object_id: Some(value.object_id.to_string()),
716 ..Default::default()
717 };
718
719 let kind = match value.kind {
720 ReadOnlyRoot { version, digest } => {
721 message.version = Some(version);
722 message.digest = Some(digest.to_string());
723 UnchangedConsensusObjectKind::ReadOnlyRoot
724 }
725 MutateDeleted { version } => {
726 message.version = Some(version);
727 UnchangedConsensusObjectKind::MutateConsensusStreamEnded
728 }
729 ReadDeleted { version } => {
730 message.version = Some(version);
731 UnchangedConsensusObjectKind::ReadConsensusStreamEnded
732 }
733 Canceled { version } => {
734 message.version = Some(version);
735 UnchangedConsensusObjectKind::Canceled
736 }
737 PerEpochConfig => UnchangedConsensusObjectKind::PerEpochConfig,
738 _ => UnchangedConsensusObjectKind::Unknown,
739 };
740
741 message.set_kind(kind);
742 message
743 }
744}
745
746impl TryFrom<&UnchangedConsensusObject> for sui_sdk_types::UnchangedConsensusObject {
747 type Error = TryFromProtoError;
748
749 fn try_from(value: &UnchangedConsensusObject) -> Result<Self, Self::Error> {
750 use sui_sdk_types::UnchangedConsensusKind;
751 use unchanged_consensus_object::UnchangedConsensusObjectKind;
752
753 let object_id = value
754 .object_id
755 .as_ref()
756 .ok_or_else(|| TryFromProtoError::missing("object_id"))?
757 .parse()
758 .map_err(|e| {
759 TryFromProtoError::invalid(UnchangedConsensusObject::OBJECT_ID_FIELD, e)
760 })?;
761
762 let kind = match value.kind() {
763 UnchangedConsensusObjectKind::Unknown => {
764 return Err(TryFromProtoError::invalid(
765 UnchangedConsensusObject::KIND_FIELD,
766 "unknown InputKind",
767 ));
768 }
769
770 UnchangedConsensusObjectKind::ReadOnlyRoot => UnchangedConsensusKind::ReadOnlyRoot {
771 version: value
772 .version
773 .ok_or_else(|| TryFromProtoError::missing("version"))?,
774
775 digest: value
776 .digest
777 .as_ref()
778 .ok_or_else(|| TryFromProtoError::missing("digest"))?
779 .parse()
780 .map_err(|e| {
781 TryFromProtoError::invalid(UnchangedConsensusObject::DIGEST_FIELD, e)
782 })?,
783 },
784 UnchangedConsensusObjectKind::MutateConsensusStreamEnded => {
785 UnchangedConsensusKind::MutateDeleted {
786 version: value
787 .version
788 .ok_or_else(|| TryFromProtoError::missing("version"))?,
789 }
790 }
791 UnchangedConsensusObjectKind::ReadConsensusStreamEnded => {
792 UnchangedConsensusKind::ReadDeleted {
793 version: value
794 .version
795 .ok_or_else(|| TryFromProtoError::missing("version"))?,
796 }
797 }
798 UnchangedConsensusObjectKind::Canceled => UnchangedConsensusKind::Canceled {
799 version: value
800 .version
801 .ok_or_else(|| TryFromProtoError::missing("version"))?,
802 },
803 UnchangedConsensusObjectKind::PerEpochConfig => UnchangedConsensusKind::PerEpochConfig,
804 };
805
806 Ok(Self { object_id, kind })
807 }
808}