sui_rpc/proto/sui/rpc/v2beta2/
effects.rs

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