Skip to main content

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