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        };
2186
2187        message.set_kind(kind);
2188        message
2189    }
2190}
2191
2192//
2193// Transaction
2194//
2195
2196impl From<crate::transaction::TransactionData> for Transaction {
2197    fn from(value: crate::transaction::TransactionData) -> Self {
2198        Self::merge_from(&value, &FieldMaskTree::new_wildcard())
2199    }
2200}
2201
2202impl Merge<&crate::transaction::TransactionData> for Transaction {
2203    fn merge(&mut self, source: &crate::transaction::TransactionData, mask: &FieldMaskTree) {
2204        if mask.contains(Self::BCS_FIELD.name) {
2205            let mut bcs = Bcs::serialize(&source).unwrap();
2206            bcs.name = Some("TransactionData".to_owned());
2207            self.bcs = Some(bcs);
2208        }
2209
2210        if mask.contains(Self::DIGEST_FIELD.name) {
2211            self.digest = Some(source.digest().to_string());
2212        }
2213
2214        if mask.contains(Self::VERSION_FIELD.name) {
2215            self.version = Some(1);
2216        }
2217
2218        let crate::transaction::TransactionData::V1(source) = source;
2219
2220        if mask.contains(Self::KIND_FIELD.name) {
2221            self.kind = Some(source.kind.clone().into());
2222        }
2223
2224        if mask.contains(Self::SENDER_FIELD.name) {
2225            self.sender = Some(source.sender.to_string());
2226        }
2227
2228        if mask.contains(Self::GAS_PAYMENT_FIELD.name) {
2229            self.gas_payment = Some((&source.gas_data).into());
2230        }
2231
2232        if mask.contains(Self::EXPIRATION_FIELD.name) {
2233            self.expiration = Some(source.expiration.into());
2234        }
2235    }
2236}
2237
2238//
2239// GasPayment
2240//
2241
2242impl From<&crate::transaction::GasData> for GasPayment {
2243    fn from(value: &crate::transaction::GasData) -> Self {
2244        let mut message = Self::default();
2245        message.objects = value
2246            .payment
2247            .iter()
2248            .map(|obj_ref| obj_ref.to_proto())
2249            .collect();
2250        message.owner = Some(value.owner.to_string());
2251        message.price = Some(value.price);
2252        message.budget = Some(value.budget);
2253        message
2254    }
2255}
2256
2257//
2258// TransactionExpiration
2259//
2260
2261impl From<crate::transaction::TransactionExpiration> for TransactionExpiration {
2262    fn from(value: crate::transaction::TransactionExpiration) -> Self {
2263        use crate::transaction::TransactionExpiration as E;
2264        use transaction_expiration::TransactionExpirationKind;
2265
2266        let mut message = Self::default();
2267
2268        let kind = match value {
2269            E::None => TransactionExpirationKind::None,
2270            E::Epoch(epoch) => {
2271                message.epoch = Some(epoch);
2272                TransactionExpirationKind::Epoch
2273            }
2274            E::ValidDuring {
2275                min_epoch,
2276                max_epoch,
2277                min_timestamp,
2278                max_timestamp,
2279                chain,
2280                nonce,
2281            } => {
2282                message.epoch = max_epoch;
2283                message.min_epoch = min_epoch;
2284                message.min_timestamp = min_timestamp.map(ms_to_timestamp);
2285                message.max_timestamp = max_timestamp.map(ms_to_timestamp);
2286                message.set_chain(sui_sdk_types::Digest::new(*chain.as_bytes()));
2287                message.set_nonce(nonce);
2288
2289                TransactionExpirationKind::ValidDuring
2290            }
2291        };
2292
2293        message.set_kind(kind);
2294        message
2295    }
2296}
2297
2298impl TryFrom<&TransactionExpiration> for crate::transaction::TransactionExpiration {
2299    type Error = &'static str;
2300
2301    fn try_from(value: &TransactionExpiration) -> Result<Self, Self::Error> {
2302        use transaction_expiration::TransactionExpirationKind;
2303
2304        Ok(match value.kind() {
2305            TransactionExpirationKind::None => Self::None,
2306            TransactionExpirationKind::Epoch => Self::Epoch(value.epoch()),
2307            TransactionExpirationKind::ValidDuring => {
2308                let chain_str = value
2309                    .chain
2310                    .as_deref()
2311                    .ok_or("ValidDuring expiration is missing chain")?;
2312                let chain_digest: sui_sdk_types::Digest = chain_str
2313                    .parse()
2314                    .map_err(|_| "ValidDuring expiration has invalid chain digest")?;
2315                let chain = crate::digests::ChainIdentifier::from(
2316                    crate::digests::CheckpointDigest::new(chain_digest.into_inner()),
2317                );
2318                let nonce = value
2319                    .nonce
2320                    .ok_or("ValidDuring expiration is missing nonce")?;
2321                let min_timestamp = value
2322                    .min_timestamp
2323                    .as_ref()
2324                    .map(timestamp_to_ms)
2325                    .transpose()?;
2326                let max_timestamp = value
2327                    .max_timestamp
2328                    .as_ref()
2329                    .map(timestamp_to_ms)
2330                    .transpose()?;
2331                Self::ValidDuring {
2332                    min_epoch: value.min_epoch,
2333                    max_epoch: value.epoch,
2334                    min_timestamp,
2335                    max_timestamp,
2336                    chain,
2337                    nonce,
2338                }
2339            }
2340            TransactionExpirationKind::Unknown | _ => {
2341                return Err("unknown TransactionExpirationKind");
2342            }
2343        })
2344    }
2345}
2346
2347//
2348// TransactionKind
2349//
2350
2351impl From<crate::transaction::TransactionKind> for TransactionKind {
2352    fn from(value: crate::transaction::TransactionKind) -> Self {
2353        use crate::transaction::TransactionKind as K;
2354        use transaction_kind::Kind;
2355
2356        let message = Self::default();
2357
2358        match value {
2359            K::ProgrammableTransaction(ptb) => message
2360                .with_programmable_transaction(ptb)
2361                .with_kind(Kind::ProgrammableTransaction),
2362            K::ChangeEpoch(change_epoch) => message
2363                .with_change_epoch(change_epoch)
2364                .with_kind(Kind::ChangeEpoch),
2365            K::Genesis(genesis) => message.with_genesis(genesis).with_kind(Kind::Genesis),
2366            K::ConsensusCommitPrologue(prologue) => message
2367                .with_consensus_commit_prologue(prologue)
2368                .with_kind(Kind::ConsensusCommitPrologueV1),
2369            K::AuthenticatorStateUpdate(update) => message
2370                .with_authenticator_state_update(update)
2371                .with_kind(Kind::AuthenticatorStateUpdate),
2372            K::EndOfEpochTransaction(transactions) => message
2373                .with_end_of_epoch({
2374                    EndOfEpochTransaction::default()
2375                        .with_transactions(transactions.into_iter().map(Into::into).collect())
2376                })
2377                .with_kind(Kind::EndOfEpoch),
2378            K::RandomnessStateUpdate(update) => message
2379                .with_randomness_state_update(update)
2380                .with_kind(Kind::RandomnessStateUpdate),
2381            K::ConsensusCommitPrologueV2(prologue) => message
2382                .with_consensus_commit_prologue(prologue)
2383                .with_kind(Kind::ConsensusCommitPrologueV2),
2384            K::ConsensusCommitPrologueV3(prologue) => message
2385                .with_consensus_commit_prologue(prologue)
2386                .with_kind(Kind::ConsensusCommitPrologueV3),
2387            K::ConsensusCommitPrologueV4(prologue) => message
2388                .with_consensus_commit_prologue(prologue)
2389                .with_kind(Kind::ConsensusCommitPrologueV4),
2390            K::ProgrammableSystemTransaction(ptb) => message
2391                .with_programmable_transaction(ptb)
2392                .with_kind(Kind::ProgrammableSystemTransaction),
2393        }
2394    }
2395}
2396
2397//
2398// ConsensusCommitPrologue
2399//
2400
2401impl From<crate::messages_consensus::ConsensusCommitPrologue> for ConsensusCommitPrologue {
2402    fn from(value: crate::messages_consensus::ConsensusCommitPrologue) -> Self {
2403        let mut message = Self::default();
2404        message.epoch = Some(value.epoch);
2405        message.round = Some(value.round);
2406        message.commit_timestamp = Some(sui_rpc::proto::timestamp_ms_to_proto(
2407            value.commit_timestamp_ms,
2408        ));
2409        message
2410    }
2411}
2412
2413impl From<crate::messages_consensus::ConsensusCommitPrologueV2> for ConsensusCommitPrologue {
2414    fn from(value: crate::messages_consensus::ConsensusCommitPrologueV2) -> Self {
2415        let mut message = Self::default();
2416        message.epoch = Some(value.epoch);
2417        message.round = Some(value.round);
2418        message.commit_timestamp = Some(sui_rpc::proto::timestamp_ms_to_proto(
2419            value.commit_timestamp_ms,
2420        ));
2421        message.consensus_commit_digest = Some(value.consensus_commit_digest.to_string());
2422        message
2423    }
2424}
2425
2426impl From<crate::messages_consensus::ConsensusCommitPrologueV3> for ConsensusCommitPrologue {
2427    fn from(value: crate::messages_consensus::ConsensusCommitPrologueV3) -> Self {
2428        let mut message = Self::default();
2429        message.epoch = Some(value.epoch);
2430        message.round = Some(value.round);
2431        message.commit_timestamp = Some(sui_rpc::proto::timestamp_ms_to_proto(
2432            value.commit_timestamp_ms,
2433        ));
2434        message.consensus_commit_digest = Some(value.consensus_commit_digest.to_string());
2435        message.sub_dag_index = value.sub_dag_index;
2436        message.consensus_determined_version_assignments =
2437            Some(value.consensus_determined_version_assignments.into());
2438        message
2439    }
2440}
2441
2442impl From<crate::messages_consensus::ConsensusCommitPrologueV4> for ConsensusCommitPrologue {
2443    fn from(
2444        crate::messages_consensus::ConsensusCommitPrologueV4 {
2445            epoch,
2446            round,
2447            sub_dag_index,
2448            commit_timestamp_ms,
2449            consensus_commit_digest,
2450            consensus_determined_version_assignments,
2451            additional_state_digest,
2452        }: crate::messages_consensus::ConsensusCommitPrologueV4,
2453    ) -> Self {
2454        let mut message = Self::default();
2455        message.epoch = Some(epoch);
2456        message.round = Some(round);
2457        message.commit_timestamp = Some(sui_rpc::proto::timestamp_ms_to_proto(commit_timestamp_ms));
2458        message.consensus_commit_digest = Some(consensus_commit_digest.to_string());
2459        message.sub_dag_index = sub_dag_index;
2460        message.consensus_determined_version_assignments =
2461            Some(consensus_determined_version_assignments.into());
2462        message.additional_state_digest = Some(additional_state_digest.to_string());
2463        message
2464    }
2465}
2466
2467//
2468// ConsensusDeterminedVersionAssignments
2469//
2470
2471impl From<crate::messages_consensus::ConsensusDeterminedVersionAssignments>
2472    for ConsensusDeterminedVersionAssignments
2473{
2474    fn from(value: crate::messages_consensus::ConsensusDeterminedVersionAssignments) -> Self {
2475        use crate::messages_consensus::ConsensusDeterminedVersionAssignments as A;
2476
2477        let mut message = Self::default();
2478
2479        let version = match value {
2480            A::CancelledTransactions(canceled_transactions) => {
2481                message.canceled_transactions = canceled_transactions
2482                    .into_iter()
2483                    .map(|(tx_digest, assignments)| {
2484                        let mut message = CanceledTransaction::default();
2485                        message.digest = Some(tx_digest.to_string());
2486                        message.version_assignments = assignments
2487                            .into_iter()
2488                            .map(|(id, version)| {
2489                                let mut message = VersionAssignment::default();
2490                                message.object_id = Some(id.to_canonical_string(true));
2491                                message.version = Some(version.value());
2492                                message
2493                            })
2494                            .collect();
2495                        message
2496                    })
2497                    .collect();
2498                1
2499            }
2500            A::CancelledTransactionsV2(canceled_transactions) => {
2501                message.canceled_transactions = canceled_transactions
2502                    .into_iter()
2503                    .map(|(tx_digest, assignments)| {
2504                        let mut message = CanceledTransaction::default();
2505                        message.digest = Some(tx_digest.to_string());
2506                        message.version_assignments = assignments
2507                            .into_iter()
2508                            .map(|((id, start_version), version)| {
2509                                let mut message = VersionAssignment::default();
2510                                message.object_id = Some(id.to_canonical_string(true));
2511                                message.start_version = Some(start_version.value());
2512                                message.version = Some(version.value());
2513                                message
2514                            })
2515                            .collect();
2516                        message
2517                    })
2518                    .collect();
2519                2
2520            }
2521        };
2522
2523        message.version = Some(version);
2524        message
2525    }
2526}
2527
2528//
2529// GenesisTransaction
2530//
2531
2532impl From<crate::transaction::GenesisTransaction> for GenesisTransaction {
2533    fn from(value: crate::transaction::GenesisTransaction) -> Self {
2534        let mut message = Self::default();
2535        message.objects = value.objects.into_iter().map(Into::into).collect();
2536        message
2537    }
2538}
2539
2540//
2541// RandomnessStateUpdate
2542//
2543
2544impl From<crate::transaction::RandomnessStateUpdate> for RandomnessStateUpdate {
2545    fn from(value: crate::transaction::RandomnessStateUpdate) -> Self {
2546        let mut message = Self::default();
2547        message.epoch = Some(value.epoch);
2548        message.randomness_round = Some(value.randomness_round.0);
2549        message.random_bytes = Some(value.random_bytes.into());
2550        message.randomness_object_initial_shared_version =
2551            Some(value.randomness_obj_initial_shared_version.value());
2552        message
2553    }
2554}
2555
2556//
2557// AuthenticatorStateUpdate
2558//
2559
2560impl From<crate::transaction::AuthenticatorStateUpdate> for AuthenticatorStateUpdate {
2561    fn from(value: crate::transaction::AuthenticatorStateUpdate) -> Self {
2562        let mut message = Self::default();
2563        message.epoch = Some(value.epoch);
2564        message.round = Some(value.round);
2565        message.new_active_jwks = value.new_active_jwks.into_iter().map(Into::into).collect();
2566        message.authenticator_object_initial_shared_version =
2567            Some(value.authenticator_obj_initial_shared_version.value());
2568        message
2569    }
2570}
2571
2572//
2573// ActiveJwk
2574//
2575
2576impl From<crate::authenticator_state::ActiveJwk> for ActiveJwk {
2577    fn from(value: crate::authenticator_state::ActiveJwk) -> Self {
2578        let mut jwk_id = JwkId::default();
2579        jwk_id.iss = Some(value.jwk_id.iss);
2580        jwk_id.kid = Some(value.jwk_id.kid);
2581
2582        let mut jwk = Jwk::default();
2583        jwk.kty = Some(value.jwk.kty);
2584        jwk.e = Some(value.jwk.e);
2585        jwk.n = Some(value.jwk.n);
2586        jwk.alg = Some(value.jwk.alg);
2587
2588        let mut message = Self::default();
2589        message.id = Some(jwk_id);
2590        message.jwk = Some(jwk);
2591        message.epoch = Some(value.epoch);
2592        message
2593    }
2594}
2595
2596//
2597// ChangeEpoch
2598//
2599
2600impl From<crate::transaction::ChangeEpoch> for ChangeEpoch {
2601    fn from(value: crate::transaction::ChangeEpoch) -> Self {
2602        let mut message = Self::default();
2603        message.epoch = Some(value.epoch);
2604        message.protocol_version = Some(value.protocol_version.as_u64());
2605        message.storage_charge = Some(value.storage_charge);
2606        message.computation_charge = Some(value.computation_charge);
2607        message.storage_rebate = Some(value.storage_rebate);
2608        message.non_refundable_storage_fee = Some(value.non_refundable_storage_fee);
2609        message.epoch_start_timestamp = Some(sui_rpc::proto::timestamp_ms_to_proto(
2610            value.epoch_start_timestamp_ms,
2611        ));
2612        message.system_packages = value
2613            .system_packages
2614            .into_iter()
2615            .map(|(version, modules, dependencies)| {
2616                let mut message = SystemPackage::default();
2617                message.version = Some(version.value());
2618                message.modules = modules.into_iter().map(Into::into).collect();
2619                message.dependencies = dependencies
2620                    .iter()
2621                    .map(|d| d.to_canonical_string(true))
2622                    .collect();
2623                message
2624            })
2625            .collect();
2626        message
2627    }
2628}
2629
2630//
2631// EndOfEpochTransactionkind
2632//
2633
2634impl From<crate::transaction::EndOfEpochTransactionKind> for EndOfEpochTransactionKind {
2635    fn from(value: crate::transaction::EndOfEpochTransactionKind) -> Self {
2636        use crate::transaction::EndOfEpochTransactionKind as K;
2637        use end_of_epoch_transaction_kind::Kind;
2638
2639        let message = Self::default();
2640
2641        match value {
2642            K::ChangeEpoch(change_epoch) => message
2643                .with_change_epoch(change_epoch)
2644                .with_kind(Kind::ChangeEpoch),
2645            K::AuthenticatorStateCreate => message.with_kind(Kind::AuthenticatorStateCreate),
2646            K::AuthenticatorStateExpire(expire) => message
2647                .with_authenticator_state_expire(expire)
2648                .with_kind(Kind::AuthenticatorStateExpire),
2649            K::RandomnessStateCreate => message.with_kind(Kind::RandomnessStateCreate),
2650            K::DenyListStateCreate => message.with_kind(Kind::DenyListStateCreate),
2651            K::BridgeStateCreate(chain_id) => message
2652                .with_bridge_chain_id(chain_id.to_string())
2653                .with_kind(Kind::BridgeStateCreate),
2654            K::BridgeCommitteeInit(bridge_object_version) => message
2655                .with_bridge_object_version(bridge_object_version.into())
2656                .with_kind(Kind::BridgeCommitteeInit),
2657            K::StoreExecutionTimeObservations(observations) => message
2658                .with_execution_time_observations(observations)
2659                .with_kind(Kind::StoreExecutionTimeObservations),
2660            K::AccumulatorRootCreate => message.with_kind(Kind::AccumulatorRootCreate),
2661            K::CoinRegistryCreate => message.with_kind(Kind::CoinRegistryCreate),
2662            K::DisplayRegistryCreate => message.with_kind(Kind::DisplayRegistryCreate),
2663            K::AddressAliasStateCreate => message.with_kind(Kind::AddressAliasStateCreate),
2664            K::WriteAccumulatorStorageCost(storage_cost) => message
2665                .with_kind(Kind::WriteAccumulatorStorageCost)
2666                .with_storage_cost(storage_cost.storage_cost),
2667        }
2668    }
2669}
2670
2671//
2672// AuthenticatorStateExpire
2673//
2674
2675impl From<crate::transaction::AuthenticatorStateExpire> for AuthenticatorStateExpire {
2676    fn from(value: crate::transaction::AuthenticatorStateExpire) -> Self {
2677        let mut message = Self::default();
2678        message.min_epoch = Some(value.min_epoch);
2679        message.authenticator_object_initial_shared_version =
2680            Some(value.authenticator_obj_initial_shared_version.value());
2681        message
2682    }
2683}
2684
2685// ExecutionTimeObservations
2686
2687impl From<crate::transaction::StoredExecutionTimeObservations> for ExecutionTimeObservations {
2688    fn from(value: crate::transaction::StoredExecutionTimeObservations) -> Self {
2689        let mut message = Self::default();
2690        match value {
2691            crate::transaction::StoredExecutionTimeObservations::V1(vec) => {
2692                message.version = Some(1);
2693                message.observations = vec
2694                    .into_iter()
2695                    .map(|(key, observation)| {
2696                        use crate::execution::ExecutionTimeObservationKey as K;
2697                        use execution_time_observation::ExecutionTimeObservationKind;
2698
2699                        let mut message = ExecutionTimeObservation::default();
2700
2701                        let kind = match key {
2702                            K::MoveEntryPoint {
2703                                package,
2704                                module,
2705                                function,
2706                                type_arguments,
2707                            } => {
2708                                message.move_entry_point = Some({
2709                                    let mut message = MoveCall::default();
2710                                    message.package = Some(package.to_canonical_string(true));
2711                                    message.module = Some(module);
2712                                    message.function = Some(function);
2713                                    message.type_arguments = type_arguments
2714                                        .into_iter()
2715                                        .map(|ty| ty.to_canonical_string(true))
2716                                        .collect();
2717                                    message
2718                                });
2719                                ExecutionTimeObservationKind::MoveEntryPoint
2720                            }
2721                            K::TransferObjects => ExecutionTimeObservationKind::TransferObjects,
2722                            K::SplitCoins => ExecutionTimeObservationKind::SplitCoins,
2723                            K::MergeCoins => ExecutionTimeObservationKind::MergeCoins,
2724                            K::Publish => ExecutionTimeObservationKind::Publish,
2725                            K::MakeMoveVec => ExecutionTimeObservationKind::MakeMoveVector,
2726                            K::Upgrade => ExecutionTimeObservationKind::Upgrade,
2727                        };
2728
2729                        message.validator_observations = observation
2730                            .into_iter()
2731                            .map(|(name, duration)| {
2732                                let mut message = ValidatorExecutionTimeObservation::default();
2733                                message.validator = Some(name.0.to_vec().into());
2734                                message.duration = Some(prost_types::Duration {
2735                                    seconds: duration.as_secs() as i64,
2736                                    nanos: duration.subsec_nanos() as i32,
2737                                });
2738                                message
2739                            })
2740                            .collect();
2741
2742                        message.set_kind(kind);
2743                        message
2744                    })
2745                    .collect();
2746            }
2747        }
2748
2749        message
2750    }
2751}
2752
2753//
2754// ProgrammableTransaction
2755//
2756
2757impl From<crate::transaction::ProgrammableTransaction> for ProgrammableTransaction {
2758    fn from(value: crate::transaction::ProgrammableTransaction) -> Self {
2759        let mut message = Self::default();
2760        message.inputs = value.inputs.into_iter().map(Into::into).collect();
2761        message.commands = value.commands.into_iter().map(Into::into).collect();
2762        message
2763    }
2764}
2765
2766//
2767// Input
2768//
2769
2770impl From<crate::transaction::CallArg> for Input {
2771    fn from(value: crate::transaction::CallArg) -> Self {
2772        use crate::transaction::CallArg as I;
2773        use crate::transaction::ObjectArg as O;
2774        use input::InputKind;
2775        use input::Mutability;
2776
2777        let mut message = Self::default();
2778
2779        let kind = match value {
2780            I::Pure(value) => {
2781                message.pure = Some(value.into());
2782                InputKind::Pure
2783            }
2784            I::Object(o) => match o {
2785                O::ImmOrOwnedObject((id, version, digest)) => {
2786                    message.object_id = Some(id.to_canonical_string(true));
2787                    message.version = Some(version.value());
2788                    message.digest = Some(digest.to_string());
2789                    InputKind::ImmutableOrOwned
2790                }
2791                O::SharedObject {
2792                    id,
2793                    initial_shared_version,
2794                    mutability,
2795                } => {
2796                    message.object_id = Some(id.to_canonical_string(true));
2797                    message.version = Some(initial_shared_version.value());
2798                    message.mutable = Some(mutability.is_exclusive());
2799                    message.set_mutability(match mutability {
2800                        crate::transaction::SharedObjectMutability::Immutable => {
2801                            Mutability::Immutable
2802                        }
2803                        crate::transaction::SharedObjectMutability::Mutable => Mutability::Mutable,
2804                        crate::transaction::SharedObjectMutability::NonExclusiveWrite => {
2805                            Mutability::NonExclusiveWrite
2806                        }
2807                    });
2808                    InputKind::Shared
2809                }
2810                O::Receiving((id, version, digest)) => {
2811                    message.object_id = Some(id.to_canonical_string(true));
2812                    message.version = Some(version.value());
2813                    message.digest = Some(digest.to_string());
2814                    InputKind::Receiving
2815                }
2816            },
2817            I::FundsWithdrawal(withdrawal) => {
2818                message.set_funds_withdrawal(withdrawal);
2819                InputKind::FundsWithdrawal
2820            }
2821        };
2822
2823        message.set_kind(kind);
2824        message
2825    }
2826}
2827
2828impl From<crate::transaction::FundsWithdrawalArg> for FundsWithdrawal {
2829    fn from(value: crate::transaction::FundsWithdrawalArg) -> Self {
2830        use funds_withdrawal::Source;
2831
2832        let mut message = Self::default();
2833
2834        message.amount = match value.reservation {
2835            crate::transaction::Reservation::MaxAmountU64(amount) => Some(amount),
2836        };
2837        let crate::transaction::WithdrawalTypeArg::Balance(coin_type) = value.type_arg;
2838        message.coin_type = Some(coin_type.to_canonical_string(true));
2839        message.set_source(match value.withdraw_from {
2840            crate::transaction::WithdrawFrom::Sender => Source::Sender,
2841            crate::transaction::WithdrawFrom::Sponsor => Source::Sponsor,
2842        });
2843
2844        message
2845    }
2846}
2847
2848//
2849// Argument
2850//
2851
2852impl From<crate::transaction::Argument> for Argument {
2853    fn from(value: crate::transaction::Argument) -> Self {
2854        use crate::transaction::Argument as A;
2855        use argument::ArgumentKind;
2856
2857        let mut message = Self::default();
2858
2859        let kind = match value {
2860            A::GasCoin => ArgumentKind::Gas,
2861            A::Input(input) => {
2862                message.input = Some(input.into());
2863                ArgumentKind::Input
2864            }
2865            A::Result(result) => {
2866                message.result = Some(result.into());
2867                ArgumentKind::Result
2868            }
2869            A::NestedResult(result, subresult) => {
2870                message.result = Some(result.into());
2871                message.subresult = Some(subresult.into());
2872                ArgumentKind::Result
2873            }
2874        };
2875
2876        message.set_kind(kind);
2877        message
2878    }
2879}
2880
2881//
2882// Command
2883//
2884
2885impl From<crate::transaction::Command> for Command {
2886    fn from(value: crate::transaction::Command) -> Self {
2887        use crate::transaction::Command as C;
2888        use command::Command;
2889
2890        let command = match value {
2891            C::MoveCall(move_call) => Command::MoveCall((*move_call).into()),
2892            C::TransferObjects(objects, address) => Command::TransferObjects({
2893                let mut message = TransferObjects::default();
2894                message.objects = objects.into_iter().map(Into::into).collect();
2895                message.address = Some(address.into());
2896                message
2897            }),
2898            C::SplitCoins(coin, amounts) => Command::SplitCoins({
2899                let mut message = SplitCoins::default();
2900                message.coin = Some(coin.into());
2901                message.amounts = amounts.into_iter().map(Into::into).collect();
2902                message
2903            }),
2904            C::MergeCoins(coin, coins_to_merge) => Command::MergeCoins({
2905                let mut message = MergeCoins::default();
2906                message.coin = Some(coin.into());
2907                message.coins_to_merge = coins_to_merge.into_iter().map(Into::into).collect();
2908                message
2909            }),
2910            C::Publish(modules, dependencies) => Command::Publish({
2911                let mut message = Publish::default();
2912                message.modules = modules.into_iter().map(Into::into).collect();
2913                message.dependencies = dependencies
2914                    .iter()
2915                    .map(|d| d.to_canonical_string(true))
2916                    .collect();
2917                message
2918            }),
2919            C::MakeMoveVec(element_type, elements) => Command::MakeMoveVector({
2920                let mut message = MakeMoveVector::default();
2921                message.element_type = element_type.map(|t| t.to_canonical_string(true));
2922                message.elements = elements.into_iter().map(Into::into).collect();
2923                message
2924            }),
2925            C::Upgrade(modules, dependencies, package, ticket) => Command::Upgrade({
2926                let mut message = Upgrade::default();
2927                message.modules = modules.into_iter().map(Into::into).collect();
2928                message.dependencies = dependencies
2929                    .iter()
2930                    .map(|d| d.to_canonical_string(true))
2931                    .collect();
2932                message.package = Some(package.to_canonical_string(true));
2933                message.ticket = Some(ticket.into());
2934                message
2935            }),
2936        };
2937
2938        let mut message = Self::default();
2939        message.command = Some(command);
2940        message
2941    }
2942}
2943
2944//
2945// MoveCall
2946//
2947
2948impl From<crate::transaction::ProgrammableMoveCall> for MoveCall {
2949    fn from(value: crate::transaction::ProgrammableMoveCall) -> Self {
2950        let mut message = Self::default();
2951        message.package = Some(value.package.to_canonical_string(true));
2952        message.module = Some(value.module.to_string());
2953        message.function = Some(value.function.to_string());
2954        message.type_arguments = value
2955            .type_arguments
2956            .iter()
2957            .map(|t| t.to_canonical_string(true))
2958            .collect();
2959        message.arguments = value.arguments.into_iter().map(Into::into).collect();
2960        message
2961    }
2962}
2963
2964//
2965// TransactionEffects
2966//
2967
2968impl From<crate::effects::TransactionEffects> for TransactionEffects {
2969    fn from(value: crate::effects::TransactionEffects) -> Self {
2970        Self::merge_from(&value, &FieldMaskTree::new_wildcard())
2971    }
2972}
2973
2974impl Merge<&crate::effects::TransactionEffects> for TransactionEffects {
2975    fn merge(&mut self, source: &crate::effects::TransactionEffects, mask: &FieldMaskTree) {
2976        if mask.contains(Self::BCS_FIELD.name) {
2977            let mut bcs = Bcs::serialize(&source).unwrap();
2978            bcs.name = Some("TransactionEffects".to_owned());
2979            self.bcs = Some(bcs);
2980        }
2981
2982        if mask.contains(Self::DIGEST_FIELD.name) {
2983            self.digest = Some(source.digest().to_string());
2984        }
2985
2986        match source {
2987            crate::effects::TransactionEffects::V1(v1) => self.merge(v1, mask),
2988            crate::effects::TransactionEffects::V2(v2) => self.merge(v2, mask),
2989        }
2990    }
2991}
2992
2993//
2994// TransactionEffectsV1
2995//
2996
2997impl Merge<&crate::effects::TransactionEffectsV1> for TransactionEffects {
2998    fn merge(&mut self, value: &crate::effects::TransactionEffectsV1, mask: &FieldMaskTree) {
2999        use crate::effects::TransactionEffectsAPI;
3000
3001        if mask.contains(Self::VERSION_FIELD.name) {
3002            self.version = Some(1);
3003        }
3004
3005        if mask.contains(Self::STATUS_FIELD.name) {
3006            self.status = Some(value.status().clone().into());
3007        }
3008
3009        if mask.contains(Self::EPOCH_FIELD.name) {
3010            self.epoch = Some(value.executed_epoch());
3011        }
3012
3013        if mask.contains(Self::GAS_USED_FIELD.name) {
3014            self.gas_used = Some(value.gas_cost_summary().clone().into());
3015        }
3016
3017        if mask.contains(Self::TRANSACTION_DIGEST_FIELD.name) {
3018            self.transaction_digest = Some(value.transaction_digest().to_string());
3019        }
3020
3021        if mask.contains(Self::EVENTS_DIGEST_FIELD.name) {
3022            self.events_digest = value.events_digest().map(|d| d.to_string());
3023        }
3024
3025        if mask.contains(Self::DEPENDENCIES_FIELD.name) {
3026            self.dependencies = value
3027                .dependencies()
3028                .iter()
3029                .map(ToString::to_string)
3030                .collect();
3031        }
3032
3033        if mask.contains(Self::CHANGED_OBJECTS_FIELD.name)
3034            || mask.contains(Self::UNCHANGED_CONSENSUS_OBJECTS_FIELD.name)
3035            || mask.contains(Self::GAS_OBJECT_FIELD.name)
3036        {
3037            let mut changed_objects = Vec::new();
3038            let mut unchanged_consensus_objects = Vec::new();
3039
3040            for ((id, version, digest), owner) in value.created() {
3041                let mut change = ChangedObject::default();
3042                change.object_id = Some(id.to_canonical_string(true));
3043                change.input_state = Some(changed_object::InputObjectState::DoesNotExist.into());
3044                change.output_state = Some(changed_object::OutputObjectState::ObjectWrite.into());
3045                change.output_version = Some(version.value());
3046                change.output_digest = Some(digest.to_string());
3047                change.output_owner = Some(owner.clone().into());
3048                change.id_operation = Some(changed_object::IdOperation::Created.into());
3049
3050                changed_objects.push(change);
3051            }
3052
3053            for ((id, version, digest), owner) in value.mutated() {
3054                let mut change = ChangedObject::default();
3055                change.object_id = Some(id.to_canonical_string(true));
3056                change.input_state = Some(changed_object::InputObjectState::Exists.into());
3057                change.output_state = Some(changed_object::OutputObjectState::ObjectWrite.into());
3058                change.output_version = Some(version.value());
3059                change.output_digest = Some(digest.to_string());
3060                change.output_owner = Some(owner.clone().into());
3061                change.id_operation = Some(changed_object::IdOperation::None.into());
3062
3063                changed_objects.push(change);
3064            }
3065
3066            for ((id, version, digest), owner) in value.unwrapped() {
3067                let mut change = ChangedObject::default();
3068                change.object_id = Some(id.to_canonical_string(true));
3069                change.input_state = Some(changed_object::InputObjectState::DoesNotExist.into());
3070                change.output_state = Some(changed_object::OutputObjectState::ObjectWrite.into());
3071                change.output_version = Some(version.value());
3072                change.output_digest = Some(digest.to_string());
3073                change.output_owner = Some(owner.clone().into());
3074                change.id_operation = Some(changed_object::IdOperation::None.into());
3075
3076                changed_objects.push(change);
3077            }
3078
3079            for (id, version, digest) in value.deleted() {
3080                let mut change = ChangedObject::default();
3081                change.object_id = Some(id.to_canonical_string(true));
3082                change.input_state = Some(changed_object::InputObjectState::Exists.into());
3083                change.output_state = Some(changed_object::OutputObjectState::DoesNotExist.into());
3084                change.output_version = Some(version.value());
3085                change.output_digest = Some(digest.to_string());
3086                change.id_operation = Some(changed_object::IdOperation::Deleted.into());
3087
3088                changed_objects.push(change);
3089            }
3090
3091            for (id, version, digest) in value.unwrapped_then_deleted() {
3092                let mut change = ChangedObject::default();
3093                change.object_id = Some(id.to_canonical_string(true));
3094                change.input_state = Some(changed_object::InputObjectState::DoesNotExist.into());
3095                change.output_state = Some(changed_object::OutputObjectState::DoesNotExist.into());
3096                change.output_version = Some(version.value());
3097                change.output_digest = Some(digest.to_string());
3098                change.id_operation = Some(changed_object::IdOperation::Deleted.into());
3099
3100                changed_objects.push(change);
3101            }
3102
3103            for (id, version, digest) in value.wrapped() {
3104                let mut change = ChangedObject::default();
3105                change.object_id = Some(id.to_canonical_string(true));
3106                change.input_state = Some(changed_object::InputObjectState::Exists.into());
3107                change.output_state = Some(changed_object::OutputObjectState::DoesNotExist.into());
3108                change.output_version = Some(version.value());
3109                change.output_digest = Some(digest.to_string());
3110                change.id_operation = Some(changed_object::IdOperation::Deleted.into());
3111
3112                changed_objects.push(change);
3113            }
3114
3115            for (object_id, version) in value.modified_at_versions() {
3116                let object_id = object_id.to_canonical_string(true);
3117                let version = version.value();
3118                if let Some(changed_object) = changed_objects
3119                    .iter_mut()
3120                    .find(|object| object.object_id() == object_id)
3121                {
3122                    changed_object.input_version = Some(version);
3123                }
3124            }
3125
3126            for (id, version, digest) in value.shared_objects() {
3127                let object_id = id.to_canonical_string(true);
3128                let version = version.value();
3129                let digest = digest.to_string();
3130
3131                if let Some(changed_object) = changed_objects
3132                    .iter_mut()
3133                    .find(|object| object.object_id() == object_id)
3134                {
3135                    changed_object.input_version = Some(version);
3136                    changed_object.input_digest = Some(digest);
3137                } else {
3138                    let mut unchanged_consensus_object = UnchangedConsensusObject::default();
3139                    unchanged_consensus_object.kind = Some(
3140                        unchanged_consensus_object::UnchangedConsensusObjectKind::ReadOnlyRoot
3141                            .into(),
3142                    );
3143                    unchanged_consensus_object.object_id = Some(object_id);
3144                    unchanged_consensus_object.version = Some(version);
3145                    unchanged_consensus_object.digest = Some(digest);
3146
3147                    unchanged_consensus_objects.push(unchanged_consensus_object);
3148                }
3149            }
3150
3151            if mask.contains(Self::GAS_OBJECT_FIELD.name)
3152                && let Some(((gas_id, _, _), _)) = value.gas_object()
3153            {
3154                let gas_object_id = gas_id.to_canonical_string(true);
3155                self.gas_object = changed_objects
3156                    .iter()
3157                    .find(|object| object.object_id() == gas_object_id)
3158                    .cloned();
3159            }
3160
3161            if mask.contains(Self::CHANGED_OBJECTS_FIELD.name) {
3162                self.changed_objects = changed_objects;
3163            }
3164
3165            if mask.contains(Self::UNCHANGED_CONSENSUS_OBJECTS_FIELD.name) {
3166                self.unchanged_consensus_objects = unchanged_consensus_objects;
3167            }
3168        }
3169    }
3170}
3171
3172//
3173// TransactionEffectsV2
3174//
3175
3176impl Merge<&crate::effects::TransactionEffectsV2> for TransactionEffects {
3177    fn merge(
3178        &mut self,
3179        crate::effects::TransactionEffectsV2 {
3180            status,
3181            executed_epoch,
3182            gas_used,
3183            transaction_digest,
3184            gas_object_index,
3185            events_digest,
3186            dependencies,
3187            lamport_version,
3188            changed_objects,
3189            unchanged_consensus_objects,
3190            aux_data_digest,
3191        }: &crate::effects::TransactionEffectsV2,
3192        mask: &FieldMaskTree,
3193    ) {
3194        if mask.contains(Self::VERSION_FIELD.name) {
3195            self.version = Some(2);
3196        }
3197
3198        if mask.contains(Self::STATUS_FIELD.name) {
3199            self.status = Some(status.clone().into());
3200        }
3201
3202        if mask.contains(Self::EPOCH_FIELD.name) {
3203            self.epoch = Some(*executed_epoch);
3204        }
3205
3206        if mask.contains(Self::GAS_USED_FIELD.name) {
3207            self.gas_used = Some(gas_used.clone().into());
3208        }
3209
3210        if mask.contains(Self::TRANSACTION_DIGEST_FIELD.name) {
3211            self.transaction_digest = Some(transaction_digest.to_string());
3212        }
3213
3214        if mask.contains(Self::GAS_OBJECT_FIELD.name) {
3215            self.gas_object = gas_object_index
3216                .map(|index| {
3217                    changed_objects
3218                        .get(index as usize)
3219                        .cloned()
3220                        .map(|(id, change)| {
3221                            let mut message = ChangedObject::from(change);
3222                            message.object_id = Some(id.to_canonical_string(true));
3223                            message
3224                        })
3225                })
3226                .flatten();
3227        }
3228
3229        if mask.contains(Self::EVENTS_DIGEST_FIELD.name) {
3230            self.events_digest = events_digest.map(|d| d.to_string());
3231        }
3232
3233        if mask.contains(Self::DEPENDENCIES_FIELD.name) {
3234            self.dependencies = dependencies.iter().map(ToString::to_string).collect();
3235        }
3236
3237        if mask.contains(Self::LAMPORT_VERSION_FIELD.name) {
3238            self.lamport_version = Some(lamport_version.value());
3239        }
3240
3241        if mask.contains(Self::CHANGED_OBJECTS_FIELD.name) {
3242            self.changed_objects = changed_objects
3243                .clone()
3244                .into_iter()
3245                .map(|(id, change)| {
3246                    let mut message = ChangedObject::from(change);
3247                    message.object_id = Some(id.to_canonical_string(true));
3248                    message
3249                })
3250                .collect();
3251        }
3252
3253        for object in self.changed_objects.iter_mut().chain(&mut self.gas_object) {
3254            if object.output_digest.is_some() && object.output_version.is_none() {
3255                object.output_version = Some(lamport_version.value());
3256            }
3257        }
3258
3259        if mask.contains(Self::UNCHANGED_CONSENSUS_OBJECTS_FIELD.name) {
3260            self.unchanged_consensus_objects = unchanged_consensus_objects
3261                .clone()
3262                .into_iter()
3263                .map(|(id, unchanged)| {
3264                    let mut message = UnchangedConsensusObject::from(unchanged);
3265                    message.object_id = Some(id.to_canonical_string(true));
3266                    message
3267                })
3268                .collect();
3269        }
3270
3271        if mask.contains(Self::AUXILIARY_DATA_DIGEST_FIELD.name) {
3272            self.auxiliary_data_digest = aux_data_digest.map(|d| d.to_string());
3273        }
3274    }
3275}
3276
3277//
3278// ChangedObject
3279//
3280
3281impl From<crate::effects::EffectsObjectChange> for ChangedObject {
3282    fn from(value: crate::effects::EffectsObjectChange) -> Self {
3283        use crate::effects::ObjectIn;
3284        use crate::effects::ObjectOut;
3285        use changed_object::InputObjectState;
3286        use changed_object::OutputObjectState;
3287
3288        let mut message = Self::default();
3289
3290        // Input State
3291        let input_state = match value.input_state {
3292            ObjectIn::NotExist => InputObjectState::DoesNotExist,
3293            ObjectIn::Exist(((version, digest), owner)) => {
3294                message.input_version = Some(version.value());
3295                message.input_digest = Some(digest.to_string());
3296                message.input_owner = Some(owner.into());
3297                InputObjectState::Exists
3298            }
3299        };
3300        message.set_input_state(input_state);
3301
3302        // Output State
3303        let output_state = match value.output_state {
3304            ObjectOut::NotExist => OutputObjectState::DoesNotExist,
3305            ObjectOut::ObjectWrite((digest, owner)) => {
3306                message.output_digest = Some(digest.to_string());
3307                message.output_owner = Some(owner.into());
3308                OutputObjectState::ObjectWrite
3309            }
3310            ObjectOut::PackageWrite((version, digest)) => {
3311                message.output_version = Some(version.value());
3312                message.output_digest = Some(digest.to_string());
3313                OutputObjectState::PackageWrite
3314            }
3315            ObjectOut::AccumulatorWriteV1(accumulator_write) => {
3316                message.set_accumulator_write(accumulator_write);
3317                OutputObjectState::AccumulatorWrite
3318            }
3319        };
3320        message.set_output_state(output_state);
3321
3322        message.set_id_operation(value.id_operation.into());
3323        message
3324    }
3325}
3326
3327impl From<crate::effects::AccumulatorWriteV1> for AccumulatorWrite {
3328    fn from(value: crate::effects::AccumulatorWriteV1) -> Self {
3329        use accumulator_write::AccumulatorOperation;
3330
3331        let mut message = Self::default();
3332
3333        message.set_address(value.address.address.to_string());
3334        message.set_accumulator_type(value.address.ty.to_canonical_string(true));
3335        message.set_operation(match value.operation {
3336            crate::effects::AccumulatorOperation::Merge => AccumulatorOperation::Merge,
3337            crate::effects::AccumulatorOperation::Split => AccumulatorOperation::Split,
3338        });
3339        match value.value {
3340            crate::effects::AccumulatorValue::Integer(value) => message.set_integer_value(value),
3341            //TODO unsupported value types
3342            crate::effects::AccumulatorValue::IntegerTuple(_, _)
3343            | crate::effects::AccumulatorValue::EventDigest(_) => {}
3344        }
3345
3346        message
3347    }
3348}
3349
3350//
3351// IdOperation
3352//
3353
3354impl From<crate::effects::IDOperation> for changed_object::IdOperation {
3355    fn from(value: crate::effects::IDOperation) -> Self {
3356        use crate::effects::IDOperation as I;
3357
3358        match value {
3359            I::None => Self::None,
3360            I::Created => Self::Created,
3361            I::Deleted => Self::Deleted,
3362        }
3363    }
3364}
3365
3366//
3367// UnchangedConsensusObject
3368//
3369
3370impl From<crate::effects::UnchangedConsensusKind> for UnchangedConsensusObject {
3371    fn from(value: crate::effects::UnchangedConsensusKind) -> Self {
3372        use crate::effects::UnchangedConsensusKind as K;
3373        use unchanged_consensus_object::UnchangedConsensusObjectKind;
3374
3375        let mut message = Self::default();
3376
3377        let kind = match value {
3378            K::ReadOnlyRoot((version, digest)) => {
3379                message.version = Some(version.value());
3380                message.digest = Some(digest.to_string());
3381                UnchangedConsensusObjectKind::ReadOnlyRoot
3382            }
3383            K::MutateConsensusStreamEnded(version) => {
3384                message.version = Some(version.value());
3385                UnchangedConsensusObjectKind::MutateConsensusStreamEnded
3386            }
3387            K::ReadConsensusStreamEnded(version) => {
3388                message.version = Some(version.value());
3389                UnchangedConsensusObjectKind::ReadConsensusStreamEnded
3390            }
3391            K::Cancelled(version) => {
3392                message.version = Some(version.value());
3393                UnchangedConsensusObjectKind::Canceled
3394            }
3395            K::PerEpochConfig => UnchangedConsensusObjectKind::PerEpochConfig,
3396            // PerEpochConfigWithSequenceNumber { version } => {
3397            //     message.version = Some(version);
3398            //     UnchangedSharedObjectKind::PerEpochConfig
3399            // }
3400        };
3401
3402        message.set_kind(kind);
3403        message
3404    }
3405}
3406
3407//
3408// TransactionChecks
3409//
3410
3411impl From<simulate_transaction_request::TransactionChecks>
3412    for crate::transaction_executor::TransactionChecks
3413{
3414    fn from(value: simulate_transaction_request::TransactionChecks) -> Self {
3415        match value {
3416            simulate_transaction_request::TransactionChecks::Enabled => Self::Enabled,
3417            simulate_transaction_request::TransactionChecks::Disabled => Self::Disabled,
3418            // Default to enabled
3419            _ => Self::Enabled,
3420        }
3421    }
3422}
3423
3424//
3425// Coin-related conversions
3426//
3427
3428impl From<crate::coin_registry::MetadataCapState> for coin_metadata::MetadataCapState {
3429    fn from(value: crate::coin_registry::MetadataCapState) -> Self {
3430        match value {
3431            crate::coin_registry::MetadataCapState::Claimed(_) => {
3432                coin_metadata::MetadataCapState::Claimed
3433            }
3434            crate::coin_registry::MetadataCapState::Unclaimed => {
3435                coin_metadata::MetadataCapState::Unclaimed
3436            }
3437            crate::coin_registry::MetadataCapState::Deleted => {
3438                coin_metadata::MetadataCapState::Deleted
3439            }
3440        }
3441    }
3442}
3443
3444impl From<&crate::coin_registry::Currency> for CoinMetadata {
3445    fn from(value: &crate::coin_registry::Currency) -> Self {
3446        let mut metadata = CoinMetadata::default();
3447        metadata.id = Some(sui_sdk_types::Address::from(value.id.into_bytes()).to_string());
3448        metadata.decimals = Some(value.decimals.into());
3449        metadata.name = Some(value.name.clone());
3450        metadata.symbol = Some(value.symbol.clone());
3451        metadata.description = Some(value.description.clone());
3452        metadata.icon_url = Some(value.icon_url.clone());
3453
3454        match &value.metadata_cap_id {
3455            crate::coin_registry::MetadataCapState::Claimed(id) => {
3456                metadata.metadata_cap_state = Some(coin_metadata::MetadataCapState::Claimed as i32);
3457                metadata.metadata_cap_id = Some(sui_sdk_types::Address::from(*id).to_string());
3458            }
3459            crate::coin_registry::MetadataCapState::Unclaimed => {
3460                metadata.metadata_cap_state =
3461                    Some(coin_metadata::MetadataCapState::Unclaimed as i32);
3462            }
3463            crate::coin_registry::MetadataCapState::Deleted => {
3464                metadata.metadata_cap_state = Some(coin_metadata::MetadataCapState::Deleted as i32);
3465            }
3466        }
3467
3468        metadata
3469    }
3470}
3471
3472impl From<crate::coin::CoinMetadata> for CoinMetadata {
3473    fn from(value: crate::coin::CoinMetadata) -> Self {
3474        let mut metadata = CoinMetadata::default();
3475        metadata.id = Some(sui_sdk_types::Address::from(value.id.id.bytes).to_string());
3476        metadata.decimals = Some(value.decimals.into());
3477        metadata.name = Some(value.name);
3478        metadata.symbol = Some(value.symbol);
3479        metadata.description = Some(value.description);
3480        metadata.icon_url = value.icon_url;
3481        metadata
3482    }
3483}
3484
3485impl From<crate::coin_registry::SupplyState> for coin_treasury::SupplyState {
3486    fn from(value: crate::coin_registry::SupplyState) -> Self {
3487        match value {
3488            crate::coin_registry::SupplyState::Fixed(_) => coin_treasury::SupplyState::Fixed,
3489            crate::coin_registry::SupplyState::BurnOnly(_) => coin_treasury::SupplyState::BurnOnly,
3490            crate::coin_registry::SupplyState::Unknown => coin_treasury::SupplyState::Unknown,
3491        }
3492    }
3493}
3494
3495impl From<crate::coin::TreasuryCap> for CoinTreasury {
3496    fn from(value: crate::coin::TreasuryCap) -> Self {
3497        let mut treasury = CoinTreasury::default();
3498        treasury.id = Some(sui_sdk_types::Address::from(value.id.id.bytes).to_string());
3499        treasury.total_supply = Some(value.total_supply.value);
3500        treasury
3501    }
3502}
3503
3504impl From<&crate::coin_registry::RegulatedState> for RegulatedCoinMetadata {
3505    fn from(value: &crate::coin_registry::RegulatedState) -> Self {
3506        let mut regulated = RegulatedCoinMetadata::default();
3507
3508        match value {
3509            crate::coin_registry::RegulatedState::Regulated {
3510                cap,
3511                allow_global_pause,
3512                variant,
3513            } => {
3514                regulated.deny_cap_object = Some(sui_sdk_types::Address::from(*cap).to_string());
3515                regulated.allow_global_pause = *allow_global_pause;
3516                regulated.variant = Some(*variant as u32);
3517                regulated.coin_regulated_state =
3518                    Some(regulated_coin_metadata::CoinRegulatedState::Regulated as i32);
3519            }
3520            crate::coin_registry::RegulatedState::Unregulated => {
3521                regulated.coin_regulated_state =
3522                    Some(regulated_coin_metadata::CoinRegulatedState::Unregulated as i32);
3523            }
3524            crate::coin_registry::RegulatedState::Unknown => {
3525                regulated.coin_regulated_state =
3526                    Some(regulated_coin_metadata::CoinRegulatedState::Unknown as i32);
3527            }
3528        }
3529
3530        regulated
3531    }
3532}
3533
3534impl From<crate::coin_registry::RegulatedState> for RegulatedCoinMetadata {
3535    fn from(value: crate::coin_registry::RegulatedState) -> Self {
3536        (&value).into()
3537    }
3538}
3539
3540impl From<crate::coin::RegulatedCoinMetadata> for RegulatedCoinMetadata {
3541    fn from(value: crate::coin::RegulatedCoinMetadata) -> Self {
3542        let mut message = RegulatedCoinMetadata::default();
3543        message.id = Some(sui_sdk_types::Address::from(value.id.id.bytes).to_string());
3544        message.coin_metadata_object =
3545            Some(sui_sdk_types::Address::from(value.coin_metadata_object.bytes).to_string());
3546        message.deny_cap_object =
3547            Some(sui_sdk_types::Address::from(value.deny_cap_object.bytes).to_string());
3548        message.coin_regulated_state =
3549            Some(regulated_coin_metadata::CoinRegulatedState::Regulated as i32);
3550        message
3551    }
3552}
3553
3554impl TryFrom<&ObjectSet> for crate::full_checkpoint_content::ObjectSet {
3555    type Error = TryFromProtoError;
3556
3557    fn try_from(value: &ObjectSet) -> Result<Self, Self::Error> {
3558        let mut objects = Self::default();
3559
3560        for o in value.objects() {
3561            objects.insert(
3562                o.bcs()
3563                    .deserialize()
3564                    .map_err(|e| TryFromProtoError::invalid("object.bcs", e))?,
3565            );
3566        }
3567
3568        Ok(objects)
3569    }
3570}