sui_types/
rpc_proto_conversions.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4//! Module for conversions from sui-core types to rpc protos
5
6use crate::crypto::SuiSignature;
7
8fn ms_to_timestamp(ms: u64) -> prost_types::Timestamp {
9    prost_types::Timestamp {
10        seconds: (ms / 1000) as _,
11        nanos: ((ms % 1000) * 1_000_000) as _,
12    }
13}
14
15fn timestamp_to_ms(timestamp: &prost_types::Timestamp) -> Result<u64, &'static str> {
16    let seconds: u64 = timestamp
17        .seconds
18        .try_into()
19        .map_err(|_| "invalid timestamp: negative seconds")?;
20    let nanos: u64 = timestamp
21        .nanos
22        .try_into()
23        .map_err(|_| "invalid timestamp: negative nanos")?;
24    seconds
25        .checked_mul(1000)
26        .and_then(|ms| ms.checked_add(nanos / 1_000_000))
27        .ok_or("invalid timestamp: out of range")
28}
29use crate::message_envelope::Message as _;
30use fastcrypto::traits::ToFromBytes;
31use sui_rpc::field::FieldMaskTree;
32use sui_rpc::merge::Merge;
33use sui_rpc::proto::TryFromProtoError;
34use sui_rpc::proto::sui::rpc::v2::*;
35
36//
37// CheckpointSummary
38//
39
40impl Merge<&crate::full_checkpoint_content::Checkpoint> for Checkpoint {
41    fn merge(&mut self, source: &crate::full_checkpoint_content::Checkpoint, mask: &FieldMaskTree) {
42        let sequence_number = source.summary.sequence_number;
43        let timestamp_ms = source.summary.timestamp_ms;
44
45        let summary = source.summary.data();
46        let signature = source.summary.auth_sig();
47
48        self.merge(summary, mask);
49        self.merge(signature.clone(), mask);
50
51        if mask.contains(Checkpoint::CONTENTS_FIELD.name) {
52            self.merge(&source.contents, mask);
53        }
54
55        if let Some(submask) = mask
56            .subtree(Checkpoint::OBJECTS_FIELD)
57            .and_then(|submask| submask.subtree(ObjectSet::OBJECTS_FIELD))
58        {
59            let set = source
60                .object_set
61                .iter()
62                .map(|o| sui_rpc::proto::sui::rpc::v2::Object::merge_from(o, &submask))
63                .collect();
64            self.objects = Some(ObjectSet::default().with_objects(set));
65        }
66
67        if let Some(submask) = mask.subtree(Checkpoint::TRANSACTIONS_FIELD.name) {
68            self.transactions = source
69                .transactions
70                .iter()
71                .map(|t| {
72                    let mut transaction = ExecutedTransaction::merge_from(t, &submask);
73                    transaction.checkpoint = submask
74                        .contains(ExecutedTransaction::CHECKPOINT_FIELD)
75                        .then_some(sequence_number);
76                    transaction.timestamp = submask
77                        .contains(ExecutedTransaction::TIMESTAMP_FIELD)
78                        .then(|| sui_rpc::proto::timestamp_ms_to_proto(timestamp_ms));
79                    transaction
80                })
81                .collect();
82        }
83    }
84}
85
86impl Merge<&crate::full_checkpoint_content::ExecutedTransaction> for ExecutedTransaction {
87    fn merge(
88        &mut self,
89        source: &crate::full_checkpoint_content::ExecutedTransaction,
90        mask: &FieldMaskTree,
91    ) {
92        if mask.contains(ExecutedTransaction::DIGEST_FIELD) {
93            self.digest = Some(source.transaction.digest().to_string());
94        }
95
96        if let Some(submask) = mask.subtree(ExecutedTransaction::TRANSACTION_FIELD) {
97            self.transaction = Some(Transaction::merge_from(&source.transaction, &submask));
98        }
99
100        if let Some(submask) = mask.subtree(ExecutedTransaction::SIGNATURES_FIELD) {
101            self.signatures = source
102                .signatures
103                .iter()
104                .map(|s| UserSignature::merge_from(s, &submask))
105                .collect();
106        }
107
108        if let Some(submask) = mask.subtree(ExecutedTransaction::EFFECTS_FIELD) {
109            let mut effects = TransactionEffects::merge_from(&source.effects, &submask);
110            if submask.contains(TransactionEffects::UNCHANGED_LOADED_RUNTIME_OBJECTS_FIELD) {
111                effects.set_unchanged_loaded_runtime_objects(
112                    source
113                        .unchanged_loaded_runtime_objects
114                        .iter()
115                        .map(Into::into)
116                        .collect(),
117                );
118            }
119            self.effects = Some(effects);
120        }
121
122        if let Some(submask) = mask.subtree(ExecutedTransaction::EVENTS_FIELD) {
123            self.events = source
124                .events
125                .as_ref()
126                .map(|events| TransactionEvents::merge_from(events, &submask));
127        }
128    }
129}
130
131impl TryFrom<&Checkpoint> for crate::full_checkpoint_content::Checkpoint {
132    type Error = TryFromProtoError;
133
134    fn try_from(checkpoint: &Checkpoint) -> Result<Self, Self::Error> {
135        let summary = checkpoint
136            .summary()
137            .bcs()
138            .deserialize()
139            .map_err(|e| TryFromProtoError::invalid("summary.bcs", e))?;
140
141        let signature =
142            crate::crypto::AuthorityStrongQuorumSignInfo::try_from(checkpoint.signature())?;
143
144        let summary = crate::messages_checkpoint::CertifiedCheckpointSummary::new_from_data_and_sig(
145            summary, signature,
146        );
147
148        let contents: crate::messages_checkpoint::CheckpointContents = checkpoint
149            .contents()
150            .bcs()
151            .deserialize()
152            .map_err(|e| TryFromProtoError::invalid("contents.bcs", e))?;
153
154        let user_signatures: Vec<_> = contents
155            .clone()
156            .into_iter_with_signatures()
157            .map(|(_, user_signatures)| user_signatures)
158            .collect();
159
160        #[allow(clippy::disallowed_methods)]
161        // Intentional zip: transactions field may be partially populated via field masks
162        let transactions = checkpoint
163            .transactions()
164            .iter()
165            .zip(user_signatures)
166            .map(|(tx, user_signatures)| {
167                let mut executed_tx: crate::full_checkpoint_content::ExecutedTransaction =
168                    tx.try_into()?;
169                executed_tx.signatures = user_signatures;
170                Ok(executed_tx)
171            })
172            .collect::<Result<_, TryFromProtoError>>()?;
173
174        let object_set = checkpoint.objects().try_into()?;
175
176        Ok(Self {
177            summary,
178            contents,
179            transactions,
180            object_set,
181        })
182    }
183}
184
185impl TryFrom<&ExecutedTransaction> for crate::full_checkpoint_content::ExecutedTransaction {
186    type Error = TryFromProtoError;
187
188    fn try_from(value: &ExecutedTransaction) -> Result<Self, Self::Error> {
189        Ok(Self {
190            transaction: value
191                .transaction()
192                .bcs()
193                .deserialize()
194                .map_err(|e| TryFromProtoError::invalid("transaction.bcs", e))?,
195            signatures: value
196                .signatures()
197                .iter()
198                .map(|sig| {
199                    crate::signature::GenericSignature::from_bytes(sig.bcs().value())
200                        .map_err(|e| TryFromProtoError::invalid("signature.bcs", e))
201                })
202                .collect::<Result<_, _>>()?,
203            effects: value
204                .effects()
205                .bcs()
206                .deserialize()
207                .map_err(|e| TryFromProtoError::invalid("effects.bcs", e))?,
208            events: value
209                .events_opt()
210                .map(|events| {
211                    events
212                        .bcs()
213                        .deserialize()
214                        .map_err(|e| TryFromProtoError::invalid("effects.bcs", e))
215                })
216                .transpose()?,
217            unchanged_loaded_runtime_objects: value
218                .effects()
219                .unchanged_loaded_runtime_objects()
220                .iter()
221                .map(TryInto::try_into)
222                .collect::<Result<_, _>>()?,
223        })
224    }
225}
226
227impl TryFrom<&ObjectReference> for crate::storage::ObjectKey {
228    type Error = TryFromProtoError;
229
230    fn try_from(value: &ObjectReference) -> Result<Self, Self::Error> {
231        Ok(Self(
232            value
233                .object_id()
234                .parse()
235                .map_err(|e| TryFromProtoError::invalid("object_id", e))?,
236            value.version().into(),
237        ))
238    }
239}
240
241//
242// CheckpointSummary
243//
244
245impl From<crate::messages_checkpoint::CheckpointSummary> for CheckpointSummary {
246    fn from(summary: crate::messages_checkpoint::CheckpointSummary) -> Self {
247        Self::merge_from(summary, &FieldMaskTree::new_wildcard())
248    }
249}
250
251impl Merge<crate::messages_checkpoint::CheckpointSummary> for CheckpointSummary {
252    fn merge(
253        &mut self,
254        source: crate::messages_checkpoint::CheckpointSummary,
255        mask: &FieldMaskTree,
256    ) {
257        if mask.contains(Self::BCS_FIELD) {
258            let mut bcs = Bcs::serialize(&source).unwrap();
259            bcs.name = Some("CheckpointSummary".to_owned());
260            self.bcs = Some(bcs);
261        }
262
263        if mask.contains(Self::DIGEST_FIELD) {
264            self.digest = Some(source.digest().to_string());
265        }
266
267        let crate::messages_checkpoint::CheckpointSummary {
268            epoch,
269            sequence_number,
270            network_total_transactions,
271            content_digest,
272            previous_digest,
273            epoch_rolling_gas_cost_summary,
274            timestamp_ms,
275            checkpoint_commitments,
276            end_of_epoch_data,
277            version_specific_data,
278        } = source;
279
280        if mask.contains(Self::EPOCH_FIELD) {
281            self.epoch = Some(epoch);
282        }
283
284        if mask.contains(Self::SEQUENCE_NUMBER_FIELD) {
285            self.sequence_number = Some(sequence_number);
286        }
287
288        if mask.contains(Self::TOTAL_NETWORK_TRANSACTIONS_FIELD) {
289            self.total_network_transactions = Some(network_total_transactions);
290        }
291
292        if mask.contains(Self::CONTENT_DIGEST_FIELD) {
293            self.content_digest = Some(content_digest.to_string());
294        }
295
296        if mask.contains(Self::PREVIOUS_DIGEST_FIELD) {
297            self.previous_digest = previous_digest.map(|d| d.to_string());
298        }
299
300        if mask.contains(Self::EPOCH_ROLLING_GAS_COST_SUMMARY_FIELD) {
301            self.epoch_rolling_gas_cost_summary = Some(epoch_rolling_gas_cost_summary.into());
302        }
303
304        if mask.contains(Self::TIMESTAMP_FIELD) {
305            self.timestamp = Some(sui_rpc::proto::timestamp_ms_to_proto(timestamp_ms));
306        }
307
308        if mask.contains(Self::COMMITMENTS_FIELD) {
309            self.commitments = checkpoint_commitments.into_iter().map(Into::into).collect();
310        }
311
312        if mask.contains(Self::END_OF_EPOCH_DATA_FIELD) {
313            self.end_of_epoch_data = end_of_epoch_data.map(Into::into);
314        }
315
316        if mask.contains(Self::VERSION_SPECIFIC_DATA_FIELD) {
317            self.version_specific_data = Some(version_specific_data.into());
318        }
319    }
320}
321
322//
323// GasCostSummary
324//
325
326impl From<crate::gas::GasCostSummary> for GasCostSummary {
327    fn from(
328        crate::gas::GasCostSummary {
329            computation_cost,
330            storage_cost,
331            storage_rebate,
332            non_refundable_storage_fee,
333        }: crate::gas::GasCostSummary,
334    ) -> Self {
335        let mut message = Self::default();
336        message.computation_cost = Some(computation_cost);
337        message.storage_cost = Some(storage_cost);
338        message.storage_rebate = Some(storage_rebate);
339        message.non_refundable_storage_fee = Some(non_refundable_storage_fee);
340        message
341    }
342}
343
344//
345// CheckpointCommitment
346//
347
348impl From<crate::messages_checkpoint::CheckpointCommitment> for CheckpointCommitment {
349    fn from(value: crate::messages_checkpoint::CheckpointCommitment) -> Self {
350        use checkpoint_commitment::CheckpointCommitmentKind;
351
352        let mut message = Self::default();
353
354        let kind = match value {
355            crate::messages_checkpoint::CheckpointCommitment::ECMHLiveObjectSetDigest(digest) => {
356                message.digest = Some(digest.digest.to_string());
357                CheckpointCommitmentKind::EcmhLiveObjectSet
358            }
359            crate::messages_checkpoint::CheckpointCommitment::CheckpointArtifactsDigest(digest) => {
360                message.digest = Some(digest.to_string());
361                CheckpointCommitmentKind::CheckpointArtifacts
362            }
363        };
364
365        message.set_kind(kind);
366        message
367    }
368}
369
370//
371// EndOfEpochData
372//
373
374impl From<crate::messages_checkpoint::EndOfEpochData> for EndOfEpochData {
375    fn from(
376        crate::messages_checkpoint::EndOfEpochData {
377            next_epoch_committee,
378            next_epoch_protocol_version,
379            epoch_commitments,
380        }: crate::messages_checkpoint::EndOfEpochData,
381    ) -> Self {
382        let mut message = Self::default();
383
384        message.next_epoch_committee = next_epoch_committee
385            .into_iter()
386            .map(|(name, weight)| {
387                let mut member = ValidatorCommitteeMember::default();
388                member.public_key = Some(name.0.to_vec().into());
389                member.weight = Some(weight);
390                member
391            })
392            .collect();
393        message.next_epoch_protocol_version = Some(next_epoch_protocol_version.as_u64());
394        message.epoch_commitments = epoch_commitments.into_iter().map(Into::into).collect();
395
396        message
397    }
398}
399
400//
401// CheckpointContents
402//
403
404impl From<crate::messages_checkpoint::CheckpointContents> for CheckpointContents {
405    fn from(value: crate::messages_checkpoint::CheckpointContents) -> Self {
406        Self::merge_from(value, &FieldMaskTree::new_wildcard())
407    }
408}
409
410impl Merge<crate::messages_checkpoint::CheckpointContents> for CheckpointContents {
411    fn merge(
412        &mut self,
413        source: crate::messages_checkpoint::CheckpointContents,
414        mask: &FieldMaskTree,
415    ) {
416        if mask.contains(Self::BCS_FIELD) {
417            let mut bcs = Bcs::serialize(&source).unwrap();
418            bcs.name = Some("CheckpointContents".to_owned());
419            self.bcs = Some(bcs);
420        }
421
422        if mask.contains(Self::DIGEST_FIELD) {
423            self.digest = Some(source.digest().to_string());
424        }
425
426        if mask.contains(Self::VERSION_FIELD) {
427            self.set_version(match &source {
428                crate::messages_checkpoint::CheckpointContents::V1(_) => 1,
429                crate::messages_checkpoint::CheckpointContents::V2(_) => 2,
430            });
431        }
432
433        if mask.contains(Self::TRANSACTIONS_FIELD) {
434            self.transactions = source
435                .inner()
436                .iter()
437                .map(|(digests, sigs)| {
438                    let mut info = CheckpointedTransactionInfo::default();
439                    info.transaction = Some(digests.transaction.to_string());
440                    info.effects = Some(digests.effects.to_string());
441                    let (signatures, versions) = sigs
442                        .map(|(s, v)| {
443                            (s.into(), {
444                                let mut message = AddressAliasesVersion::default();
445                                message.version = v.map(Into::into);
446                                message
447                            })
448                        })
449                        .unzip();
450                    info.signatures = signatures;
451                    info.address_aliases_versions = versions;
452                    info
453                })
454                .collect();
455        }
456    }
457}
458
459impl Merge<&crate::messages_checkpoint::CheckpointContents> for Checkpoint {
460    fn merge(
461        &mut self,
462        source: &crate::messages_checkpoint::CheckpointContents,
463        mask: &FieldMaskTree,
464    ) {
465        if let Some(submask) = mask.subtree(Self::CONTENTS_FIELD.name) {
466            self.contents = Some(CheckpointContents::merge_from(source.to_owned(), &submask));
467        }
468    }
469}
470
471//
472// Checkpoint
473//
474
475impl Merge<&crate::messages_checkpoint::CheckpointSummary> for Checkpoint {
476    fn merge(
477        &mut self,
478        source: &crate::messages_checkpoint::CheckpointSummary,
479        mask: &FieldMaskTree,
480    ) {
481        if mask.contains(Self::SEQUENCE_NUMBER_FIELD) {
482            self.sequence_number = Some(source.sequence_number);
483        }
484
485        if mask.contains(Self::DIGEST_FIELD) {
486            self.digest = Some(source.digest().to_string());
487        }
488
489        if let Some(submask) = mask.subtree(Self::SUMMARY_FIELD) {
490            self.summary = Some(CheckpointSummary::merge_from(source.clone(), &submask));
491        }
492    }
493}
494
495impl<const T: bool> Merge<crate::crypto::AuthorityQuorumSignInfo<T>> for Checkpoint {
496    fn merge(&mut self, source: crate::crypto::AuthorityQuorumSignInfo<T>, mask: &FieldMaskTree) {
497        if mask.contains(Self::SIGNATURE_FIELD) {
498            self.signature = Some(source.into());
499        }
500    }
501}
502
503impl Merge<crate::messages_checkpoint::CheckpointContents> for Checkpoint {
504    fn merge(
505        &mut self,
506        source: crate::messages_checkpoint::CheckpointContents,
507        mask: &FieldMaskTree,
508    ) {
509        if let Some(submask) = mask.subtree(Self::CONTENTS_FIELD) {
510            self.contents = Some(CheckpointContents::merge_from(source, &submask));
511        }
512    }
513}
514
515//
516// Event
517//
518
519impl From<crate::event::Event> for Event {
520    fn from(value: crate::event::Event) -> Self {
521        Self::merge_from(&value, &FieldMaskTree::new_wildcard())
522    }
523}
524
525impl Merge<&crate::event::Event> for Event {
526    fn merge(&mut self, source: &crate::event::Event, mask: &FieldMaskTree) {
527        if mask.contains(Self::PACKAGE_ID_FIELD) {
528            self.package_id = Some(source.package_id.to_canonical_string(true));
529        }
530
531        if mask.contains(Self::MODULE_FIELD) {
532            self.module = Some(source.transaction_module.to_string());
533        }
534
535        if mask.contains(Self::SENDER_FIELD) {
536            self.sender = Some(source.sender.to_string());
537        }
538
539        if mask.contains(Self::EVENT_TYPE_FIELD) {
540            self.event_type = Some(source.type_.to_canonical_string(true));
541        }
542
543        if mask.contains(Self::CONTENTS_FIELD) {
544            let mut bcs = Bcs::from(source.contents.clone());
545            bcs.name = Some(source.type_.to_canonical_string(true));
546            self.contents = Some(bcs);
547        }
548    }
549}
550
551//
552// TransactionEvents
553//
554
555impl From<crate::effects::TransactionEvents> for TransactionEvents {
556    fn from(value: crate::effects::TransactionEvents) -> Self {
557        Self::merge_from(&value, &FieldMaskTree::new_wildcard())
558    }
559}
560
561impl Merge<&crate::effects::TransactionEvents> for TransactionEvents {
562    fn merge(&mut self, source: &crate::effects::TransactionEvents, mask: &FieldMaskTree) {
563        if mask.contains(Self::BCS_FIELD) {
564            let mut bcs = Bcs::serialize(&source).unwrap();
565            bcs.name = Some("TransactionEvents".to_owned());
566            self.bcs = Some(bcs);
567        }
568
569        if mask.contains(Self::DIGEST_FIELD) {
570            self.digest = Some(source.digest().to_string());
571        }
572
573        if let Some(events_mask) = mask.subtree(Self::EVENTS_FIELD) {
574            self.events = source
575                .data
576                .iter()
577                .map(|event| Event::merge_from(event, &events_mask))
578                .collect();
579        }
580    }
581}
582
583//
584// SystemState
585//
586
587impl From<crate::sui_system_state::SuiSystemState> for SystemState {
588    fn from(value: crate::sui_system_state::SuiSystemState) -> Self {
589        match value {
590            crate::sui_system_state::SuiSystemState::V1(v1) => v1.into(),
591            crate::sui_system_state::SuiSystemState::V2(v2) => v2.into(),
592
593            #[allow(unreachable_patterns)]
594            _ => Self::default(),
595        }
596    }
597}
598
599impl From<crate::sui_system_state::sui_system_state_inner_v1::SuiSystemStateInnerV1>
600    for SystemState
601{
602    fn from(
603        crate::sui_system_state::sui_system_state_inner_v1::SuiSystemStateInnerV1 {
604            epoch,
605            protocol_version,
606            system_state_version,
607            validators,
608            storage_fund,
609            parameters,
610            reference_gas_price,
611            validator_report_records,
612            stake_subsidy,
613            safe_mode,
614            safe_mode_storage_rewards,
615            safe_mode_computation_rewards,
616            safe_mode_storage_rebates,
617            safe_mode_non_refundable_storage_fee,
618            epoch_start_timestamp_ms,
619            extra_fields,
620        }: crate::sui_system_state::sui_system_state_inner_v1::SuiSystemStateInnerV1,
621    ) -> Self {
622        let validator_report_records = validator_report_records
623            .contents
624            .into_iter()
625            .map(|entry| {
626                let mut record = ValidatorReportRecord::default();
627                record.reported = Some(entry.key.to_string());
628                record.reporters = entry
629                    .value
630                    .contents
631                    .iter()
632                    .map(ToString::to_string)
633                    .collect();
634                record
635            })
636            .collect();
637
638        let mut message = Self::default();
639
640        message.version = Some(system_state_version);
641        message.epoch = Some(epoch);
642        message.protocol_version = Some(protocol_version);
643        message.validators = Some(validators.into());
644        message.storage_fund = Some(storage_fund.into());
645        message.parameters = Some(parameters.into());
646        message.reference_gas_price = Some(reference_gas_price);
647        message.validator_report_records = validator_report_records;
648        message.stake_subsidy = Some(stake_subsidy.into());
649        message.safe_mode = Some(safe_mode);
650        message.safe_mode_storage_rewards = Some(safe_mode_storage_rewards.value());
651        message.safe_mode_computation_rewards = Some(safe_mode_computation_rewards.value());
652        message.safe_mode_storage_rebates = Some(safe_mode_storage_rebates);
653        message.safe_mode_non_refundable_storage_fee = Some(safe_mode_non_refundable_storage_fee);
654        message.epoch_start_timestamp_ms = Some(epoch_start_timestamp_ms);
655        message.extra_fields = Some(extra_fields.into());
656        message
657    }
658}
659
660impl From<crate::sui_system_state::sui_system_state_inner_v2::SuiSystemStateInnerV2>
661    for SystemState
662{
663    fn from(
664        crate::sui_system_state::sui_system_state_inner_v2::SuiSystemStateInnerV2 {
665            epoch,
666            protocol_version,
667            system_state_version,
668            validators,
669            storage_fund,
670            parameters,
671            reference_gas_price,
672            validator_report_records,
673            stake_subsidy,
674            safe_mode,
675            safe_mode_storage_rewards,
676            safe_mode_computation_rewards,
677            safe_mode_storage_rebates,
678            safe_mode_non_refundable_storage_fee,
679            epoch_start_timestamp_ms,
680            extra_fields,
681        }: crate::sui_system_state::sui_system_state_inner_v2::SuiSystemStateInnerV2,
682    ) -> Self {
683        let validator_report_records = validator_report_records
684            .contents
685            .into_iter()
686            .map(|entry| {
687                let mut record = ValidatorReportRecord::default();
688                record.reported = Some(entry.key.to_string());
689                record.reporters = entry
690                    .value
691                    .contents
692                    .iter()
693                    .map(ToString::to_string)
694                    .collect();
695                record
696            })
697            .collect();
698
699        let mut message = Self::default();
700
701        message.version = Some(system_state_version);
702        message.epoch = Some(epoch);
703        message.protocol_version = Some(protocol_version);
704        message.validators = Some(validators.into());
705        message.storage_fund = Some(storage_fund.into());
706        message.parameters = Some(parameters.into());
707        message.reference_gas_price = Some(reference_gas_price);
708        message.validator_report_records = validator_report_records;
709        message.stake_subsidy = Some(stake_subsidy.into());
710        message.safe_mode = Some(safe_mode);
711        message.safe_mode_storage_rewards = Some(safe_mode_storage_rewards.value());
712        message.safe_mode_computation_rewards = Some(safe_mode_computation_rewards.value());
713        message.safe_mode_storage_rebates = Some(safe_mode_storage_rebates);
714        message.safe_mode_non_refundable_storage_fee = Some(safe_mode_non_refundable_storage_fee);
715        message.epoch_start_timestamp_ms = Some(epoch_start_timestamp_ms);
716        message.extra_fields = Some(extra_fields.into());
717        message
718    }
719}
720
721impl From<crate::collection_types::Bag> for MoveTable {
722    fn from(crate::collection_types::Bag { id, size }: crate::collection_types::Bag) -> Self {
723        let mut message = Self::default();
724        message.id = Some(id.id.bytes.to_canonical_string(true));
725        message.size = Some(size);
726        message
727    }
728}
729
730impl From<crate::collection_types::Table> for MoveTable {
731    fn from(crate::collection_types::Table { id, size }: crate::collection_types::Table) -> Self {
732        let mut message = Self::default();
733        message.id = Some(id.to_canonical_string(true));
734        message.size = Some(size);
735        message
736    }
737}
738
739impl From<crate::collection_types::TableVec> for MoveTable {
740    fn from(value: crate::collection_types::TableVec) -> Self {
741        value.contents.into()
742    }
743}
744
745impl From<crate::sui_system_state::sui_system_state_inner_v1::StakeSubsidyV1> for StakeSubsidy {
746    fn from(
747        crate::sui_system_state::sui_system_state_inner_v1::StakeSubsidyV1 {
748            balance,
749            distribution_counter,
750            current_distribution_amount,
751            stake_subsidy_period_length,
752            stake_subsidy_decrease_rate,
753            extra_fields,
754        }: crate::sui_system_state::sui_system_state_inner_v1::StakeSubsidyV1,
755    ) -> Self {
756        let mut message = Self::default();
757        message.balance = Some(balance.value());
758        message.distribution_counter = Some(distribution_counter);
759        message.current_distribution_amount = Some(current_distribution_amount);
760        message.stake_subsidy_period_length = Some(stake_subsidy_period_length);
761        message.stake_subsidy_decrease_rate = Some(stake_subsidy_decrease_rate.into());
762        message.extra_fields = Some(extra_fields.into());
763        message
764    }
765}
766
767impl From<crate::sui_system_state::sui_system_state_inner_v1::SystemParametersV1>
768    for SystemParameters
769{
770    fn from(
771        crate::sui_system_state::sui_system_state_inner_v1::SystemParametersV1 {
772            epoch_duration_ms,
773            stake_subsidy_start_epoch,
774            max_validator_count,
775            min_validator_joining_stake,
776            validator_low_stake_threshold,
777            validator_very_low_stake_threshold,
778            validator_low_stake_grace_period,
779            extra_fields,
780        }: crate::sui_system_state::sui_system_state_inner_v1::SystemParametersV1,
781    ) -> Self {
782        let mut message = Self::default();
783        message.epoch_duration_ms = Some(epoch_duration_ms);
784        message.stake_subsidy_start_epoch = Some(stake_subsidy_start_epoch);
785        message.min_validator_count = None;
786        message.max_validator_count = Some(max_validator_count);
787        message.min_validator_joining_stake = Some(min_validator_joining_stake);
788        message.validator_low_stake_threshold = Some(validator_low_stake_threshold);
789        message.validator_very_low_stake_threshold = Some(validator_very_low_stake_threshold);
790        message.validator_low_stake_grace_period = Some(validator_low_stake_grace_period);
791        message.extra_fields = Some(extra_fields.into());
792        message
793    }
794}
795
796impl From<crate::sui_system_state::sui_system_state_inner_v2::SystemParametersV2>
797    for SystemParameters
798{
799    fn from(
800        crate::sui_system_state::sui_system_state_inner_v2::SystemParametersV2 {
801            epoch_duration_ms,
802            stake_subsidy_start_epoch,
803            min_validator_count,
804            max_validator_count,
805            min_validator_joining_stake,
806            validator_low_stake_threshold,
807            validator_very_low_stake_threshold,
808            validator_low_stake_grace_period,
809            extra_fields,
810        }: crate::sui_system_state::sui_system_state_inner_v2::SystemParametersV2,
811    ) -> Self {
812        let mut message = Self::default();
813        message.epoch_duration_ms = Some(epoch_duration_ms);
814        message.stake_subsidy_start_epoch = Some(stake_subsidy_start_epoch);
815        message.min_validator_count = Some(min_validator_count);
816        message.max_validator_count = Some(max_validator_count);
817        message.min_validator_joining_stake = Some(min_validator_joining_stake);
818        message.validator_low_stake_threshold = Some(validator_low_stake_threshold);
819        message.validator_very_low_stake_threshold = Some(validator_very_low_stake_threshold);
820        message.validator_low_stake_grace_period = Some(validator_low_stake_grace_period);
821        message.extra_fields = Some(extra_fields.into());
822        message
823    }
824}
825
826impl From<crate::sui_system_state::sui_system_state_inner_v1::StorageFundV1> for StorageFund {
827    fn from(
828        crate::sui_system_state::sui_system_state_inner_v1::StorageFundV1 {
829            total_object_storage_rebates,
830            non_refundable_balance,
831        }: crate::sui_system_state::sui_system_state_inner_v1::StorageFundV1,
832    ) -> Self {
833        let mut message = Self::default();
834        message.total_object_storage_rebates = Some(total_object_storage_rebates.value());
835        message.non_refundable_balance = Some(non_refundable_balance.value());
836        message
837    }
838}
839
840impl From<crate::sui_system_state::sui_system_state_inner_v1::ValidatorSetV1> for ValidatorSet {
841    fn from(
842        crate::sui_system_state::sui_system_state_inner_v1::ValidatorSetV1 {
843            total_stake,
844            active_validators,
845            pending_active_validators,
846            pending_removals,
847            staking_pool_mappings,
848            inactive_validators,
849            validator_candidates,
850            at_risk_validators,
851            extra_fields,
852        }: crate::sui_system_state::sui_system_state_inner_v1::ValidatorSetV1,
853    ) -> Self {
854        let at_risk_validators = at_risk_validators
855            .contents
856            .into_iter()
857            .map(|entry| (entry.key.to_string(), entry.value))
858            .collect();
859
860        let mut message = Self::default();
861        message.total_stake = Some(total_stake);
862        message.active_validators = active_validators.into_iter().map(Into::into).collect();
863        message.pending_active_validators = Some(pending_active_validators.into());
864        message.pending_removals = pending_removals;
865        message.staking_pool_mappings = Some(staking_pool_mappings.into());
866        message.inactive_validators = Some(inactive_validators.into());
867        message.validator_candidates = Some(validator_candidates.into());
868        message.at_risk_validators = at_risk_validators;
869        message.extra_fields = Some(extra_fields.into());
870        message
871    }
872}
873
874impl From<crate::sui_system_state::sui_system_state_inner_v1::StakingPoolV1> for StakingPool {
875    fn from(
876        crate::sui_system_state::sui_system_state_inner_v1::StakingPoolV1 {
877            id,
878            activation_epoch,
879            deactivation_epoch,
880            sui_balance,
881            rewards_pool,
882            pool_token_balance,
883            exchange_rates,
884            pending_stake,
885            pending_total_sui_withdraw,
886            pending_pool_token_withdraw,
887            extra_fields,
888        }: crate::sui_system_state::sui_system_state_inner_v1::StakingPoolV1,
889    ) -> Self {
890        let mut message = Self::default();
891        message.id = Some(id.to_canonical_string(true));
892        message.activation_epoch = activation_epoch;
893        message.deactivation_epoch = deactivation_epoch;
894        message.sui_balance = Some(sui_balance);
895        message.rewards_pool = Some(rewards_pool.value());
896        message.pool_token_balance = Some(pool_token_balance);
897        message.exchange_rates = Some(exchange_rates.into());
898        message.pending_stake = Some(pending_stake);
899        message.pending_total_sui_withdraw = Some(pending_total_sui_withdraw);
900        message.pending_pool_token_withdraw = Some(pending_pool_token_withdraw);
901        message.extra_fields = Some(extra_fields.into());
902        message
903    }
904}
905
906impl From<crate::sui_system_state::sui_system_state_inner_v1::ValidatorV1> for Validator {
907    fn from(
908        crate::sui_system_state::sui_system_state_inner_v1::ValidatorV1 {
909            metadata:
910                crate::sui_system_state::sui_system_state_inner_v1::ValidatorMetadataV1 {
911                    sui_address,
912                    protocol_pubkey_bytes,
913                    network_pubkey_bytes,
914                    worker_pubkey_bytes,
915                    proof_of_possession_bytes,
916                    name,
917                    description,
918                    image_url,
919                    project_url,
920                    net_address,
921                    p2p_address,
922                    primary_address,
923                    worker_address,
924                    next_epoch_protocol_pubkey_bytes,
925                    next_epoch_proof_of_possession,
926                    next_epoch_network_pubkey_bytes,
927                    next_epoch_worker_pubkey_bytes,
928                    next_epoch_net_address,
929                    next_epoch_p2p_address,
930                    next_epoch_primary_address,
931                    next_epoch_worker_address,
932                    extra_fields: metadata_extra_fields,
933                },
934            voting_power,
935            operation_cap_id,
936            gas_price,
937            staking_pool,
938            commission_rate,
939            next_epoch_stake,
940            next_epoch_gas_price,
941            next_epoch_commission_rate,
942            extra_fields,
943            ..
944        }: crate::sui_system_state::sui_system_state_inner_v1::ValidatorV1,
945    ) -> Self {
946        let mut message = Self::default();
947        message.name = Some(name);
948        message.address = Some(sui_address.to_string());
949        message.description = Some(description);
950        message.image_url = Some(image_url);
951        message.project_url = Some(project_url);
952        message.protocol_public_key = Some(protocol_pubkey_bytes.into());
953        message.proof_of_possession = Some(proof_of_possession_bytes.into());
954        message.network_public_key = Some(network_pubkey_bytes.into());
955        message.worker_public_key = Some(worker_pubkey_bytes.into());
956        message.network_address = Some(net_address);
957        message.p2p_address = Some(p2p_address);
958        message.primary_address = Some(primary_address);
959        message.worker_address = Some(worker_address);
960        message.next_epoch_protocol_public_key = next_epoch_protocol_pubkey_bytes.map(Into::into);
961        message.next_epoch_proof_of_possession = next_epoch_proof_of_possession.map(Into::into);
962        message.next_epoch_network_public_key = next_epoch_network_pubkey_bytes.map(Into::into);
963        message.next_epoch_worker_public_key = next_epoch_worker_pubkey_bytes.map(Into::into);
964        message.next_epoch_network_address = next_epoch_net_address;
965        message.next_epoch_p2p_address = next_epoch_p2p_address;
966        message.next_epoch_primary_address = next_epoch_primary_address;
967        message.next_epoch_worker_address = next_epoch_worker_address;
968        message.metadata_extra_fields = Some(metadata_extra_fields.into());
969        message.voting_power = Some(voting_power);
970        message.operation_cap_id = Some(operation_cap_id.bytes.to_canonical_string(true));
971        message.gas_price = Some(gas_price);
972        message.staking_pool = Some(staking_pool.into());
973        message.commission_rate = Some(commission_rate);
974        message.next_epoch_stake = Some(next_epoch_stake);
975        message.next_epoch_gas_price = Some(next_epoch_gas_price);
976        message.next_epoch_commission_rate = Some(next_epoch_commission_rate);
977        message.extra_fields = Some(extra_fields.into());
978        message
979    }
980}
981
982impl TryFrom<&SystemState>
983    for crate::sui_system_state::sui_system_state_summary::SuiSystemStateSummary
984{
985    type Error = TryFromProtoError;
986
987    fn try_from(s: &SystemState) -> Result<Self, Self::Error> {
988        Ok(Self {
989            epoch: s.epoch(),
990            protocol_version: s.protocol_version(),
991            system_state_version: s.version(),
992            storage_fund_total_object_storage_rebates: s
993                .storage_fund()
994                .total_object_storage_rebates(),
995            storage_fund_non_refundable_balance: s.storage_fund().non_refundable_balance(),
996            reference_gas_price: s.reference_gas_price(),
997            safe_mode: s.safe_mode(),
998            safe_mode_storage_rewards: s.safe_mode_storage_rewards(),
999            safe_mode_computation_rewards: s.safe_mode_computation_rewards(),
1000            safe_mode_storage_rebates: s.safe_mode_storage_rebates(),
1001            safe_mode_non_refundable_storage_fee: s.safe_mode_non_refundable_storage_fee(),
1002            epoch_start_timestamp_ms: s.epoch_start_timestamp_ms(),
1003            epoch_duration_ms: s.parameters().epoch_duration_ms(),
1004            stake_subsidy_start_epoch: s.parameters().stake_subsidy_start_epoch(),
1005            max_validator_count: s.parameters().max_validator_count(),
1006            min_validator_joining_stake: s.parameters().min_validator_joining_stake(),
1007            validator_low_stake_threshold: s.parameters().validator_low_stake_threshold(),
1008            validator_very_low_stake_threshold: s.parameters().validator_very_low_stake_threshold(),
1009            validator_low_stake_grace_period: s.parameters().validator_low_stake_grace_period(),
1010            stake_subsidy_balance: s.stake_subsidy().balance(),
1011            stake_subsidy_distribution_counter: s.stake_subsidy().distribution_counter(),
1012            stake_subsidy_current_distribution_amount: s
1013                .stake_subsidy()
1014                .current_distribution_amount(),
1015            stake_subsidy_period_length: s.stake_subsidy().stake_subsidy_period_length(),
1016            stake_subsidy_decrease_rate: s.stake_subsidy().stake_subsidy_decrease_rate() as u16,
1017            total_stake: s.validators().total_stake(),
1018            active_validators: s
1019                .validators()
1020                .active_validators()
1021                .iter()
1022                .map(TryInto::try_into)
1023                .collect::<Result<_, _>>()?,
1024            pending_active_validators_id: s
1025                .validators()
1026                .pending_active_validators()
1027                .id()
1028                .parse()
1029                .map_err(|e| {
1030                TryFromProtoError::invalid("pending_active_validators_id", e)
1031            })?,
1032            pending_active_validators_size: s.validators().pending_active_validators().size(),
1033            pending_removals: s.validators().pending_removals().to_vec(),
1034            staking_pool_mappings_id: s
1035                .validators()
1036                .staking_pool_mappings()
1037                .id()
1038                .parse()
1039                .map_err(|e| TryFromProtoError::invalid("staking_pool_mappings_id", e))?,
1040            staking_pool_mappings_size: s.validators().staking_pool_mappings().size(),
1041            inactive_pools_id: s
1042                .validators()
1043                .inactive_validators()
1044                .id()
1045                .parse()
1046                .map_err(|e| TryFromProtoError::invalid("inactive_pools_id", e))?,
1047            inactive_pools_size: s.validators().inactive_validators().size(),
1048            validator_candidates_id: s
1049                .validators()
1050                .validator_candidates()
1051                .id()
1052                .parse()
1053                .map_err(|e| TryFromProtoError::invalid("validator_candidates", e))?,
1054            validator_candidates_size: s.validators().validator_candidates().size(),
1055            at_risk_validators: s
1056                .validators()
1057                .at_risk_validators()
1058                .iter()
1059                .map(|(address, epoch)| {
1060                    address
1061                        .parse()
1062                        .map(|address| (address, *epoch))
1063                        .map_err(|e| TryFromProtoError::invalid("at_risk_validators", e))
1064                })
1065                .collect::<Result<_, _>>()?,
1066            validator_report_records: s
1067                .validator_report_records()
1068                .iter()
1069                .map(|record| {
1070                    let reported = record.reported().parse()?;
1071                    let reporters = record
1072                        .reporters()
1073                        .iter()
1074                        .map(|address| address.parse())
1075                        .collect::<Result<Vec<_>, _>>()?;
1076                    Ok((reported, reporters))
1077                })
1078                .collect::<Result<_, anyhow::Error>>()
1079                .map_err(|e| TryFromProtoError::invalid("validator_report_records", e))?,
1080        })
1081    }
1082}
1083
1084impl TryFrom<&Validator>
1085    for crate::sui_system_state::sui_system_state_summary::SuiValidatorSummary
1086{
1087    type Error = TryFromProtoError;
1088
1089    fn try_from(v: &Validator) -> Result<Self, Self::Error> {
1090        Ok(Self {
1091            sui_address: v
1092                .address()
1093                .parse()
1094                .map_err(|e| TryFromProtoError::invalid("address", e))?,
1095            protocol_pubkey_bytes: v.protocol_public_key().into(),
1096            network_pubkey_bytes: v.network_public_key().into(),
1097            worker_pubkey_bytes: v.worker_public_key().into(),
1098            proof_of_possession_bytes: v.proof_of_possession().into(),
1099            name: v.name().into(),
1100            description: v.description().into(),
1101            image_url: v.image_url().into(),
1102            project_url: v.project_url().into(),
1103            net_address: v.network_address().into(),
1104            p2p_address: v.p2p_address().into(),
1105            primary_address: v.primary_address().into(),
1106            worker_address: v.worker_address().into(),
1107            next_epoch_protocol_pubkey_bytes: v
1108                .next_epoch_protocol_public_key_opt()
1109                .map(Into::into),
1110            next_epoch_proof_of_possession: v.next_epoch_proof_of_possession_opt().map(Into::into),
1111            next_epoch_network_pubkey_bytes: v.next_epoch_network_public_key_opt().map(Into::into),
1112            next_epoch_worker_pubkey_bytes: v.next_epoch_worker_public_key_opt().map(Into::into),
1113            next_epoch_net_address: v.next_epoch_network_address_opt().map(Into::into),
1114            next_epoch_p2p_address: v.next_epoch_p2p_address_opt().map(Into::into),
1115            next_epoch_primary_address: v.next_epoch_primary_address_opt().map(Into::into),
1116            next_epoch_worker_address: v.next_epoch_worker_address_opt().map(Into::into),
1117            voting_power: v.voting_power(),
1118            operation_cap_id: v
1119                .operation_cap_id()
1120                .parse()
1121                .map_err(|e| TryFromProtoError::invalid("operation_cap_id", e))?,
1122            gas_price: v.gas_price(),
1123            commission_rate: v.commission_rate(),
1124            next_epoch_stake: v.next_epoch_stake(),
1125            next_epoch_gas_price: v.next_epoch_gas_price(),
1126            next_epoch_commission_rate: v.next_epoch_commission_rate(),
1127            staking_pool_id: v
1128                .staking_pool()
1129                .id()
1130                .parse()
1131                .map_err(|e| TryFromProtoError::invalid("staking_pool_id", e))?,
1132            staking_pool_activation_epoch: v.staking_pool().activation_epoch_opt(),
1133            staking_pool_deactivation_epoch: v.staking_pool().deactivation_epoch_opt(),
1134            staking_pool_sui_balance: v.staking_pool().sui_balance(),
1135            rewards_pool: v.staking_pool().rewards_pool(),
1136            pool_token_balance: v.staking_pool().pool_token_balance(),
1137            pending_stake: v.staking_pool().pending_stake(),
1138            pending_total_sui_withdraw: v.staking_pool().pending_total_sui_withdraw(),
1139            pending_pool_token_withdraw: v.staking_pool().pending_pool_token_withdraw(),
1140            exchange_rates_id: v
1141                .staking_pool()
1142                .exchange_rates()
1143                .id()
1144                .parse()
1145                .map_err(|e| TryFromProtoError::invalid("exchange_rates_id", e))?,
1146            exchange_rates_size: v.staking_pool().exchange_rates().size(),
1147        })
1148    }
1149}
1150
1151//
1152// ExecutionStatus
1153//
1154
1155impl From<crate::execution_status::ExecutionStatus> for ExecutionStatus {
1156    fn from(value: crate::execution_status::ExecutionStatus) -> Self {
1157        let mut message = Self::default();
1158        match value {
1159            crate::execution_status::ExecutionStatus::Success => {
1160                message.success = Some(true);
1161            }
1162            crate::execution_status::ExecutionStatus::Failure(
1163                crate::execution_status::ExecutionFailure { error, command },
1164            ) => {
1165                let description = if let Some(command) = command {
1166                    format!("{error:?} in command {command}")
1167                } else {
1168                    format!("{error:?}")
1169                };
1170                let mut error_message = ExecutionError::from(error);
1171                error_message.command = command.map(|i| i as u64);
1172                error_message.description = Some(description);
1173
1174                message.success = Some(false);
1175                message.error = Some(error_message);
1176            }
1177        }
1178
1179        message
1180    }
1181}
1182
1183//
1184// ExecutionError
1185//
1186
1187fn size_error(size: u64, max_size: u64) -> SizeError {
1188    let mut message = SizeError::default();
1189    message.size = Some(size);
1190    message.max_size = Some(max_size);
1191    message
1192}
1193
1194fn index_error(index: u32, secondary_idx: Option<u32>) -> IndexError {
1195    let mut message = IndexError::default();
1196    message.index = Some(index);
1197    message.subresult = secondary_idx;
1198    message
1199}
1200
1201impl From<crate::execution_status::ExecutionErrorKind> for ExecutionError {
1202    fn from(value: crate::execution_status::ExecutionErrorKind) -> Self {
1203        use crate::execution_status::ExecutionErrorKind as E;
1204        use execution_error::ErrorDetails;
1205        use execution_error::ExecutionErrorKind;
1206
1207        let mut message = Self::default();
1208
1209        let kind = match value {
1210            E::InsufficientGas => ExecutionErrorKind::InsufficientGas,
1211            E::InvalidGasObject => ExecutionErrorKind::InvalidGasObject,
1212            E::InvariantViolation => ExecutionErrorKind::InvariantViolation,
1213            E::FeatureNotYetSupported => ExecutionErrorKind::FeatureNotYetSupported,
1214            E::MoveObjectTooBig {
1215                object_size,
1216                max_object_size,
1217            } => {
1218                message.error_details = Some(ErrorDetails::SizeError(size_error(
1219                    object_size,
1220                    max_object_size,
1221                )));
1222                ExecutionErrorKind::ObjectTooBig
1223            }
1224            E::MovePackageTooBig {
1225                object_size,
1226                max_object_size,
1227            } => {
1228                message.error_details = Some(ErrorDetails::SizeError(size_error(
1229                    object_size,
1230                    max_object_size,
1231                )));
1232                ExecutionErrorKind::PackageTooBig
1233            }
1234            E::CircularObjectOwnership { object } => {
1235                message.error_details =
1236                    Some(ErrorDetails::ObjectId(object.to_canonical_string(true)));
1237                ExecutionErrorKind::CircularObjectOwnership
1238            }
1239            E::InsufficientCoinBalance => ExecutionErrorKind::InsufficientCoinBalance,
1240            E::CoinBalanceOverflow => ExecutionErrorKind::CoinBalanceOverflow,
1241            E::PublishErrorNonZeroAddress => ExecutionErrorKind::PublishErrorNonZeroAddress,
1242            E::SuiMoveVerificationError => ExecutionErrorKind::SuiMoveVerificationError,
1243            E::MovePrimitiveRuntimeError(location) => {
1244                message.error_details = location.0.map(|l| {
1245                    let mut abort = MoveAbort::default();
1246                    abort.location = Some(l.into());
1247                    ErrorDetails::Abort(abort)
1248                });
1249                ExecutionErrorKind::MovePrimitiveRuntimeError
1250            }
1251            E::MoveAbort(location, code) => {
1252                let mut abort = MoveAbort::default();
1253                abort.abort_code = Some(code);
1254                abort.location = Some(location.into());
1255                message.error_details = Some(ErrorDetails::Abort(abort));
1256                ExecutionErrorKind::MoveAbort
1257            }
1258            E::VMVerificationOrDeserializationError => {
1259                ExecutionErrorKind::VmVerificationOrDeserializationError
1260            }
1261            E::VMInvariantViolation => ExecutionErrorKind::VmInvariantViolation,
1262            E::FunctionNotFound => ExecutionErrorKind::FunctionNotFound,
1263            E::ArityMismatch => ExecutionErrorKind::ArityMismatch,
1264            E::TypeArityMismatch => ExecutionErrorKind::TypeArityMismatch,
1265            E::NonEntryFunctionInvoked => ExecutionErrorKind::NonEntryFunctionInvoked,
1266            E::CommandArgumentError { arg_idx, kind } => {
1267                let mut command_argument_error = CommandArgumentError::from(kind);
1268                command_argument_error.argument = Some(arg_idx.into());
1269                message.error_details =
1270                    Some(ErrorDetails::CommandArgumentError(command_argument_error));
1271                ExecutionErrorKind::CommandArgumentError
1272            }
1273            E::TypeArgumentError { argument_idx, kind } => {
1274                let mut type_argument_error = TypeArgumentError::default();
1275                type_argument_error.type_argument = Some(argument_idx.into());
1276                type_argument_error.kind =
1277                    Some(type_argument_error::TypeArgumentErrorKind::from(kind).into());
1278                message.error_details = Some(ErrorDetails::TypeArgumentError(type_argument_error));
1279                ExecutionErrorKind::TypeArgumentError
1280            }
1281            E::UnusedValueWithoutDrop {
1282                result_idx,
1283                secondary_idx,
1284            } => {
1285                message.error_details = Some(ErrorDetails::IndexError(index_error(
1286                    result_idx.into(),
1287                    Some(secondary_idx.into()),
1288                )));
1289                ExecutionErrorKind::UnusedValueWithoutDrop
1290            }
1291            E::InvalidPublicFunctionReturnType { idx } => {
1292                message.error_details =
1293                    Some(ErrorDetails::IndexError(index_error(idx.into(), None)));
1294                ExecutionErrorKind::InvalidPublicFunctionReturnType
1295            }
1296            E::InvalidTransferObject => ExecutionErrorKind::InvalidTransferObject,
1297            E::EffectsTooLarge {
1298                current_size,
1299                max_size,
1300            } => {
1301                message.error_details =
1302                    Some(ErrorDetails::SizeError(size_error(current_size, max_size)));
1303                ExecutionErrorKind::EffectsTooLarge
1304            }
1305            E::PublishUpgradeMissingDependency => {
1306                ExecutionErrorKind::PublishUpgradeMissingDependency
1307            }
1308            E::PublishUpgradeDependencyDowngrade => {
1309                ExecutionErrorKind::PublishUpgradeDependencyDowngrade
1310            }
1311            E::PackageUpgradeError { upgrade_error } => {
1312                message.error_details =
1313                    Some(ErrorDetails::PackageUpgradeError(upgrade_error.into()));
1314                ExecutionErrorKind::PackageUpgradeError
1315            }
1316            E::WrittenObjectsTooLarge {
1317                current_size,
1318                max_size,
1319            } => {
1320                message.error_details =
1321                    Some(ErrorDetails::SizeError(size_error(current_size, max_size)));
1322
1323                ExecutionErrorKind::WrittenObjectsTooLarge
1324            }
1325            E::CertificateDenied => ExecutionErrorKind::CertificateDenied,
1326            E::SuiMoveVerificationTimedout => ExecutionErrorKind::SuiMoveVerificationTimedout,
1327            E::SharedObjectOperationNotAllowed => {
1328                ExecutionErrorKind::ConsensusObjectOperationNotAllowed
1329            }
1330            E::InputObjectDeleted => ExecutionErrorKind::InputObjectDeleted,
1331            E::ExecutionCancelledDueToSharedObjectCongestion { congested_objects } => {
1332                message.error_details = Some(ErrorDetails::CongestedObjects({
1333                    let mut message = CongestedObjects::default();
1334                    message.objects = congested_objects
1335                        .0
1336                        .iter()
1337                        .map(|o| o.to_canonical_string(true))
1338                        .collect();
1339                    message
1340                }));
1341
1342                ExecutionErrorKind::ExecutionCanceledDueToConsensusObjectCongestion
1343            }
1344            E::AddressDeniedForCoin { address, coin_type } => {
1345                message.error_details = Some(ErrorDetails::CoinDenyListError({
1346                    let mut message = CoinDenyListError::default();
1347                    message.address = Some(address.to_string());
1348                    message.coin_type = Some(coin_type);
1349                    message
1350                }));
1351                ExecutionErrorKind::AddressDeniedForCoin
1352            }
1353            E::CoinTypeGlobalPause { coin_type } => {
1354                message.error_details = Some(ErrorDetails::CoinDenyListError({
1355                    let mut message = CoinDenyListError::default();
1356                    message.coin_type = Some(coin_type);
1357                    message
1358                }));
1359                ExecutionErrorKind::CoinTypeGlobalPause
1360            }
1361            E::ExecutionCancelledDueToRandomnessUnavailable => {
1362                ExecutionErrorKind::ExecutionCanceledDueToRandomnessUnavailable
1363            }
1364            E::MoveVectorElemTooBig {
1365                value_size,
1366                max_scaled_size,
1367            } => {
1368                message.error_details = Some(ErrorDetails::SizeError(size_error(
1369                    value_size,
1370                    max_scaled_size,
1371                )));
1372
1373                ExecutionErrorKind::MoveVectorElemTooBig
1374            }
1375            E::MoveRawValueTooBig {
1376                value_size,
1377                max_scaled_size,
1378            } => {
1379                message.error_details = Some(ErrorDetails::SizeError(size_error(
1380                    value_size,
1381                    max_scaled_size,
1382                )));
1383                ExecutionErrorKind::MoveRawValueTooBig
1384            }
1385            E::InvalidLinkage => ExecutionErrorKind::InvalidLinkage,
1386            E::InsufficientFundsForWithdraw => ExecutionErrorKind::InsufficientFundsForWithdraw,
1387            E::NonExclusiveWriteInputObjectModified { id } => {
1388                message.set_object_id(id.to_canonical_string(true));
1389                ExecutionErrorKind::NonExclusiveWriteInputObjectModified
1390            }
1391        };
1392
1393        message.set_kind(kind);
1394        message
1395    }
1396}
1397
1398//
1399// CommandArgumentError
1400//
1401
1402impl From<crate::execution_status::CommandArgumentError> for CommandArgumentError {
1403    fn from(value: crate::execution_status::CommandArgumentError) -> Self {
1404        use crate::execution_status::CommandArgumentError as E;
1405        use command_argument_error::CommandArgumentErrorKind;
1406
1407        let mut message = Self::default();
1408
1409        let kind = match value {
1410            E::TypeMismatch => CommandArgumentErrorKind::TypeMismatch,
1411            E::InvalidBCSBytes => CommandArgumentErrorKind::InvalidBcsBytes,
1412            E::InvalidUsageOfPureArg => CommandArgumentErrorKind::InvalidUsageOfPureArgument,
1413            E::InvalidArgumentToPrivateEntryFunction => {
1414                CommandArgumentErrorKind::InvalidArgumentToPrivateEntryFunction
1415            }
1416            E::IndexOutOfBounds { idx } => {
1417                message.index_error = Some(index_error(idx.into(), None));
1418                CommandArgumentErrorKind::IndexOutOfBounds
1419            }
1420            E::SecondaryIndexOutOfBounds {
1421                result_idx,
1422                secondary_idx,
1423            } => {
1424                message.index_error =
1425                    Some(index_error(result_idx.into(), Some(secondary_idx.into())));
1426                CommandArgumentErrorKind::SecondaryIndexOutOfBounds
1427            }
1428            E::InvalidResultArity { result_idx } => {
1429                message.index_error = Some(index_error(result_idx.into(), None));
1430                CommandArgumentErrorKind::InvalidResultArity
1431            }
1432            E::InvalidGasCoinUsage => CommandArgumentErrorKind::InvalidGasCoinUsage,
1433            E::InvalidValueUsage => CommandArgumentErrorKind::InvalidValueUsage,
1434            E::InvalidObjectByValue => CommandArgumentErrorKind::InvalidObjectByValue,
1435            E::InvalidObjectByMutRef => CommandArgumentErrorKind::InvalidObjectByMutRef,
1436            E::SharedObjectOperationNotAllowed => {
1437                CommandArgumentErrorKind::ConsensusObjectOperationNotAllowed
1438            }
1439            E::InvalidArgumentArity => CommandArgumentErrorKind::InvalidArgumentArity,
1440
1441            E::InvalidTransferObject => CommandArgumentErrorKind::InvalidTransferObject,
1442            E::InvalidMakeMoveVecNonObjectArgument => {
1443                CommandArgumentErrorKind::InvalidMakeMoveVecNonObjectArgument
1444            }
1445            E::ArgumentWithoutValue => CommandArgumentErrorKind::ArgumentWithoutValue,
1446            E::CannotMoveBorrowedValue => CommandArgumentErrorKind::CannotMoveBorrowedValue,
1447            E::CannotWriteToExtendedReference => {
1448                CommandArgumentErrorKind::CannotWriteToExtendedReference
1449            }
1450            E::InvalidReferenceArgument => CommandArgumentErrorKind::InvalidReferenceArgument,
1451        };
1452
1453        message.set_kind(kind);
1454        message
1455    }
1456}
1457
1458//
1459// TypeArgumentError
1460//
1461
1462impl From<crate::execution_status::TypeArgumentError>
1463    for type_argument_error::TypeArgumentErrorKind
1464{
1465    fn from(value: crate::execution_status::TypeArgumentError) -> Self {
1466        use crate::execution_status::TypeArgumentError::*;
1467
1468        match value {
1469            TypeNotFound => Self::TypeNotFound,
1470            ConstraintNotSatisfied => Self::ConstraintNotSatisfied,
1471        }
1472    }
1473}
1474
1475//
1476// PackageUpgradeError
1477//
1478
1479impl From<crate::execution_status::PackageUpgradeError> for PackageUpgradeError {
1480    fn from(value: crate::execution_status::PackageUpgradeError) -> Self {
1481        use crate::execution_status::PackageUpgradeError as E;
1482        use package_upgrade_error::PackageUpgradeErrorKind;
1483
1484        let mut message = Self::default();
1485
1486        let kind = match value {
1487            E::UnableToFetchPackage { package_id } => {
1488                message.package_id = Some(package_id.to_canonical_string(true));
1489                PackageUpgradeErrorKind::UnableToFetchPackage
1490            }
1491            E::NotAPackage { object_id } => {
1492                message.package_id = Some(object_id.to_canonical_string(true));
1493                PackageUpgradeErrorKind::NotAPackage
1494            }
1495            E::IncompatibleUpgrade => PackageUpgradeErrorKind::IncompatibleUpgrade,
1496            E::DigestDoesNotMatch { digest } => {
1497                message.digest = crate::digests::Digest::try_from(digest)
1498                    .ok()
1499                    .map(|d| d.to_string());
1500                PackageUpgradeErrorKind::DigestDoesNotMatch
1501            }
1502            E::UnknownUpgradePolicy { policy } => {
1503                message.policy = Some(policy.into());
1504                PackageUpgradeErrorKind::UnknownUpgradePolicy
1505            }
1506            E::PackageIDDoesNotMatch {
1507                package_id,
1508                ticket_id,
1509            } => {
1510                message.package_id = Some(package_id.to_canonical_string(true));
1511                message.ticket_id = Some(ticket_id.to_canonical_string(true));
1512                PackageUpgradeErrorKind::PackageIdDoesNotMatch
1513            }
1514        };
1515
1516        message.set_kind(kind);
1517        message
1518    }
1519}
1520
1521//
1522// MoveLocation
1523//
1524
1525impl From<crate::execution_status::MoveLocation> for MoveLocation {
1526    fn from(value: crate::execution_status::MoveLocation) -> Self {
1527        let mut message = Self::default();
1528        message.package = Some(value.module.address().to_canonical_string(true));
1529        message.module = Some(value.module.name().to_string());
1530        message.function = Some(value.function.into());
1531        message.instruction = Some(value.instruction.into());
1532        message.function_name = value.function_name.map(|name| name.to_string());
1533        message
1534    }
1535}
1536
1537//
1538// AuthorityQuorumSignInfo aka ValidatorAggregatedSignature
1539//
1540
1541impl<const T: bool> From<crate::crypto::AuthorityQuorumSignInfo<T>>
1542    for ValidatorAggregatedSignature
1543{
1544    fn from(value: crate::crypto::AuthorityQuorumSignInfo<T>) -> Self {
1545        let mut bitmap = Vec::new();
1546        value.signers_map.serialize_into(&mut bitmap).unwrap();
1547
1548        Self::default()
1549            .with_epoch(value.epoch)
1550            .with_signature(value.signature.as_ref().to_vec())
1551            .with_bitmap(bitmap)
1552    }
1553}
1554
1555impl<const T: bool> TryFrom<&ValidatorAggregatedSignature>
1556    for crate::crypto::AuthorityQuorumSignInfo<T>
1557{
1558    type Error = TryFromProtoError;
1559
1560    fn try_from(value: &ValidatorAggregatedSignature) -> Result<Self, Self::Error> {
1561        Ok(Self {
1562            epoch: value.epoch(),
1563            signature: crate::crypto::AggregateAuthoritySignature::from_bytes(value.signature())
1564                .map_err(|e| TryFromProtoError::invalid("signature", e))?,
1565            signers_map: crate::sui_serde::deserialize_sui_bitmap(value.bitmap())
1566                .map_err(|e| TryFromProtoError::invalid("bitmap", e))?,
1567        })
1568    }
1569}
1570
1571//
1572// ValidatorCommittee
1573//
1574
1575impl From<crate::committee::Committee> for ValidatorCommittee {
1576    fn from(value: crate::committee::Committee) -> Self {
1577        let mut message = Self::default();
1578        message.epoch = Some(value.epoch);
1579        message.members = value
1580            .voting_rights
1581            .into_iter()
1582            .map(|(name, weight)| {
1583                let mut member = ValidatorCommitteeMember::default();
1584                member.public_key = Some(name.0.to_vec().into());
1585                member.weight = Some(weight);
1586                member
1587            })
1588            .collect();
1589        message
1590    }
1591}
1592
1593impl TryFrom<&ValidatorCommittee> for crate::committee::Committee {
1594    type Error = TryFromProtoError;
1595
1596    fn try_from(s: &ValidatorCommittee) -> Result<Self, Self::Error> {
1597        let members = s
1598            .members()
1599            .iter()
1600            .map(|member| {
1601                let public_key =
1602                    crate::crypto::AuthorityPublicKeyBytes::from_bytes(member.public_key())
1603                        .map_err(|e| TryFromProtoError::invalid("public_key", e))?;
1604                Ok((public_key, member.weight()))
1605            })
1606            .collect::<Result<_, _>>()?;
1607        Ok(Self::new(s.epoch(), members))
1608    }
1609}
1610
1611//
1612// ZkLoginAuthenticator
1613//
1614
1615impl From<&crate::zk_login_authenticator::ZkLoginAuthenticator> for ZkLoginAuthenticator {
1616    fn from(value: &crate::zk_login_authenticator::ZkLoginAuthenticator) -> Self {
1617        //TODO implement this without going through the sdk type
1618        let mut inputs = ZkLoginInputs::default();
1619        inputs.address_seed = Some(value.inputs.get_address_seed().to_string());
1620        let mut message = Self::default();
1621        message.inputs = Some(inputs);
1622        message.max_epoch = Some(value.get_max_epoch());
1623        message.signature = Some(value.user_signature.clone().into());
1624
1625        sui_sdk_types::ZkLoginAuthenticator::try_from(value.clone())
1626            .map(Into::into)
1627            .ok()
1628            .unwrap_or(message)
1629    }
1630}
1631
1632//
1633// ZkLoginPublicIdentifier
1634//
1635
1636impl From<&crate::crypto::ZkLoginPublicIdentifier> for ZkLoginPublicIdentifier {
1637    fn from(value: &crate::crypto::ZkLoginPublicIdentifier) -> Self {
1638        //TODO implement this without going through the sdk type
1639        sui_sdk_types::ZkLoginPublicIdentifier::try_from(value.to_owned())
1640            .map(|id| (&id).into())
1641            .ok()
1642            .unwrap_or_default()
1643    }
1644}
1645
1646//
1647// SignatureScheme
1648//
1649
1650impl From<crate::crypto::SignatureScheme> for SignatureScheme {
1651    fn from(value: crate::crypto::SignatureScheme) -> Self {
1652        use crate::crypto::SignatureScheme as S;
1653
1654        match value {
1655            S::ED25519 => Self::Ed25519,
1656            S::Secp256k1 => Self::Secp256k1,
1657            S::Secp256r1 => Self::Secp256r1,
1658            S::BLS12381 => Self::Bls12381,
1659            S::MultiSig => Self::Multisig,
1660            S::ZkLoginAuthenticator => Self::Zklogin,
1661            S::PasskeyAuthenticator => Self::Passkey,
1662        }
1663    }
1664}
1665
1666//
1667// SimpleSignature
1668//
1669
1670impl From<crate::crypto::Signature> for SimpleSignature {
1671    fn from(value: crate::crypto::Signature) -> Self {
1672        Self::from(&value)
1673    }
1674}
1675
1676impl From<&crate::crypto::Signature> for SimpleSignature {
1677    fn from(value: &crate::crypto::Signature) -> Self {
1678        let scheme: SignatureScheme = value.scheme().into();
1679        let signature = value.signature_bytes();
1680        let public_key = value.public_key_bytes();
1681
1682        let mut message = Self::default();
1683        message.scheme = Some(scheme.into());
1684        message.signature = Some(signature.to_vec().into());
1685        message.public_key = Some(public_key.to_vec().into());
1686        message
1687    }
1688}
1689
1690//
1691// PasskeyAuthenticator
1692//
1693
1694impl From<&crate::passkey_authenticator::PasskeyAuthenticator> for PasskeyAuthenticator {
1695    fn from(value: &crate::passkey_authenticator::PasskeyAuthenticator) -> Self {
1696        let mut message = Self::default();
1697        message.authenticator_data = Some(value.authenticator_data().to_vec().into());
1698        message.client_data_json = Some(value.client_data_json().to_owned());
1699        message.signature = Some(value.signature().into());
1700        message
1701    }
1702}
1703
1704//
1705// MultisigMemberPublicKey
1706//
1707
1708impl From<&crate::crypto::PublicKey> for MultisigMemberPublicKey {
1709    fn from(value: &crate::crypto::PublicKey) -> Self {
1710        let mut message = Self::default();
1711
1712        match value {
1713            crate::crypto::PublicKey::Ed25519(_)
1714            | crate::crypto::PublicKey::Secp256k1(_)
1715            | crate::crypto::PublicKey::Secp256r1(_)
1716            | crate::crypto::PublicKey::Passkey(_) => {
1717                message.public_key = Some(value.as_ref().to_vec().into());
1718            }
1719            crate::crypto::PublicKey::ZkLogin(z) => {
1720                message.zklogin = Some(z.into());
1721            }
1722        }
1723
1724        message.set_scheme(value.scheme().into());
1725        message
1726    }
1727}
1728
1729//
1730// MultisigCommittee
1731//
1732
1733impl From<&crate::multisig::MultiSigPublicKey> for MultisigCommittee {
1734    fn from(value: &crate::multisig::MultiSigPublicKey) -> Self {
1735        let mut message = Self::default();
1736        message.members = value
1737            .pubkeys()
1738            .iter()
1739            .map(|(pk, weight)| {
1740                let mut member = MultisigMember::default();
1741                member.public_key = Some(pk.into());
1742                member.weight = Some((*weight).into());
1743                member
1744            })
1745            .collect();
1746        message.threshold = Some((*value.threshold()).into());
1747        message
1748    }
1749}
1750
1751impl From<&crate::multisig_legacy::MultiSigPublicKeyLegacy> for MultisigCommittee {
1752    fn from(value: &crate::multisig_legacy::MultiSigPublicKeyLegacy) -> Self {
1753        let mut message = Self::default();
1754        message.members = value
1755            .pubkeys()
1756            .iter()
1757            .map(|(pk, weight)| {
1758                let mut member = MultisigMember::default();
1759                member.public_key = Some(pk.into());
1760                member.weight = Some((*weight).into());
1761                member
1762            })
1763            .collect();
1764        message.threshold = Some((*value.threshold()).into());
1765        message
1766    }
1767}
1768
1769//
1770// MultisigMemberSignature
1771//
1772
1773impl From<&crate::crypto::CompressedSignature> for MultisigMemberSignature {
1774    fn from(value: &crate::crypto::CompressedSignature) -> Self {
1775        let mut message = Self::default();
1776
1777        let scheme = match value {
1778            crate::crypto::CompressedSignature::Ed25519(b) => {
1779                message.signature = Some(b.0.to_vec().into());
1780                SignatureScheme::Ed25519
1781            }
1782            crate::crypto::CompressedSignature::Secp256k1(b) => {
1783                message.signature = Some(b.0.to_vec().into());
1784                SignatureScheme::Secp256k1
1785            }
1786            crate::crypto::CompressedSignature::Secp256r1(b) => {
1787                message.signature = Some(b.0.to_vec().into());
1788                SignatureScheme::Secp256r1
1789            }
1790            crate::crypto::CompressedSignature::ZkLogin(_z) => {
1791                //TODO
1792                SignatureScheme::Zklogin
1793            }
1794            crate::crypto::CompressedSignature::Passkey(_p) => {
1795                //TODO
1796                SignatureScheme::Passkey
1797            }
1798        };
1799
1800        message.set_scheme(scheme);
1801        message
1802    }
1803}
1804
1805//
1806// MultisigAggregatedSignature
1807//
1808
1809impl From<&crate::multisig_legacy::MultiSigLegacy> for MultisigAggregatedSignature {
1810    fn from(value: &crate::multisig_legacy::MultiSigLegacy) -> Self {
1811        let mut legacy_bitmap = Vec::new();
1812        value
1813            .get_bitmap()
1814            .serialize_into(&mut legacy_bitmap)
1815            .unwrap();
1816
1817        Self::default()
1818            .with_signatures(value.get_sigs().iter().map(Into::into).collect())
1819            .with_legacy_bitmap(legacy_bitmap)
1820            .with_committee(value.get_pk())
1821    }
1822}
1823
1824impl From<&crate::multisig::MultiSig> for MultisigAggregatedSignature {
1825    fn from(value: &crate::multisig::MultiSig) -> Self {
1826        let mut message = Self::default();
1827        message.signatures = value.get_sigs().iter().map(Into::into).collect();
1828        message.bitmap = Some(value.get_bitmap().into());
1829        message.committee = Some(value.get_pk().into());
1830        message
1831    }
1832}
1833
1834//
1835// UserSignature
1836//
1837
1838impl From<&crate::signature::GenericSignature> for UserSignature {
1839    fn from(value: &crate::signature::GenericSignature) -> Self {
1840        Self::merge_from(value, &FieldMaskTree::new_wildcard())
1841    }
1842}
1843
1844impl Merge<&crate::signature::GenericSignature> for UserSignature {
1845    fn merge(&mut self, source: &crate::signature::GenericSignature, mask: &FieldMaskTree) {
1846        use user_signature::Signature;
1847
1848        if mask.contains(Self::BCS_FIELD) {
1849            let mut bcs = Bcs::from(source.as_ref().to_vec());
1850            bcs.name = Some("UserSignatureBytes".to_owned());
1851            self.bcs = Some(bcs);
1852        }
1853
1854        let scheme = match source {
1855            crate::signature::GenericSignature::MultiSig(multi_sig) => {
1856                if mask.contains(Self::MULTISIG_FIELD) {
1857                    self.signature = Some(Signature::Multisig(multi_sig.into()));
1858                }
1859                SignatureScheme::Multisig
1860            }
1861            crate::signature::GenericSignature::MultiSigLegacy(multi_sig_legacy) => {
1862                if mask.contains(Self::MULTISIG_FIELD) {
1863                    self.signature = Some(Signature::Multisig(multi_sig_legacy.into()));
1864                }
1865                SignatureScheme::Multisig
1866            }
1867            crate::signature::GenericSignature::Signature(signature) => {
1868                let scheme = signature.scheme().into();
1869                if mask.contains(Self::SIMPLE_FIELD) {
1870                    self.signature = Some(Signature::Simple(signature.into()));
1871                }
1872                scheme
1873            }
1874            crate::signature::GenericSignature::ZkLoginAuthenticator(z) => {
1875                if mask.contains(Self::ZKLOGIN_FIELD) {
1876                    self.signature = Some(Signature::Zklogin(z.into()));
1877                }
1878                SignatureScheme::Zklogin
1879            }
1880            crate::signature::GenericSignature::PasskeyAuthenticator(p) => {
1881                if mask.contains(Self::PASSKEY_FIELD) {
1882                    self.signature = Some(Signature::Passkey(p.into()));
1883                }
1884                SignatureScheme::Passkey
1885            }
1886        };
1887
1888        if mask.contains(Self::SCHEME_FIELD) {
1889            self.set_scheme(scheme);
1890        }
1891    }
1892}
1893
1894//
1895// BalanceChange
1896//
1897
1898impl From<crate::balance_change::BalanceChange> for BalanceChange {
1899    fn from(value: crate::balance_change::BalanceChange) -> Self {
1900        let mut message = Self::default();
1901        message.address = Some(value.address.to_string());
1902        message.coin_type = Some(value.coin_type.to_canonical_string(true));
1903        message.amount = Some(value.amount.to_string());
1904        message
1905    }
1906}
1907
1908impl TryFrom<&BalanceChange> for crate::balance_change::BalanceChange {
1909    type Error = TryFromProtoError;
1910
1911    fn try_from(value: &BalanceChange) -> Result<Self, Self::Error> {
1912        Ok(Self {
1913            address: value
1914                .address()
1915                .parse()
1916                .map_err(|e| TryFromProtoError::invalid(BalanceChange::ADDRESS_FIELD, e))?,
1917            coin_type: value
1918                .coin_type()
1919                .parse()
1920                .map_err(|e| TryFromProtoError::invalid(BalanceChange::COIN_TYPE_FIELD, e))?,
1921            amount: value
1922                .amount()
1923                .parse()
1924                .map_err(|e| TryFromProtoError::invalid(BalanceChange::AMOUNT_FIELD, e))?,
1925        })
1926    }
1927}
1928
1929//
1930// Object
1931//
1932
1933pub const PACKAGE_TYPE: &str = "package";
1934
1935impl From<crate::object::Object> for Object {
1936    fn from(value: crate::object::Object) -> Self {
1937        Self::merge_from(&value, &FieldMaskTree::new_wildcard())
1938    }
1939}
1940
1941impl Merge<&crate::object::Object> for Object {
1942    fn merge(&mut self, source: &crate::object::Object, mask: &FieldMaskTree) {
1943        if mask.contains(Self::BCS_FIELD.name) {
1944            let mut bcs = Bcs::serialize(&source).unwrap();
1945            bcs.name = Some("Object".to_owned());
1946            self.bcs = Some(bcs);
1947        }
1948
1949        if mask.contains(Self::DIGEST_FIELD.name) {
1950            self.digest = Some(source.digest().to_string());
1951        }
1952
1953        if mask.contains(Self::OBJECT_ID_FIELD.name) {
1954            self.object_id = Some(source.id().to_canonical_string(true));
1955        }
1956
1957        if mask.contains(Self::VERSION_FIELD.name) {
1958            self.version = Some(source.version().value());
1959        }
1960
1961        if mask.contains(Self::OWNER_FIELD.name) {
1962            self.owner = Some(source.owner().to_owned().into());
1963        }
1964
1965        if mask.contains(Self::PREVIOUS_TRANSACTION_FIELD.name) {
1966            self.previous_transaction = Some(source.previous_transaction.to_string());
1967        }
1968
1969        if mask.contains(Self::STORAGE_REBATE_FIELD.name) {
1970            self.storage_rebate = Some(source.storage_rebate);
1971        }
1972
1973        if mask.contains(Self::BALANCE_FIELD) {
1974            self.balance = source.as_coin_maybe().map(|coin| coin.balance.value());
1975        }
1976
1977        self.merge(&source.data, mask);
1978    }
1979}
1980
1981impl Merge<&crate::object::MoveObject> for Object {
1982    fn merge(&mut self, source: &crate::object::MoveObject, mask: &FieldMaskTree) {
1983        self.object_id = Some(source.id().to_canonical_string(true));
1984        self.version = Some(source.version().value());
1985
1986        if mask.contains(Self::OBJECT_TYPE_FIELD.name) {
1987            self.object_type = Some(source.type_().to_canonical_string(true));
1988        }
1989
1990        if mask.contains(Self::HAS_PUBLIC_TRANSFER_FIELD.name) {
1991            self.has_public_transfer = Some(source.has_public_transfer());
1992        }
1993
1994        if mask.contains(Self::CONTENTS_FIELD.name) {
1995            let mut bcs = Bcs::from(source.contents().to_vec());
1996            bcs.name = Some(source.type_().to_canonical_string(true));
1997            self.contents = Some(bcs);
1998        }
1999    }
2000}
2001
2002impl Merge<&crate::move_package::MovePackage> for Object {
2003    fn merge(&mut self, source: &crate::move_package::MovePackage, mask: &FieldMaskTree) {
2004        self.object_id = Some(source.id().to_canonical_string(true));
2005        self.version = Some(source.version().value());
2006
2007        if mask.contains(Self::OBJECT_TYPE_FIELD.name) {
2008            self.object_type = Some(PACKAGE_TYPE.to_owned());
2009        }
2010
2011        if mask.contains(Self::PACKAGE_FIELD.name) {
2012            let mut package = Package::default();
2013            package.modules = source
2014                .serialized_module_map()
2015                .iter()
2016                .map(|(name, contents)| {
2017                    let mut module = Module::default();
2018                    module.name = Some(name.to_string());
2019                    module.contents = Some(contents.clone().into());
2020                    module
2021                })
2022                .collect();
2023            package.type_origins = source
2024                .type_origin_table()
2025                .clone()
2026                .into_iter()
2027                .map(Into::into)
2028                .collect();
2029            package.linkage = source
2030                .linkage_table()
2031                .iter()
2032                .map(
2033                    |(
2034                        original_id,
2035                        crate::move_package::UpgradeInfo {
2036                            upgraded_id,
2037                            upgraded_version,
2038                        },
2039                    )| {
2040                        let mut linkage = Linkage::default();
2041                        linkage.original_id = Some(original_id.to_canonical_string(true));
2042                        linkage.upgraded_id = Some(upgraded_id.to_canonical_string(true));
2043                        linkage.upgraded_version = Some(upgraded_version.value());
2044                        linkage
2045                    },
2046                )
2047                .collect();
2048
2049            self.package = Some(package);
2050        }
2051    }
2052}
2053
2054impl Merge<&crate::object::Data> for Object {
2055    fn merge(&mut self, source: &crate::object::Data, mask: &FieldMaskTree) {
2056        match source {
2057            crate::object::Data::Move(object) => self.merge(object, mask),
2058            crate::object::Data::Package(package) => self.merge(package, mask),
2059        }
2060    }
2061}
2062
2063//
2064// TypeOrigin
2065//
2066
2067impl From<crate::move_package::TypeOrigin> for TypeOrigin {
2068    fn from(value: crate::move_package::TypeOrigin) -> Self {
2069        let mut message = Self::default();
2070        message.module_name = Some(value.module_name.to_string());
2071        message.datatype_name = Some(value.datatype_name.to_string());
2072        message.package_id = Some(value.package.to_canonical_string(true));
2073        message
2074    }
2075}
2076
2077//
2078// GenesisObject
2079//
2080
2081impl From<crate::transaction::GenesisObject> for Object {
2082    fn from(value: crate::transaction::GenesisObject) -> Self {
2083        let crate::transaction::GenesisObject::RawObject { data, owner } = value;
2084        let mut message = Self::default();
2085        message.owner = Some(owner.into());
2086
2087        message.merge(&data, &FieldMaskTree::new_wildcard());
2088
2089        message
2090    }
2091}
2092
2093//
2094// ObjectReference
2095//
2096
2097pub trait ObjectRefExt {
2098    fn to_proto(self) -> ObjectReference;
2099}
2100
2101pub trait ObjectReferenceExt {
2102    fn try_to_object_ref(&self) -> Result<crate::base_types::ObjectRef, anyhow::Error>;
2103}
2104
2105impl ObjectRefExt for crate::base_types::ObjectRef {
2106    fn to_proto(self) -> ObjectReference {
2107        let (object_id, version, digest) = self;
2108        let mut message = ObjectReference::default();
2109        message.object_id = Some(object_id.to_canonical_string(true));
2110        message.version = Some(version.value());
2111        message.digest = Some(digest.to_string());
2112        message
2113    }
2114}
2115
2116impl ObjectReferenceExt for ObjectReference {
2117    fn try_to_object_ref(&self) -> Result<crate::base_types::ObjectRef, anyhow::Error> {
2118        use anyhow::Context;
2119
2120        let object_id = self
2121            .object_id_opt()
2122            .ok_or_else(|| anyhow::anyhow!("missing object_id"))?;
2123        let object_id = crate::base_types::ObjectID::from_hex_literal(object_id)
2124            .with_context(|| format!("Failed to parse object_id: {}", object_id))?;
2125
2126        let version = self
2127            .version_opt()
2128            .ok_or_else(|| anyhow::anyhow!("missing version"))?;
2129        let version = crate::base_types::SequenceNumber::from(version);
2130
2131        let digest = self
2132            .digest_opt()
2133            .ok_or_else(|| anyhow::anyhow!("missing digest"))?;
2134        let digest = digest
2135            .parse::<crate::digests::ObjectDigest>()
2136            .with_context(|| format!("Failed to parse digest: {}", digest))?;
2137
2138        Ok((object_id, version, digest))
2139    }
2140}
2141
2142impl From<&crate::storage::ObjectKey> for ObjectReference {
2143    fn from(value: &crate::storage::ObjectKey) -> Self {
2144        Self::default()
2145            .with_object_id(value.0.to_canonical_string(true))
2146            .with_version(value.1.value())
2147    }
2148}
2149
2150//
2151// Owner
2152//
2153
2154impl From<crate::object::Owner> for Owner {
2155    fn from(value: crate::object::Owner) -> Self {
2156        use crate::object::Owner as O;
2157        use owner::OwnerKind;
2158
2159        let mut message = Self::default();
2160
2161        let kind = match value {
2162            O::AddressOwner(address) => {
2163                message.address = Some(address.to_string());
2164                OwnerKind::Address
2165            }
2166            O::ObjectOwner(address) => {
2167                message.address = Some(address.to_string());
2168                OwnerKind::Object
2169            }
2170            O::Shared {
2171                initial_shared_version,
2172            } => {
2173                message.version = Some(initial_shared_version.value());
2174                OwnerKind::Shared
2175            }
2176            O::Immutable => OwnerKind::Immutable,
2177            O::ConsensusAddressOwner {
2178                start_version,
2179                owner,
2180            } => {
2181                message.version = Some(start_version.value());
2182                message.address = Some(owner.to_string());
2183                OwnerKind::ConsensusAddress
2184            }
2185            // TODO(Party WIP)
2186            O::Party { .. } => todo!("Party WIP"),
2187        };
2188
2189        message.set_kind(kind);
2190        message
2191    }
2192}
2193
2194//
2195// Transaction
2196//
2197
2198impl From<crate::transaction::TransactionData> for Transaction {
2199    fn from(value: crate::transaction::TransactionData) -> Self {
2200        Self::merge_from(&value, &FieldMaskTree::new_wildcard())
2201    }
2202}
2203
2204impl Merge<&crate::transaction::TransactionData> for Transaction {
2205    fn merge(&mut self, source: &crate::transaction::TransactionData, mask: &FieldMaskTree) {
2206        if mask.contains(Self::BCS_FIELD.name) {
2207            let mut bcs = Bcs::serialize(&source).unwrap();
2208            bcs.name = Some("TransactionData".to_owned());
2209            self.bcs = Some(bcs);
2210        }
2211
2212        if mask.contains(Self::DIGEST_FIELD.name) {
2213            self.digest = Some(source.digest().to_string());
2214        }
2215
2216        if mask.contains(Self::VERSION_FIELD.name) {
2217            self.version = Some(1);
2218        }
2219
2220        let crate::transaction::TransactionData::V1(source) = source;
2221
2222        if mask.contains(Self::KIND_FIELD.name) {
2223            self.kind = Some(source.kind.clone().into());
2224        }
2225
2226        if mask.contains(Self::SENDER_FIELD.name) {
2227            self.sender = Some(source.sender.to_string());
2228        }
2229
2230        if mask.contains(Self::GAS_PAYMENT_FIELD.name) {
2231            self.gas_payment = Some((&source.gas_data).into());
2232        }
2233
2234        if mask.contains(Self::EXPIRATION_FIELD.name) {
2235            self.expiration = Some(source.expiration.into());
2236        }
2237    }
2238}
2239
2240//
2241// GasPayment
2242//
2243
2244impl From<&crate::transaction::GasData> for GasPayment {
2245    fn from(value: &crate::transaction::GasData) -> Self {
2246        let mut message = Self::default();
2247        message.objects = value
2248            .payment
2249            .iter()
2250            .map(|obj_ref| obj_ref.to_proto())
2251            .collect();
2252        message.owner = Some(value.owner.to_string());
2253        message.price = Some(value.price);
2254        message.budget = Some(value.budget);
2255        message
2256    }
2257}
2258
2259//
2260// TransactionExpiration
2261//
2262
2263impl From<crate::transaction::TransactionExpiration> for TransactionExpiration {
2264    fn from(value: crate::transaction::TransactionExpiration) -> Self {
2265        use crate::transaction::TransactionExpiration as E;
2266        use transaction_expiration::TransactionExpirationKind;
2267
2268        let mut message = Self::default();
2269
2270        let kind = match value {
2271            E::None => TransactionExpirationKind::None,
2272            E::Epoch(epoch) => {
2273                message.epoch = Some(epoch);
2274                TransactionExpirationKind::Epoch
2275            }
2276            E::ValidDuring {
2277                min_epoch,
2278                max_epoch,
2279                min_timestamp,
2280                max_timestamp,
2281                chain,
2282                nonce,
2283            } => {
2284                message.epoch = max_epoch;
2285                message.min_epoch = min_epoch;
2286                message.min_timestamp = min_timestamp.map(ms_to_timestamp);
2287                message.max_timestamp = max_timestamp.map(ms_to_timestamp);
2288                message.set_chain(sui_sdk_types::Digest::new(*chain.as_bytes()));
2289                message.set_nonce(nonce);
2290
2291                TransactionExpirationKind::ValidDuring
2292            }
2293        };
2294
2295        message.set_kind(kind);
2296        message
2297    }
2298}
2299
2300impl TryFrom<&TransactionExpiration> for crate::transaction::TransactionExpiration {
2301    type Error = &'static str;
2302
2303    fn try_from(value: &TransactionExpiration) -> Result<Self, Self::Error> {
2304        use transaction_expiration::TransactionExpirationKind;
2305
2306        Ok(match value.kind() {
2307            TransactionExpirationKind::None => Self::None,
2308            TransactionExpirationKind::Epoch => Self::Epoch(value.epoch()),
2309            TransactionExpirationKind::ValidDuring => {
2310                let chain_str = value
2311                    .chain
2312                    .as_deref()
2313                    .ok_or("ValidDuring expiration is missing chain")?;
2314                let chain_digest: sui_sdk_types::Digest = chain_str
2315                    .parse()
2316                    .map_err(|_| "ValidDuring expiration has invalid chain digest")?;
2317                let chain = crate::digests::ChainIdentifier::from(
2318                    crate::digests::CheckpointDigest::new(chain_digest.into_inner()),
2319                );
2320                let nonce = value
2321                    .nonce
2322                    .ok_or("ValidDuring expiration is missing nonce")?;
2323                let min_timestamp = value
2324                    .min_timestamp
2325                    .as_ref()
2326                    .map(timestamp_to_ms)
2327                    .transpose()?;
2328                let max_timestamp = value
2329                    .max_timestamp
2330                    .as_ref()
2331                    .map(timestamp_to_ms)
2332                    .transpose()?;
2333                Self::ValidDuring {
2334                    min_epoch: value.min_epoch,
2335                    max_epoch: value.epoch,
2336                    min_timestamp,
2337                    max_timestamp,
2338                    chain,
2339                    nonce,
2340                }
2341            }
2342            TransactionExpirationKind::Unknown | _ => {
2343                return Err("unknown TransactionExpirationKind");
2344            }
2345        })
2346    }
2347}
2348
2349//
2350// TransactionKind
2351//
2352
2353impl From<crate::transaction::TransactionKind> for TransactionKind {
2354    fn from(value: crate::transaction::TransactionKind) -> Self {
2355        use crate::transaction::TransactionKind as K;
2356        use transaction_kind::Kind;
2357
2358        let message = Self::default();
2359
2360        match value {
2361            K::ProgrammableTransaction(ptb) => message
2362                .with_programmable_transaction(ptb)
2363                .with_kind(Kind::ProgrammableTransaction),
2364            K::ChangeEpoch(change_epoch) => message
2365                .with_change_epoch(change_epoch)
2366                .with_kind(Kind::ChangeEpoch),
2367            K::Genesis(genesis) => message.with_genesis(genesis).with_kind(Kind::Genesis),
2368            K::ConsensusCommitPrologue(prologue) => message
2369                .with_consensus_commit_prologue(prologue)
2370                .with_kind(Kind::ConsensusCommitPrologueV1),
2371            K::AuthenticatorStateUpdate(update) => message
2372                .with_authenticator_state_update(update)
2373                .with_kind(Kind::AuthenticatorStateUpdate),
2374            K::EndOfEpochTransaction(transactions) => message
2375                .with_end_of_epoch({
2376                    EndOfEpochTransaction::default()
2377                        .with_transactions(transactions.into_iter().map(Into::into).collect())
2378                })
2379                .with_kind(Kind::EndOfEpoch),
2380            K::RandomnessStateUpdate(update) => message
2381                .with_randomness_state_update(update)
2382                .with_kind(Kind::RandomnessStateUpdate),
2383            K::ConsensusCommitPrologueV2(prologue) => message
2384                .with_consensus_commit_prologue(prologue)
2385                .with_kind(Kind::ConsensusCommitPrologueV2),
2386            K::ConsensusCommitPrologueV3(prologue) => message
2387                .with_consensus_commit_prologue(prologue)
2388                .with_kind(Kind::ConsensusCommitPrologueV3),
2389            K::ConsensusCommitPrologueV4(prologue) => message
2390                .with_consensus_commit_prologue(prologue)
2391                .with_kind(Kind::ConsensusCommitPrologueV4),
2392            K::ProgrammableSystemTransaction(ptb) => message
2393                .with_programmable_transaction(ptb)
2394                .with_kind(Kind::ProgrammableSystemTransaction),
2395        }
2396    }
2397}
2398
2399//
2400// ConsensusCommitPrologue
2401//
2402
2403impl From<crate::messages_consensus::ConsensusCommitPrologue> for ConsensusCommitPrologue {
2404    fn from(value: crate::messages_consensus::ConsensusCommitPrologue) -> Self {
2405        let mut message = Self::default();
2406        message.epoch = Some(value.epoch);
2407        message.round = Some(value.round);
2408        message.commit_timestamp = Some(sui_rpc::proto::timestamp_ms_to_proto(
2409            value.commit_timestamp_ms,
2410        ));
2411        message
2412    }
2413}
2414
2415impl From<crate::messages_consensus::ConsensusCommitPrologueV2> for ConsensusCommitPrologue {
2416    fn from(value: crate::messages_consensus::ConsensusCommitPrologueV2) -> Self {
2417        let mut message = Self::default();
2418        message.epoch = Some(value.epoch);
2419        message.round = Some(value.round);
2420        message.commit_timestamp = Some(sui_rpc::proto::timestamp_ms_to_proto(
2421            value.commit_timestamp_ms,
2422        ));
2423        message.consensus_commit_digest = Some(value.consensus_commit_digest.to_string());
2424        message
2425    }
2426}
2427
2428impl From<crate::messages_consensus::ConsensusCommitPrologueV3> for ConsensusCommitPrologue {
2429    fn from(value: crate::messages_consensus::ConsensusCommitPrologueV3) -> Self {
2430        let mut message = Self::default();
2431        message.epoch = Some(value.epoch);
2432        message.round = Some(value.round);
2433        message.commit_timestamp = Some(sui_rpc::proto::timestamp_ms_to_proto(
2434            value.commit_timestamp_ms,
2435        ));
2436        message.consensus_commit_digest = Some(value.consensus_commit_digest.to_string());
2437        message.sub_dag_index = value.sub_dag_index;
2438        message.consensus_determined_version_assignments =
2439            Some(value.consensus_determined_version_assignments.into());
2440        message
2441    }
2442}
2443
2444impl From<crate::messages_consensus::ConsensusCommitPrologueV4> for ConsensusCommitPrologue {
2445    fn from(
2446        crate::messages_consensus::ConsensusCommitPrologueV4 {
2447            epoch,
2448            round,
2449            sub_dag_index,
2450            commit_timestamp_ms,
2451            consensus_commit_digest,
2452            consensus_determined_version_assignments,
2453            additional_state_digest,
2454        }: crate::messages_consensus::ConsensusCommitPrologueV4,
2455    ) -> Self {
2456        let mut message = Self::default();
2457        message.epoch = Some(epoch);
2458        message.round = Some(round);
2459        message.commit_timestamp = Some(sui_rpc::proto::timestamp_ms_to_proto(commit_timestamp_ms));
2460        message.consensus_commit_digest = Some(consensus_commit_digest.to_string());
2461        message.sub_dag_index = sub_dag_index;
2462        message.consensus_determined_version_assignments =
2463            Some(consensus_determined_version_assignments.into());
2464        message.additional_state_digest = Some(additional_state_digest.to_string());
2465        message
2466    }
2467}
2468
2469//
2470// ConsensusDeterminedVersionAssignments
2471//
2472
2473impl From<crate::messages_consensus::ConsensusDeterminedVersionAssignments>
2474    for ConsensusDeterminedVersionAssignments
2475{
2476    fn from(value: crate::messages_consensus::ConsensusDeterminedVersionAssignments) -> Self {
2477        use crate::messages_consensus::ConsensusDeterminedVersionAssignments as A;
2478
2479        let mut message = Self::default();
2480
2481        let version = match value {
2482            A::CancelledTransactions(canceled_transactions) => {
2483                message.canceled_transactions = canceled_transactions
2484                    .into_iter()
2485                    .map(|(tx_digest, assignments)| {
2486                        let mut message = CanceledTransaction::default();
2487                        message.digest = Some(tx_digest.to_string());
2488                        message.version_assignments = assignments
2489                            .into_iter()
2490                            .map(|(id, version)| {
2491                                let mut message = VersionAssignment::default();
2492                                message.object_id = Some(id.to_canonical_string(true));
2493                                message.version = Some(version.value());
2494                                message
2495                            })
2496                            .collect();
2497                        message
2498                    })
2499                    .collect();
2500                1
2501            }
2502            A::CancelledTransactionsV2(canceled_transactions) => {
2503                message.canceled_transactions = canceled_transactions
2504                    .into_iter()
2505                    .map(|(tx_digest, assignments)| {
2506                        let mut message = CanceledTransaction::default();
2507                        message.digest = Some(tx_digest.to_string());
2508                        message.version_assignments = assignments
2509                            .into_iter()
2510                            .map(|((id, start_version), version)| {
2511                                let mut message = VersionAssignment::default();
2512                                message.object_id = Some(id.to_canonical_string(true));
2513                                message.start_version = Some(start_version.value());
2514                                message.version = Some(version.value());
2515                                message
2516                            })
2517                            .collect();
2518                        message
2519                    })
2520                    .collect();
2521                2
2522            }
2523        };
2524
2525        message.version = Some(version);
2526        message
2527    }
2528}
2529
2530//
2531// GenesisTransaction
2532//
2533
2534impl From<crate::transaction::GenesisTransaction> for GenesisTransaction {
2535    fn from(value: crate::transaction::GenesisTransaction) -> Self {
2536        let mut message = Self::default();
2537        message.objects = value.objects.into_iter().map(Into::into).collect();
2538        message
2539    }
2540}
2541
2542//
2543// RandomnessStateUpdate
2544//
2545
2546impl From<crate::transaction::RandomnessStateUpdate> for RandomnessStateUpdate {
2547    fn from(value: crate::transaction::RandomnessStateUpdate) -> Self {
2548        let mut message = Self::default();
2549        message.epoch = Some(value.epoch);
2550        message.randomness_round = Some(value.randomness_round.0);
2551        message.random_bytes = Some(value.random_bytes.into());
2552        message.randomness_object_initial_shared_version =
2553            Some(value.randomness_obj_initial_shared_version.value());
2554        message
2555    }
2556}
2557
2558//
2559// AuthenticatorStateUpdate
2560//
2561
2562impl From<crate::transaction::AuthenticatorStateUpdate> for AuthenticatorStateUpdate {
2563    fn from(value: crate::transaction::AuthenticatorStateUpdate) -> Self {
2564        let mut message = Self::default();
2565        message.epoch = Some(value.epoch);
2566        message.round = Some(value.round);
2567        message.new_active_jwks = value.new_active_jwks.into_iter().map(Into::into).collect();
2568        message.authenticator_object_initial_shared_version =
2569            Some(value.authenticator_obj_initial_shared_version.value());
2570        message
2571    }
2572}
2573
2574//
2575// ActiveJwk
2576//
2577
2578impl From<crate::authenticator_state::ActiveJwk> for ActiveJwk {
2579    fn from(value: crate::authenticator_state::ActiveJwk) -> Self {
2580        let mut jwk_id = JwkId::default();
2581        jwk_id.iss = Some(value.jwk_id.iss);
2582        jwk_id.kid = Some(value.jwk_id.kid);
2583
2584        let mut jwk = Jwk::default();
2585        jwk.kty = Some(value.jwk.kty);
2586        jwk.e = Some(value.jwk.e);
2587        jwk.n = Some(value.jwk.n);
2588        jwk.alg = Some(value.jwk.alg);
2589
2590        let mut message = Self::default();
2591        message.id = Some(jwk_id);
2592        message.jwk = Some(jwk);
2593        message.epoch = Some(value.epoch);
2594        message
2595    }
2596}
2597
2598//
2599// ChangeEpoch
2600//
2601
2602impl From<crate::transaction::ChangeEpoch> for ChangeEpoch {
2603    fn from(value: crate::transaction::ChangeEpoch) -> Self {
2604        let mut message = Self::default();
2605        message.epoch = Some(value.epoch);
2606        message.protocol_version = Some(value.protocol_version.as_u64());
2607        message.storage_charge = Some(value.storage_charge);
2608        message.computation_charge = Some(value.computation_charge);
2609        message.storage_rebate = Some(value.storage_rebate);
2610        message.non_refundable_storage_fee = Some(value.non_refundable_storage_fee);
2611        message.epoch_start_timestamp = Some(sui_rpc::proto::timestamp_ms_to_proto(
2612            value.epoch_start_timestamp_ms,
2613        ));
2614        message.system_packages = value
2615            .system_packages
2616            .into_iter()
2617            .map(|(version, modules, dependencies)| {
2618                let mut message = SystemPackage::default();
2619                message.version = Some(version.value());
2620                message.modules = modules.into_iter().map(Into::into).collect();
2621                message.dependencies = dependencies
2622                    .iter()
2623                    .map(|d| d.to_canonical_string(true))
2624                    .collect();
2625                message
2626            })
2627            .collect();
2628        message
2629    }
2630}
2631
2632//
2633// EndOfEpochTransactionkind
2634//
2635
2636impl From<crate::transaction::EndOfEpochTransactionKind> for EndOfEpochTransactionKind {
2637    fn from(value: crate::transaction::EndOfEpochTransactionKind) -> Self {
2638        use crate::transaction::EndOfEpochTransactionKind as K;
2639        use end_of_epoch_transaction_kind::Kind;
2640
2641        let message = Self::default();
2642
2643        match value {
2644            K::ChangeEpoch(change_epoch) => message
2645                .with_change_epoch(change_epoch)
2646                .with_kind(Kind::ChangeEpoch),
2647            K::AuthenticatorStateCreate => message.with_kind(Kind::AuthenticatorStateCreate),
2648            K::AuthenticatorStateExpire(expire) => message
2649                .with_authenticator_state_expire(expire)
2650                .with_kind(Kind::AuthenticatorStateExpire),
2651            K::RandomnessStateCreate => message.with_kind(Kind::RandomnessStateCreate),
2652            K::DenyListStateCreate => message.with_kind(Kind::DenyListStateCreate),
2653            K::BridgeStateCreate(chain_id) => message
2654                .with_bridge_chain_id(chain_id.to_string())
2655                .with_kind(Kind::BridgeStateCreate),
2656            K::BridgeCommitteeInit(bridge_object_version) => message
2657                .with_bridge_object_version(bridge_object_version.into())
2658                .with_kind(Kind::BridgeCommitteeInit),
2659            K::StoreExecutionTimeObservations(observations) => message
2660                .with_execution_time_observations(observations)
2661                .with_kind(Kind::StoreExecutionTimeObservations),
2662            K::AccumulatorRootCreate => message.with_kind(Kind::AccumulatorRootCreate),
2663            K::CoinRegistryCreate => message.with_kind(Kind::CoinRegistryCreate),
2664            K::DisplayRegistryCreate => message.with_kind(Kind::DisplayRegistryCreate),
2665            K::AddressAliasStateCreate => message.with_kind(Kind::AddressAliasStateCreate),
2666            K::WriteAccumulatorStorageCost(storage_cost) => message
2667                .with_kind(Kind::WriteAccumulatorStorageCost)
2668                .with_storage_cost(storage_cost.storage_cost),
2669        }
2670    }
2671}
2672
2673//
2674// AuthenticatorStateExpire
2675//
2676
2677impl From<crate::transaction::AuthenticatorStateExpire> for AuthenticatorStateExpire {
2678    fn from(value: crate::transaction::AuthenticatorStateExpire) -> Self {
2679        let mut message = Self::default();
2680        message.min_epoch = Some(value.min_epoch);
2681        message.authenticator_object_initial_shared_version =
2682            Some(value.authenticator_obj_initial_shared_version.value());
2683        message
2684    }
2685}
2686
2687// ExecutionTimeObservations
2688
2689impl From<crate::transaction::StoredExecutionTimeObservations> for ExecutionTimeObservations {
2690    fn from(value: crate::transaction::StoredExecutionTimeObservations) -> Self {
2691        let mut message = Self::default();
2692        match value {
2693            crate::transaction::StoredExecutionTimeObservations::V1(vec) => {
2694                message.version = Some(1);
2695                message.observations = vec
2696                    .into_iter()
2697                    .map(|(key, observation)| {
2698                        use crate::execution::ExecutionTimeObservationKey as K;
2699                        use execution_time_observation::ExecutionTimeObservationKind;
2700
2701                        let mut message = ExecutionTimeObservation::default();
2702
2703                        let kind = match key {
2704                            K::MoveEntryPoint {
2705                                package,
2706                                module,
2707                                function,
2708                                type_arguments,
2709                            } => {
2710                                message.move_entry_point = Some({
2711                                    let mut message = MoveCall::default();
2712                                    message.package = Some(package.to_canonical_string(true));
2713                                    message.module = Some(module);
2714                                    message.function = Some(function);
2715                                    message.type_arguments = type_arguments
2716                                        .into_iter()
2717                                        .map(|ty| ty.to_canonical_string(true))
2718                                        .collect();
2719                                    message
2720                                });
2721                                ExecutionTimeObservationKind::MoveEntryPoint
2722                            }
2723                            K::TransferObjects => ExecutionTimeObservationKind::TransferObjects,
2724                            K::SplitCoins => ExecutionTimeObservationKind::SplitCoins,
2725                            K::MergeCoins => ExecutionTimeObservationKind::MergeCoins,
2726                            K::Publish => ExecutionTimeObservationKind::Publish,
2727                            K::MakeMoveVec => ExecutionTimeObservationKind::MakeMoveVector,
2728                            K::Upgrade => ExecutionTimeObservationKind::Upgrade,
2729                        };
2730
2731                        message.validator_observations = observation
2732                            .into_iter()
2733                            .map(|(name, duration)| {
2734                                let mut message = ValidatorExecutionTimeObservation::default();
2735                                message.validator = Some(name.0.to_vec().into());
2736                                message.duration = Some(prost_types::Duration {
2737                                    seconds: duration.as_secs() as i64,
2738                                    nanos: duration.subsec_nanos() as i32,
2739                                });
2740                                message
2741                            })
2742                            .collect();
2743
2744                        message.set_kind(kind);
2745                        message
2746                    })
2747                    .collect();
2748            }
2749        }
2750
2751        message
2752    }
2753}
2754
2755//
2756// ProgrammableTransaction
2757//
2758
2759impl From<crate::transaction::ProgrammableTransaction> for ProgrammableTransaction {
2760    fn from(value: crate::transaction::ProgrammableTransaction) -> Self {
2761        let mut message = Self::default();
2762        message.inputs = value.inputs.into_iter().map(Into::into).collect();
2763        message.commands = value.commands.into_iter().map(Into::into).collect();
2764        message
2765    }
2766}
2767
2768//
2769// Input
2770//
2771
2772impl From<crate::transaction::CallArg> for Input {
2773    fn from(value: crate::transaction::CallArg) -> Self {
2774        use crate::transaction::CallArg as I;
2775        use crate::transaction::ObjectArg as O;
2776        use input::InputKind;
2777        use input::Mutability;
2778
2779        let mut message = Self::default();
2780
2781        let kind = match value {
2782            I::Pure(value) => {
2783                message.pure = Some(value.into());
2784                InputKind::Pure
2785            }
2786            I::Object(o) => match o {
2787                O::ImmOrOwnedObject((id, version, digest)) => {
2788                    message.object_id = Some(id.to_canonical_string(true));
2789                    message.version = Some(version.value());
2790                    message.digest = Some(digest.to_string());
2791                    InputKind::ImmutableOrOwned
2792                }
2793                O::SharedObject {
2794                    id,
2795                    initial_shared_version,
2796                    mutability,
2797                } => {
2798                    message.object_id = Some(id.to_canonical_string(true));
2799                    message.version = Some(initial_shared_version.value());
2800                    message.mutable = Some(mutability.is_exclusive());
2801                    message.set_mutability(match mutability {
2802                        crate::transaction::SharedObjectMutability::Immutable => {
2803                            Mutability::Immutable
2804                        }
2805                        crate::transaction::SharedObjectMutability::Mutable => Mutability::Mutable,
2806                        crate::transaction::SharedObjectMutability::NonExclusiveWrite => {
2807                            Mutability::NonExclusiveWrite
2808                        }
2809                    });
2810                    InputKind::Shared
2811                }
2812                O::Receiving((id, version, digest)) => {
2813                    message.object_id = Some(id.to_canonical_string(true));
2814                    message.version = Some(version.value());
2815                    message.digest = Some(digest.to_string());
2816                    InputKind::Receiving
2817                }
2818            },
2819            I::FundsWithdrawal(withdrawal) => {
2820                message.set_funds_withdrawal(withdrawal);
2821                InputKind::FundsWithdrawal
2822            }
2823        };
2824
2825        message.set_kind(kind);
2826        message
2827    }
2828}
2829
2830impl From<crate::transaction::FundsWithdrawalArg> for FundsWithdrawal {
2831    fn from(value: crate::transaction::FundsWithdrawalArg) -> Self {
2832        use funds_withdrawal::Source;
2833
2834        let mut message = Self::default();
2835
2836        message.amount = match value.reservation {
2837            crate::transaction::Reservation::MaxAmountU64(amount) => Some(amount),
2838        };
2839        let crate::transaction::WithdrawalTypeArg::Balance(coin_type) = value.type_arg;
2840        message.coin_type = Some(coin_type.to_canonical_string(true));
2841        message.set_source(match value.withdraw_from {
2842            crate::transaction::WithdrawFrom::Sender => Source::Sender,
2843            crate::transaction::WithdrawFrom::Sponsor => Source::Sponsor,
2844        });
2845
2846        message
2847    }
2848}
2849
2850//
2851// Argument
2852//
2853
2854impl From<crate::transaction::Argument> for Argument {
2855    fn from(value: crate::transaction::Argument) -> Self {
2856        use crate::transaction::Argument as A;
2857        use argument::ArgumentKind;
2858
2859        let mut message = Self::default();
2860
2861        let kind = match value {
2862            A::GasCoin => ArgumentKind::Gas,
2863            A::Input(input) => {
2864                message.input = Some(input.into());
2865                ArgumentKind::Input
2866            }
2867            A::Result(result) => {
2868                message.result = Some(result.into());
2869                ArgumentKind::Result
2870            }
2871            A::NestedResult(result, subresult) => {
2872                message.result = Some(result.into());
2873                message.subresult = Some(subresult.into());
2874                ArgumentKind::Result
2875            }
2876        };
2877
2878        message.set_kind(kind);
2879        message
2880    }
2881}
2882
2883//
2884// Command
2885//
2886
2887impl From<crate::transaction::Command> for Command {
2888    fn from(value: crate::transaction::Command) -> Self {
2889        use crate::transaction::Command as C;
2890        use command::Command;
2891
2892        let command = match value {
2893            C::MoveCall(move_call) => Command::MoveCall((*move_call).into()),
2894            C::TransferObjects(objects, address) => Command::TransferObjects({
2895                let mut message = TransferObjects::default();
2896                message.objects = objects.into_iter().map(Into::into).collect();
2897                message.address = Some(address.into());
2898                message
2899            }),
2900            C::SplitCoins(coin, amounts) => Command::SplitCoins({
2901                let mut message = SplitCoins::default();
2902                message.coin = Some(coin.into());
2903                message.amounts = amounts.into_iter().map(Into::into).collect();
2904                message
2905            }),
2906            C::MergeCoins(coin, coins_to_merge) => Command::MergeCoins({
2907                let mut message = MergeCoins::default();
2908                message.coin = Some(coin.into());
2909                message.coins_to_merge = coins_to_merge.into_iter().map(Into::into).collect();
2910                message
2911            }),
2912            C::Publish(modules, dependencies) => Command::Publish({
2913                let mut message = Publish::default();
2914                message.modules = modules.into_iter().map(Into::into).collect();
2915                message.dependencies = dependencies
2916                    .iter()
2917                    .map(|d| d.to_canonical_string(true))
2918                    .collect();
2919                message
2920            }),
2921            C::MakeMoveVec(element_type, elements) => Command::MakeMoveVector({
2922                let mut message = MakeMoveVector::default();
2923                message.element_type = element_type.map(|t| t.to_canonical_string(true));
2924                message.elements = elements.into_iter().map(Into::into).collect();
2925                message
2926            }),
2927            C::Upgrade(modules, dependencies, package, ticket) => Command::Upgrade({
2928                let mut message = Upgrade::default();
2929                message.modules = modules.into_iter().map(Into::into).collect();
2930                message.dependencies = dependencies
2931                    .iter()
2932                    .map(|d| d.to_canonical_string(true))
2933                    .collect();
2934                message.package = Some(package.to_canonical_string(true));
2935                message.ticket = Some(ticket.into());
2936                message
2937            }),
2938        };
2939
2940        let mut message = Self::default();
2941        message.command = Some(command);
2942        message
2943    }
2944}
2945
2946//
2947// MoveCall
2948//
2949
2950impl From<crate::transaction::ProgrammableMoveCall> for MoveCall {
2951    fn from(value: crate::transaction::ProgrammableMoveCall) -> Self {
2952        let mut message = Self::default();
2953        message.package = Some(value.package.to_canonical_string(true));
2954        message.module = Some(value.module.to_string());
2955        message.function = Some(value.function.to_string());
2956        message.type_arguments = value
2957            .type_arguments
2958            .iter()
2959            .map(|t| t.to_canonical_string(true))
2960            .collect();
2961        message.arguments = value.arguments.into_iter().map(Into::into).collect();
2962        message
2963    }
2964}
2965
2966//
2967// TransactionEffects
2968//
2969
2970impl From<crate::effects::TransactionEffects> for TransactionEffects {
2971    fn from(value: crate::effects::TransactionEffects) -> Self {
2972        Self::merge_from(&value, &FieldMaskTree::new_wildcard())
2973    }
2974}
2975
2976impl Merge<&crate::effects::TransactionEffects> for TransactionEffects {
2977    fn merge(&mut self, source: &crate::effects::TransactionEffects, mask: &FieldMaskTree) {
2978        if mask.contains(Self::BCS_FIELD.name) {
2979            let mut bcs = Bcs::serialize(&source).unwrap();
2980            bcs.name = Some("TransactionEffects".to_owned());
2981            self.bcs = Some(bcs);
2982        }
2983
2984        if mask.contains(Self::DIGEST_FIELD.name) {
2985            self.digest = Some(source.digest().to_string());
2986        }
2987
2988        match source {
2989            crate::effects::TransactionEffects::V1(v1) => self.merge(v1, mask),
2990            crate::effects::TransactionEffects::V2(v2) => self.merge(v2, mask),
2991        }
2992    }
2993}
2994
2995//
2996// TransactionEffectsV1
2997//
2998
2999impl Merge<&crate::effects::TransactionEffectsV1> for TransactionEffects {
3000    fn merge(&mut self, value: &crate::effects::TransactionEffectsV1, mask: &FieldMaskTree) {
3001        use crate::effects::TransactionEffectsAPI;
3002
3003        if mask.contains(Self::VERSION_FIELD.name) {
3004            self.version = Some(1);
3005        }
3006
3007        if mask.contains(Self::STATUS_FIELD.name) {
3008            self.status = Some(value.status().clone().into());
3009        }
3010
3011        if mask.contains(Self::EPOCH_FIELD.name) {
3012            self.epoch = Some(value.executed_epoch());
3013        }
3014
3015        if mask.contains(Self::GAS_USED_FIELD.name) {
3016            self.gas_used = Some(value.gas_cost_summary().clone().into());
3017        }
3018
3019        if mask.contains(Self::TRANSACTION_DIGEST_FIELD.name) {
3020            self.transaction_digest = Some(value.transaction_digest().to_string());
3021        }
3022
3023        if mask.contains(Self::EVENTS_DIGEST_FIELD.name) {
3024            self.events_digest = value.events_digest().map(|d| d.to_string());
3025        }
3026
3027        if mask.contains(Self::DEPENDENCIES_FIELD.name) {
3028            self.dependencies = value
3029                .dependencies()
3030                .iter()
3031                .map(ToString::to_string)
3032                .collect();
3033        }
3034
3035        if mask.contains(Self::CHANGED_OBJECTS_FIELD.name)
3036            || mask.contains(Self::UNCHANGED_CONSENSUS_OBJECTS_FIELD.name)
3037            || mask.contains(Self::GAS_OBJECT_FIELD.name)
3038        {
3039            let mut changed_objects = Vec::new();
3040            let mut unchanged_consensus_objects = Vec::new();
3041
3042            for ((id, version, digest), owner) in value.created() {
3043                let mut change = ChangedObject::default();
3044                change.object_id = Some(id.to_canonical_string(true));
3045                change.input_state = Some(changed_object::InputObjectState::DoesNotExist.into());
3046                change.output_state = Some(changed_object::OutputObjectState::ObjectWrite.into());
3047                change.output_version = Some(version.value());
3048                change.output_digest = Some(digest.to_string());
3049                change.output_owner = Some(owner.clone().into());
3050                change.id_operation = Some(changed_object::IdOperation::Created.into());
3051
3052                changed_objects.push(change);
3053            }
3054
3055            for ((id, version, digest), owner) in value.mutated() {
3056                let mut change = ChangedObject::default();
3057                change.object_id = Some(id.to_canonical_string(true));
3058                change.input_state = Some(changed_object::InputObjectState::Exists.into());
3059                change.output_state = Some(changed_object::OutputObjectState::ObjectWrite.into());
3060                change.output_version = Some(version.value());
3061                change.output_digest = Some(digest.to_string());
3062                change.output_owner = Some(owner.clone().into());
3063                change.id_operation = Some(changed_object::IdOperation::None.into());
3064
3065                changed_objects.push(change);
3066            }
3067
3068            for ((id, version, digest), owner) in value.unwrapped() {
3069                let mut change = ChangedObject::default();
3070                change.object_id = Some(id.to_canonical_string(true));
3071                change.input_state = Some(changed_object::InputObjectState::DoesNotExist.into());
3072                change.output_state = Some(changed_object::OutputObjectState::ObjectWrite.into());
3073                change.output_version = Some(version.value());
3074                change.output_digest = Some(digest.to_string());
3075                change.output_owner = Some(owner.clone().into());
3076                change.id_operation = Some(changed_object::IdOperation::None.into());
3077
3078                changed_objects.push(change);
3079            }
3080
3081            for (id, version, digest) in value.deleted() {
3082                let mut change = ChangedObject::default();
3083                change.object_id = Some(id.to_canonical_string(true));
3084                change.input_state = Some(changed_object::InputObjectState::Exists.into());
3085                change.output_state = Some(changed_object::OutputObjectState::DoesNotExist.into());
3086                change.output_version = Some(version.value());
3087                change.output_digest = Some(digest.to_string());
3088                change.id_operation = Some(changed_object::IdOperation::Deleted.into());
3089
3090                changed_objects.push(change);
3091            }
3092
3093            for (id, version, digest) in value.unwrapped_then_deleted() {
3094                let mut change = ChangedObject::default();
3095                change.object_id = Some(id.to_canonical_string(true));
3096                change.input_state = Some(changed_object::InputObjectState::DoesNotExist.into());
3097                change.output_state = Some(changed_object::OutputObjectState::DoesNotExist.into());
3098                change.output_version = Some(version.value());
3099                change.output_digest = Some(digest.to_string());
3100                change.id_operation = Some(changed_object::IdOperation::Deleted.into());
3101
3102                changed_objects.push(change);
3103            }
3104
3105            for (id, version, digest) in value.wrapped() {
3106                let mut change = ChangedObject::default();
3107                change.object_id = Some(id.to_canonical_string(true));
3108                change.input_state = Some(changed_object::InputObjectState::Exists.into());
3109                change.output_state = Some(changed_object::OutputObjectState::DoesNotExist.into());
3110                change.output_version = Some(version.value());
3111                change.output_digest = Some(digest.to_string());
3112                change.id_operation = Some(changed_object::IdOperation::Deleted.into());
3113
3114                changed_objects.push(change);
3115            }
3116
3117            for (object_id, version) in value.modified_at_versions() {
3118                let object_id = object_id.to_canonical_string(true);
3119                let version = version.value();
3120                if let Some(changed_object) = changed_objects
3121                    .iter_mut()
3122                    .find(|object| object.object_id() == object_id)
3123                {
3124                    changed_object.input_version = Some(version);
3125                }
3126            }
3127
3128            for (id, version, digest) in value.shared_objects() {
3129                let object_id = id.to_canonical_string(true);
3130                let version = version.value();
3131                let digest = digest.to_string();
3132
3133                if let Some(changed_object) = changed_objects
3134                    .iter_mut()
3135                    .find(|object| object.object_id() == object_id)
3136                {
3137                    changed_object.input_version = Some(version);
3138                    changed_object.input_digest = Some(digest);
3139                } else {
3140                    let mut unchanged_consensus_object = UnchangedConsensusObject::default();
3141                    unchanged_consensus_object.kind = Some(
3142                        unchanged_consensus_object::UnchangedConsensusObjectKind::ReadOnlyRoot
3143                            .into(),
3144                    );
3145                    unchanged_consensus_object.object_id = Some(object_id);
3146                    unchanged_consensus_object.version = Some(version);
3147                    unchanged_consensus_object.digest = Some(digest);
3148
3149                    unchanged_consensus_objects.push(unchanged_consensus_object);
3150                }
3151            }
3152
3153            if mask.contains(Self::GAS_OBJECT_FIELD.name)
3154                && let Some(((gas_id, _, _), _)) = value.gas_object()
3155            {
3156                let gas_object_id = gas_id.to_canonical_string(true);
3157                self.gas_object = changed_objects
3158                    .iter()
3159                    .find(|object| object.object_id() == gas_object_id)
3160                    .cloned();
3161            }
3162
3163            if mask.contains(Self::CHANGED_OBJECTS_FIELD.name) {
3164                self.changed_objects = changed_objects;
3165            }
3166
3167            if mask.contains(Self::UNCHANGED_CONSENSUS_OBJECTS_FIELD.name) {
3168                self.unchanged_consensus_objects = unchanged_consensus_objects;
3169            }
3170        }
3171    }
3172}
3173
3174//
3175// TransactionEffectsV2
3176//
3177
3178impl Merge<&crate::effects::TransactionEffectsV2> for TransactionEffects {
3179    fn merge(
3180        &mut self,
3181        crate::effects::TransactionEffectsV2 {
3182            status,
3183            executed_epoch,
3184            gas_used,
3185            transaction_digest,
3186            gas_object_index,
3187            events_digest,
3188            dependencies,
3189            lamport_version,
3190            changed_objects,
3191            unchanged_consensus_objects,
3192            aux_data_digest,
3193        }: &crate::effects::TransactionEffectsV2,
3194        mask: &FieldMaskTree,
3195    ) {
3196        if mask.contains(Self::VERSION_FIELD.name) {
3197            self.version = Some(2);
3198        }
3199
3200        if mask.contains(Self::STATUS_FIELD.name) {
3201            self.status = Some(status.clone().into());
3202        }
3203
3204        if mask.contains(Self::EPOCH_FIELD.name) {
3205            self.epoch = Some(*executed_epoch);
3206        }
3207
3208        if mask.contains(Self::GAS_USED_FIELD.name) {
3209            self.gas_used = Some(gas_used.clone().into());
3210        }
3211
3212        if mask.contains(Self::TRANSACTION_DIGEST_FIELD.name) {
3213            self.transaction_digest = Some(transaction_digest.to_string());
3214        }
3215
3216        if mask.contains(Self::GAS_OBJECT_FIELD.name) {
3217            self.gas_object = gas_object_index
3218                .map(|index| {
3219                    changed_objects
3220                        .get(index as usize)
3221                        .cloned()
3222                        .map(|(id, change)| {
3223                            let mut message = ChangedObject::from(change);
3224                            message.object_id = Some(id.to_canonical_string(true));
3225                            message
3226                        })
3227                })
3228                .flatten();
3229        }
3230
3231        if mask.contains(Self::EVENTS_DIGEST_FIELD.name) {
3232            self.events_digest = events_digest.map(|d| d.to_string());
3233        }
3234
3235        if mask.contains(Self::DEPENDENCIES_FIELD.name) {
3236            self.dependencies = dependencies.iter().map(ToString::to_string).collect();
3237        }
3238
3239        if mask.contains(Self::LAMPORT_VERSION_FIELD.name) {
3240            self.lamport_version = Some(lamport_version.value());
3241        }
3242
3243        if mask.contains(Self::CHANGED_OBJECTS_FIELD.name) {
3244            self.changed_objects = changed_objects
3245                .clone()
3246                .into_iter()
3247                .map(|(id, change)| {
3248                    let mut message = ChangedObject::from(change);
3249                    message.object_id = Some(id.to_canonical_string(true));
3250                    message
3251                })
3252                .collect();
3253        }
3254
3255        for object in self.changed_objects.iter_mut().chain(&mut self.gas_object) {
3256            if object.output_digest.is_some() && object.output_version.is_none() {
3257                object.output_version = Some(lamport_version.value());
3258            }
3259        }
3260
3261        if mask.contains(Self::UNCHANGED_CONSENSUS_OBJECTS_FIELD.name) {
3262            self.unchanged_consensus_objects = unchanged_consensus_objects
3263                .clone()
3264                .into_iter()
3265                .map(|(id, unchanged)| {
3266                    let mut message = UnchangedConsensusObject::from(unchanged);
3267                    message.object_id = Some(id.to_canonical_string(true));
3268                    message
3269                })
3270                .collect();
3271        }
3272
3273        if mask.contains(Self::AUXILIARY_DATA_DIGEST_FIELD.name) {
3274            self.auxiliary_data_digest = aux_data_digest.map(|d| d.to_string());
3275        }
3276    }
3277}
3278
3279//
3280// ChangedObject
3281//
3282
3283impl From<crate::effects::EffectsObjectChange> for ChangedObject {
3284    fn from(value: crate::effects::EffectsObjectChange) -> Self {
3285        use crate::effects::ObjectIn;
3286        use crate::effects::ObjectOut;
3287        use changed_object::InputObjectState;
3288        use changed_object::OutputObjectState;
3289
3290        let mut message = Self::default();
3291
3292        // Input State
3293        let input_state = match value.input_state {
3294            ObjectIn::NotExist => InputObjectState::DoesNotExist,
3295            ObjectIn::Exist(((version, digest), owner)) => {
3296                message.input_version = Some(version.value());
3297                message.input_digest = Some(digest.to_string());
3298                message.input_owner = Some(owner.into());
3299                InputObjectState::Exists
3300            }
3301        };
3302        message.set_input_state(input_state);
3303
3304        // Output State
3305        let output_state = match value.output_state {
3306            ObjectOut::NotExist => OutputObjectState::DoesNotExist,
3307            ObjectOut::ObjectWrite((digest, owner)) => {
3308                message.output_digest = Some(digest.to_string());
3309                message.output_owner = Some(owner.into());
3310                OutputObjectState::ObjectWrite
3311            }
3312            ObjectOut::PackageWrite((version, digest)) => {
3313                message.output_version = Some(version.value());
3314                message.output_digest = Some(digest.to_string());
3315                OutputObjectState::PackageWrite
3316            }
3317            ObjectOut::AccumulatorWriteV1(accumulator_write) => {
3318                message.set_accumulator_write(accumulator_write);
3319                OutputObjectState::AccumulatorWrite
3320            }
3321        };
3322        message.set_output_state(output_state);
3323
3324        message.set_id_operation(value.id_operation.into());
3325        message
3326    }
3327}
3328
3329impl From<crate::effects::AccumulatorWriteV1> for AccumulatorWrite {
3330    fn from(value: crate::effects::AccumulatorWriteV1) -> Self {
3331        use accumulator_write::AccumulatorOperation;
3332
3333        let mut message = Self::default();
3334
3335        message.set_address(value.address.address.to_string());
3336        message.set_accumulator_type(value.address.ty.to_canonical_string(true));
3337        message.set_operation(match value.operation {
3338            crate::effects::AccumulatorOperation::Merge => AccumulatorOperation::Merge,
3339            crate::effects::AccumulatorOperation::Split => AccumulatorOperation::Split,
3340        });
3341        match value.value {
3342            crate::effects::AccumulatorValue::Integer(value) => message.set_integer_value(value),
3343            //TODO unsupported value types
3344            crate::effects::AccumulatorValue::IntegerTuple(_, _)
3345            | crate::effects::AccumulatorValue::EventDigest(_) => {}
3346        }
3347
3348        message
3349    }
3350}
3351
3352//
3353// IdOperation
3354//
3355
3356impl From<crate::effects::IDOperation> for changed_object::IdOperation {
3357    fn from(value: crate::effects::IDOperation) -> Self {
3358        use crate::effects::IDOperation as I;
3359
3360        match value {
3361            I::None => Self::None,
3362            I::Created => Self::Created,
3363            I::Deleted => Self::Deleted,
3364        }
3365    }
3366}
3367
3368//
3369// UnchangedConsensusObject
3370//
3371
3372impl From<crate::effects::UnchangedConsensusKind> for UnchangedConsensusObject {
3373    fn from(value: crate::effects::UnchangedConsensusKind) -> Self {
3374        use crate::effects::UnchangedConsensusKind as K;
3375        use unchanged_consensus_object::UnchangedConsensusObjectKind;
3376
3377        let mut message = Self::default();
3378
3379        let kind = match value {
3380            K::ReadOnlyRoot((version, digest)) => {
3381                message.version = Some(version.value());
3382                message.digest = Some(digest.to_string());
3383                UnchangedConsensusObjectKind::ReadOnlyRoot
3384            }
3385            K::MutateConsensusStreamEnded(version) => {
3386                message.version = Some(version.value());
3387                UnchangedConsensusObjectKind::MutateConsensusStreamEnded
3388            }
3389            K::ReadConsensusStreamEnded(version) => {
3390                message.version = Some(version.value());
3391                UnchangedConsensusObjectKind::ReadConsensusStreamEnded
3392            }
3393            K::Cancelled(version) => {
3394                message.version = Some(version.value());
3395                UnchangedConsensusObjectKind::Canceled
3396            }
3397            K::PerEpochConfig => UnchangedConsensusObjectKind::PerEpochConfig,
3398            // PerEpochConfigWithSequenceNumber { version } => {
3399            //     message.version = Some(version);
3400            //     UnchangedSharedObjectKind::PerEpochConfig
3401            // }
3402        };
3403
3404        message.set_kind(kind);
3405        message
3406    }
3407}
3408
3409//
3410// TransactionChecks
3411//
3412
3413impl From<simulate_transaction_request::TransactionChecks>
3414    for crate::transaction_executor::TransactionChecks
3415{
3416    fn from(value: simulate_transaction_request::TransactionChecks) -> Self {
3417        match value {
3418            simulate_transaction_request::TransactionChecks::Enabled => Self::Enabled,
3419            simulate_transaction_request::TransactionChecks::Disabled => Self::Disabled,
3420            // Default to enabled
3421            _ => Self::Enabled,
3422        }
3423    }
3424}
3425
3426//
3427// Coin-related conversions
3428//
3429
3430impl From<crate::coin_registry::MetadataCapState> for coin_metadata::MetadataCapState {
3431    fn from(value: crate::coin_registry::MetadataCapState) -> Self {
3432        match value {
3433            crate::coin_registry::MetadataCapState::Claimed(_) => {
3434                coin_metadata::MetadataCapState::Claimed
3435            }
3436            crate::coin_registry::MetadataCapState::Unclaimed => {
3437                coin_metadata::MetadataCapState::Unclaimed
3438            }
3439            crate::coin_registry::MetadataCapState::Deleted => {
3440                coin_metadata::MetadataCapState::Deleted
3441            }
3442        }
3443    }
3444}
3445
3446impl From<&crate::coin_registry::Currency> for CoinMetadata {
3447    fn from(value: &crate::coin_registry::Currency) -> Self {
3448        let mut metadata = CoinMetadata::default();
3449        metadata.id = Some(sui_sdk_types::Address::from(value.id.into_bytes()).to_string());
3450        metadata.decimals = Some(value.decimals.into());
3451        metadata.name = Some(value.name.clone());
3452        metadata.symbol = Some(value.symbol.clone());
3453        metadata.description = Some(value.description.clone());
3454        metadata.icon_url = Some(value.icon_url.clone());
3455
3456        match &value.metadata_cap_id {
3457            crate::coin_registry::MetadataCapState::Claimed(id) => {
3458                metadata.metadata_cap_state = Some(coin_metadata::MetadataCapState::Claimed as i32);
3459                metadata.metadata_cap_id = Some(sui_sdk_types::Address::from(*id).to_string());
3460            }
3461            crate::coin_registry::MetadataCapState::Unclaimed => {
3462                metadata.metadata_cap_state =
3463                    Some(coin_metadata::MetadataCapState::Unclaimed as i32);
3464            }
3465            crate::coin_registry::MetadataCapState::Deleted => {
3466                metadata.metadata_cap_state = Some(coin_metadata::MetadataCapState::Deleted as i32);
3467            }
3468        }
3469
3470        metadata
3471    }
3472}
3473
3474impl From<crate::coin::CoinMetadata> for CoinMetadata {
3475    fn from(value: crate::coin::CoinMetadata) -> Self {
3476        let mut metadata = CoinMetadata::default();
3477        metadata.id = Some(sui_sdk_types::Address::from(value.id.id.bytes).to_string());
3478        metadata.decimals = Some(value.decimals.into());
3479        metadata.name = Some(value.name);
3480        metadata.symbol = Some(value.symbol);
3481        metadata.description = Some(value.description);
3482        metadata.icon_url = value.icon_url;
3483        metadata
3484    }
3485}
3486
3487impl From<crate::coin_registry::SupplyState> for coin_treasury::SupplyState {
3488    fn from(value: crate::coin_registry::SupplyState) -> Self {
3489        match value {
3490            crate::coin_registry::SupplyState::Fixed(_) => coin_treasury::SupplyState::Fixed,
3491            crate::coin_registry::SupplyState::BurnOnly(_) => coin_treasury::SupplyState::BurnOnly,
3492            crate::coin_registry::SupplyState::Unknown => coin_treasury::SupplyState::Unknown,
3493        }
3494    }
3495}
3496
3497impl From<crate::coin::TreasuryCap> for CoinTreasury {
3498    fn from(value: crate::coin::TreasuryCap) -> Self {
3499        let mut treasury = CoinTreasury::default();
3500        treasury.id = Some(sui_sdk_types::Address::from(value.id.id.bytes).to_string());
3501        treasury.total_supply = Some(value.total_supply.value);
3502        treasury
3503    }
3504}
3505
3506impl From<&crate::coin_registry::RegulatedState> for RegulatedCoinMetadata {
3507    fn from(value: &crate::coin_registry::RegulatedState) -> Self {
3508        let mut regulated = RegulatedCoinMetadata::default();
3509
3510        match value {
3511            crate::coin_registry::RegulatedState::Regulated {
3512                cap,
3513                allow_global_pause,
3514                variant,
3515            } => {
3516                regulated.deny_cap_object = Some(sui_sdk_types::Address::from(*cap).to_string());
3517                regulated.allow_global_pause = *allow_global_pause;
3518                regulated.variant = Some(*variant as u32);
3519                regulated.coin_regulated_state =
3520                    Some(regulated_coin_metadata::CoinRegulatedState::Regulated as i32);
3521            }
3522            crate::coin_registry::RegulatedState::Unregulated => {
3523                regulated.coin_regulated_state =
3524                    Some(regulated_coin_metadata::CoinRegulatedState::Unregulated as i32);
3525            }
3526            crate::coin_registry::RegulatedState::Unknown => {
3527                regulated.coin_regulated_state =
3528                    Some(regulated_coin_metadata::CoinRegulatedState::Unknown as i32);
3529            }
3530        }
3531
3532        regulated
3533    }
3534}
3535
3536impl From<crate::coin_registry::RegulatedState> for RegulatedCoinMetadata {
3537    fn from(value: crate::coin_registry::RegulatedState) -> Self {
3538        (&value).into()
3539    }
3540}
3541
3542impl From<crate::coin::RegulatedCoinMetadata> for RegulatedCoinMetadata {
3543    fn from(value: crate::coin::RegulatedCoinMetadata) -> Self {
3544        let mut message = RegulatedCoinMetadata::default();
3545        message.id = Some(sui_sdk_types::Address::from(value.id.id.bytes).to_string());
3546        message.coin_metadata_object =
3547            Some(sui_sdk_types::Address::from(value.coin_metadata_object.bytes).to_string());
3548        message.deny_cap_object =
3549            Some(sui_sdk_types::Address::from(value.deny_cap_object.bytes).to_string());
3550        message.coin_regulated_state =
3551            Some(regulated_coin_metadata::CoinRegulatedState::Regulated as i32);
3552        message
3553    }
3554}
3555
3556impl TryFrom<&ObjectSet> for crate::full_checkpoint_content::ObjectSet {
3557    type Error = TryFromProtoError;
3558
3559    fn try_from(value: &ObjectSet) -> Result<Self, Self::Error> {
3560        let mut objects = Self::default();
3561
3562        for o in value.objects() {
3563            objects.insert(
3564                o.bcs()
3565                    .deserialize()
3566                    .map_err(|e| TryFromProtoError::invalid("object.bcs", e))?,
3567            );
3568        }
3569
3570        Ok(objects)
3571    }
3572}