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            // Node-local, transient retry marker that is never committed to effects, so RPC
1423            // (which only ever serves committed effects) must never observe it.
1424            E::SystemObjectNotAvailableLocally => {
1425                panic!("SystemObjectNotAvailableLocally is never committed to effects")
1426            }
1427        };
1428
1429        message.set_kind(kind);
1430        message
1431    }
1432}
1433
1434//
1435// CommandArgumentError
1436//
1437
1438impl From<crate::execution_status::CommandArgumentError> for CommandArgumentError {
1439    fn from(value: crate::execution_status::CommandArgumentError) -> Self {
1440        use crate::execution_status::CommandArgumentError as E;
1441        use command_argument_error::CommandArgumentErrorKind;
1442
1443        let mut message = Self::default();
1444
1445        let kind = match value {
1446            E::TypeMismatch => CommandArgumentErrorKind::TypeMismatch,
1447            E::InvalidBCSBytes => CommandArgumentErrorKind::InvalidBcsBytes,
1448            E::InvalidUsageOfPureArg => CommandArgumentErrorKind::InvalidUsageOfPureArgument,
1449            E::InvalidArgumentToPrivateEntryFunction => {
1450                CommandArgumentErrorKind::InvalidArgumentToPrivateEntryFunction
1451            }
1452            E::IndexOutOfBounds { idx } => {
1453                message.index_error = Some(index_error(idx.into(), None));
1454                CommandArgumentErrorKind::IndexOutOfBounds
1455            }
1456            E::SecondaryIndexOutOfBounds {
1457                result_idx,
1458                secondary_idx,
1459            } => {
1460                message.index_error =
1461                    Some(index_error(result_idx.into(), Some(secondary_idx.into())));
1462                CommandArgumentErrorKind::SecondaryIndexOutOfBounds
1463            }
1464            E::InvalidResultArity { result_idx } => {
1465                message.index_error = Some(index_error(result_idx.into(), None));
1466                CommandArgumentErrorKind::InvalidResultArity
1467            }
1468            E::InvalidGasCoinUsage => CommandArgumentErrorKind::InvalidGasCoinUsage,
1469            E::InvalidValueUsage => CommandArgumentErrorKind::InvalidValueUsage,
1470            E::InvalidObjectByValue => CommandArgumentErrorKind::InvalidObjectByValue,
1471            E::InvalidObjectByMutRef => CommandArgumentErrorKind::InvalidObjectByMutRef,
1472            E::SharedObjectOperationNotAllowed => {
1473                CommandArgumentErrorKind::ConsensusObjectOperationNotAllowed
1474            }
1475            E::InvalidArgumentArity => CommandArgumentErrorKind::InvalidArgumentArity,
1476
1477            E::InvalidTransferObject => CommandArgumentErrorKind::InvalidTransferObject,
1478            E::InvalidMakeMoveVecNonObjectArgument => {
1479                CommandArgumentErrorKind::InvalidMakeMoveVecNonObjectArgument
1480            }
1481            E::ArgumentWithoutValue => CommandArgumentErrorKind::ArgumentWithoutValue,
1482            E::CannotMoveBorrowedValue => CommandArgumentErrorKind::CannotMoveBorrowedValue,
1483            E::CannotWriteToExtendedReference => {
1484                CommandArgumentErrorKind::CannotWriteToExtendedReference
1485            }
1486            E::InvalidReferenceArgument => CommandArgumentErrorKind::InvalidReferenceArgument,
1487        };
1488
1489        message.set_kind(kind);
1490        message
1491    }
1492}
1493
1494//
1495// TypeArgumentError
1496//
1497
1498impl From<crate::execution_status::TypeArgumentError>
1499    for type_argument_error::TypeArgumentErrorKind
1500{
1501    fn from(value: crate::execution_status::TypeArgumentError) -> Self {
1502        use crate::execution_status::TypeArgumentError::*;
1503
1504        match value {
1505            TypeNotFound => Self::TypeNotFound,
1506            ConstraintNotSatisfied => Self::ConstraintNotSatisfied,
1507        }
1508    }
1509}
1510
1511//
1512// PackageUpgradeError
1513//
1514
1515impl From<crate::execution_status::PackageUpgradeError> for PackageUpgradeError {
1516    fn from(value: crate::execution_status::PackageUpgradeError) -> Self {
1517        use crate::execution_status::PackageUpgradeError as E;
1518        use package_upgrade_error::PackageUpgradeErrorKind;
1519
1520        let mut message = Self::default();
1521
1522        let kind = match value {
1523            E::UnableToFetchPackage { package_id } => {
1524                message.package_id = Some(package_id.to_canonical_string(true));
1525                PackageUpgradeErrorKind::UnableToFetchPackage
1526            }
1527            E::NotAPackage { object_id } => {
1528                message.package_id = Some(object_id.to_canonical_string(true));
1529                PackageUpgradeErrorKind::NotAPackage
1530            }
1531            E::IncompatibleUpgrade => PackageUpgradeErrorKind::IncompatibleUpgrade,
1532            E::DigestDoesNotMatch { digest } => {
1533                message.digest = crate::digests::Digest::try_from(digest)
1534                    .ok()
1535                    .map(|d| d.to_string());
1536                PackageUpgradeErrorKind::DigestDoesNotMatch
1537            }
1538            E::UnknownUpgradePolicy { policy } => {
1539                message.policy = Some(policy.into());
1540                PackageUpgradeErrorKind::UnknownUpgradePolicy
1541            }
1542            E::PackageIDDoesNotMatch {
1543                package_id,
1544                ticket_id,
1545            } => {
1546                message.package_id = Some(package_id.to_canonical_string(true));
1547                message.ticket_id = Some(ticket_id.to_canonical_string(true));
1548                PackageUpgradeErrorKind::PackageIdDoesNotMatch
1549            }
1550        };
1551
1552        message.set_kind(kind);
1553        message
1554    }
1555}
1556
1557//
1558// MoveLocation
1559//
1560
1561impl From<crate::execution_status::MoveLocation> for MoveLocation {
1562    fn from(value: crate::execution_status::MoveLocation) -> Self {
1563        let mut message = Self::default();
1564        message.package = Some(value.module.address().to_canonical_string(true));
1565        message.module = Some(value.module.name().to_string());
1566        message.function = Some(value.function.into());
1567        message.instruction = Some(value.instruction.into());
1568        message.function_name = value.function_name.map(|name| name.to_string());
1569        message
1570    }
1571}
1572
1573//
1574// AuthorityQuorumSignInfo aka ValidatorAggregatedSignature
1575//
1576
1577impl<const T: bool> From<crate::crypto::AuthorityQuorumSignInfo<T>>
1578    for ValidatorAggregatedSignature
1579{
1580    fn from(value: crate::crypto::AuthorityQuorumSignInfo<T>) -> Self {
1581        let mut bitmap = Vec::new();
1582        value.signers_map.serialize_into(&mut bitmap).unwrap();
1583
1584        Self::default()
1585            .with_epoch(value.epoch)
1586            .with_signature(value.signature.as_ref().to_vec())
1587            .with_bitmap(bitmap)
1588    }
1589}
1590
1591impl<const T: bool> TryFrom<&ValidatorAggregatedSignature>
1592    for crate::crypto::AuthorityQuorumSignInfo<T>
1593{
1594    type Error = TryFromProtoError;
1595
1596    fn try_from(value: &ValidatorAggregatedSignature) -> Result<Self, Self::Error> {
1597        Ok(Self {
1598            epoch: value.epoch(),
1599            signature: crate::crypto::AggregateAuthoritySignature::from_bytes(value.signature())
1600                .map_err(|e| TryFromProtoError::invalid("signature", e))?,
1601            signers_map: crate::sui_serde::deserialize_sui_bitmap(value.bitmap())
1602                .map_err(|e| TryFromProtoError::invalid("bitmap", e))?,
1603        })
1604    }
1605}
1606
1607//
1608// ValidatorCommittee
1609//
1610
1611impl From<crate::committee::Committee> for ValidatorCommittee {
1612    fn from(value: crate::committee::Committee) -> Self {
1613        let mut message = Self::default();
1614        message.epoch = Some(value.epoch);
1615        message.members = value
1616            .voting_rights
1617            .into_iter()
1618            .map(|(name, weight)| {
1619                let mut member = ValidatorCommitteeMember::default();
1620                member.public_key = Some(name.0.to_vec().into());
1621                member.weight = Some(weight);
1622                member
1623            })
1624            .collect();
1625        message
1626    }
1627}
1628
1629impl TryFrom<&ValidatorCommittee> for crate::committee::Committee {
1630    type Error = TryFromProtoError;
1631
1632    fn try_from(s: &ValidatorCommittee) -> Result<Self, Self::Error> {
1633        let members = s
1634            .members()
1635            .iter()
1636            .map(|member| {
1637                let public_key =
1638                    crate::crypto::AuthorityPublicKeyBytes::from_bytes(member.public_key())
1639                        .map_err(|e| TryFromProtoError::invalid("public_key", e))?;
1640                Ok((public_key, member.weight()))
1641            })
1642            .collect::<Result<_, _>>()?;
1643        Ok(Self::new(s.epoch(), members))
1644    }
1645}
1646
1647//
1648// ZkLoginAuthenticator
1649//
1650
1651impl From<&crate::zk_login_authenticator::ZkLoginAuthenticator> for ZkLoginAuthenticator {
1652    fn from(value: &crate::zk_login_authenticator::ZkLoginAuthenticator) -> Self {
1653        //TODO implement this without going through the sdk type
1654        let mut inputs = ZkLoginInputs::default();
1655        inputs.address_seed = Some(value.inputs.get_address_seed().to_string());
1656        let mut message = Self::default();
1657        message.inputs = Some(inputs);
1658        message.max_epoch = Some(value.get_max_epoch());
1659        message.signature = Some(value.user_signature.clone().into());
1660
1661        sui_sdk_types::ZkLoginAuthenticator::try_from(value.clone())
1662            .map(Into::into)
1663            .ok()
1664            .unwrap_or(message)
1665    }
1666}
1667
1668//
1669// ZkLoginPublicIdentifier
1670//
1671
1672impl From<&crate::crypto::ZkLoginPublicIdentifier> for ZkLoginPublicIdentifier {
1673    fn from(value: &crate::crypto::ZkLoginPublicIdentifier) -> Self {
1674        //TODO implement this without going through the sdk type
1675        sui_sdk_types::ZkLoginPublicIdentifier::try_from(value.to_owned())
1676            .map(|id| (&id).into())
1677            .ok()
1678            .unwrap_or_default()
1679    }
1680}
1681
1682//
1683// SignatureScheme
1684//
1685
1686impl From<crate::crypto::SignatureScheme> for SignatureScheme {
1687    fn from(value: crate::crypto::SignatureScheme) -> Self {
1688        use crate::crypto::SignatureScheme as S;
1689
1690        match value {
1691            S::ED25519 => Self::Ed25519,
1692            S::Secp256k1 => Self::Secp256k1,
1693            S::Secp256r1 => Self::Secp256r1,
1694            S::BLS12381 => Self::Bls12381,
1695            S::MultiSig => Self::Multisig,
1696            S::ZkLoginAuthenticator => Self::Zklogin,
1697            S::PasskeyAuthenticator => Self::Passkey,
1698        }
1699    }
1700}
1701
1702//
1703// SimpleSignature
1704//
1705
1706impl From<crate::crypto::Signature> for SimpleSignature {
1707    fn from(value: crate::crypto::Signature) -> Self {
1708        Self::from(&value)
1709    }
1710}
1711
1712impl From<&crate::crypto::Signature> for SimpleSignature {
1713    fn from(value: &crate::crypto::Signature) -> Self {
1714        let scheme: SignatureScheme = value.scheme().into();
1715        let signature = value.signature_bytes();
1716        let public_key = value.public_key_bytes();
1717
1718        let mut message = Self::default();
1719        message.scheme = Some(scheme.into());
1720        message.signature = Some(signature.to_vec().into());
1721        message.public_key = Some(public_key.to_vec().into());
1722        message
1723    }
1724}
1725
1726//
1727// PasskeyAuthenticator
1728//
1729
1730impl From<&crate::passkey_authenticator::PasskeyAuthenticator> for PasskeyAuthenticator {
1731    fn from(value: &crate::passkey_authenticator::PasskeyAuthenticator) -> Self {
1732        let mut message = Self::default();
1733        message.authenticator_data = Some(value.authenticator_data().to_vec().into());
1734        message.client_data_json = Some(value.client_data_json().to_owned());
1735        message.signature = Some(value.signature().into());
1736        message
1737    }
1738}
1739
1740//
1741// MultisigMemberPublicKey
1742//
1743
1744impl From<&crate::crypto::PublicKey> for MultisigMemberPublicKey {
1745    fn from(value: &crate::crypto::PublicKey) -> Self {
1746        let mut message = Self::default();
1747
1748        match value {
1749            crate::crypto::PublicKey::Ed25519(_)
1750            | crate::crypto::PublicKey::Secp256k1(_)
1751            | crate::crypto::PublicKey::Secp256r1(_)
1752            | crate::crypto::PublicKey::Passkey(_) => {
1753                message.public_key = Some(value.as_ref().to_vec().into());
1754            }
1755            crate::crypto::PublicKey::ZkLogin(z) => {
1756                message.zklogin = Some(z.into());
1757            }
1758        }
1759
1760        message.set_scheme(value.scheme().into());
1761        message
1762    }
1763}
1764
1765//
1766// MultisigCommittee
1767//
1768
1769impl From<&crate::multisig::MultiSigPublicKey> for MultisigCommittee {
1770    fn from(value: &crate::multisig::MultiSigPublicKey) -> Self {
1771        let mut message = Self::default();
1772        message.members = value
1773            .pubkeys()
1774            .iter()
1775            .map(|(pk, weight)| {
1776                let mut member = MultisigMember::default();
1777                member.public_key = Some(pk.into());
1778                member.weight = Some((*weight).into());
1779                member
1780            })
1781            .collect();
1782        message.threshold = Some((*value.threshold()).into());
1783        message
1784    }
1785}
1786
1787impl From<&crate::multisig_legacy::MultiSigPublicKeyLegacy> for MultisigCommittee {
1788    fn from(value: &crate::multisig_legacy::MultiSigPublicKeyLegacy) -> Self {
1789        let mut message = Self::default();
1790        message.members = value
1791            .pubkeys()
1792            .iter()
1793            .map(|(pk, weight)| {
1794                let mut member = MultisigMember::default();
1795                member.public_key = Some(pk.into());
1796                member.weight = Some((*weight).into());
1797                member
1798            })
1799            .collect();
1800        message.threshold = Some((*value.threshold()).into());
1801        message
1802    }
1803}
1804
1805//
1806// MultisigMemberSignature
1807//
1808
1809impl From<&crate::crypto::CompressedSignature> for MultisigMemberSignature {
1810    fn from(value: &crate::crypto::CompressedSignature) -> Self {
1811        let mut message = Self::default();
1812
1813        let scheme = match value {
1814            crate::crypto::CompressedSignature::Ed25519(b) => {
1815                message.signature = Some(b.0.to_vec().into());
1816                SignatureScheme::Ed25519
1817            }
1818            crate::crypto::CompressedSignature::Secp256k1(b) => {
1819                message.signature = Some(b.0.to_vec().into());
1820                SignatureScheme::Secp256k1
1821            }
1822            crate::crypto::CompressedSignature::Secp256r1(b) => {
1823                message.signature = Some(b.0.to_vec().into());
1824                SignatureScheme::Secp256r1
1825            }
1826            crate::crypto::CompressedSignature::ZkLogin(_z) => {
1827                //TODO
1828                SignatureScheme::Zklogin
1829            }
1830            crate::crypto::CompressedSignature::Passkey(_p) => {
1831                //TODO
1832                SignatureScheme::Passkey
1833            }
1834        };
1835
1836        message.set_scheme(scheme);
1837        message
1838    }
1839}
1840
1841//
1842// MultisigAggregatedSignature
1843//
1844
1845impl From<&crate::multisig_legacy::MultiSigLegacy> for MultisigAggregatedSignature {
1846    fn from(value: &crate::multisig_legacy::MultiSigLegacy) -> Self {
1847        let mut legacy_bitmap = Vec::new();
1848        value
1849            .get_bitmap()
1850            .serialize_into(&mut legacy_bitmap)
1851            .unwrap();
1852
1853        Self::default()
1854            .with_signatures(value.get_sigs().iter().map(Into::into).collect())
1855            .with_legacy_bitmap(legacy_bitmap)
1856            .with_committee(value.get_pk())
1857    }
1858}
1859
1860impl From<&crate::multisig::MultiSig> for MultisigAggregatedSignature {
1861    fn from(value: &crate::multisig::MultiSig) -> Self {
1862        let mut message = Self::default();
1863        message.signatures = value.get_sigs().iter().map(Into::into).collect();
1864        message.bitmap = Some(value.get_bitmap().into());
1865        message.committee = Some(value.get_pk().into());
1866        message
1867    }
1868}
1869
1870//
1871// UserSignature
1872//
1873
1874impl From<&crate::signature::GenericSignature> for UserSignature {
1875    fn from(value: &crate::signature::GenericSignature) -> Self {
1876        Self::merge_from(value, &FieldMaskTree::new_wildcard())
1877    }
1878}
1879
1880impl Merge<&crate::signature::GenericSignature> for UserSignature {
1881    fn merge(&mut self, source: &crate::signature::GenericSignature, mask: &FieldMaskTree) {
1882        use user_signature::Signature;
1883
1884        if mask.contains(Self::BCS_FIELD) {
1885            let mut bcs = Bcs::from(source.as_ref().to_vec());
1886            bcs.name = Some("UserSignatureBytes".to_owned());
1887            self.bcs = Some(bcs);
1888        }
1889
1890        let scheme = match source {
1891            crate::signature::GenericSignature::MultiSig(multi_sig) => {
1892                if mask.contains(Self::MULTISIG_FIELD) {
1893                    self.signature = Some(Signature::Multisig(multi_sig.into()));
1894                }
1895                SignatureScheme::Multisig
1896            }
1897            crate::signature::GenericSignature::MultiSigLegacy(multi_sig_legacy) => {
1898                if mask.contains(Self::MULTISIG_FIELD) {
1899                    self.signature = Some(Signature::Multisig(multi_sig_legacy.into()));
1900                }
1901                SignatureScheme::Multisig
1902            }
1903            crate::signature::GenericSignature::Signature(signature) => {
1904                let scheme = signature.scheme().into();
1905                if mask.contains(Self::SIMPLE_FIELD) {
1906                    self.signature = Some(Signature::Simple(signature.into()));
1907                }
1908                scheme
1909            }
1910            crate::signature::GenericSignature::ZkLoginAuthenticator(z) => {
1911                if mask.contains(Self::ZKLOGIN_FIELD) {
1912                    self.signature = Some(Signature::Zklogin(z.into()));
1913                }
1914                SignatureScheme::Zklogin
1915            }
1916            crate::signature::GenericSignature::PasskeyAuthenticator(p) => {
1917                if mask.contains(Self::PASSKEY_FIELD) {
1918                    self.signature = Some(Signature::Passkey(p.into()));
1919                }
1920                SignatureScheme::Passkey
1921            }
1922        };
1923
1924        if mask.contains(Self::SCHEME_FIELD) {
1925            self.set_scheme(scheme);
1926        }
1927    }
1928}
1929
1930//
1931// BalanceChange
1932//
1933
1934impl From<crate::balance_change::BalanceChange> for BalanceChange {
1935    fn from(value: crate::balance_change::BalanceChange) -> Self {
1936        let mut message = Self::default();
1937        message.address = Some(value.address.to_string());
1938        message.coin_type = Some(value.coin_type.to_canonical_string(true));
1939        message.amount = Some(value.amount.to_string());
1940        message
1941    }
1942}
1943
1944impl TryFrom<&BalanceChange> for crate::balance_change::BalanceChange {
1945    type Error = TryFromProtoError;
1946
1947    fn try_from(value: &BalanceChange) -> Result<Self, Self::Error> {
1948        Ok(Self {
1949            address: value
1950                .address()
1951                .parse()
1952                .map_err(|e| TryFromProtoError::invalid(BalanceChange::ADDRESS_FIELD, e))?,
1953            coin_type: value
1954                .coin_type()
1955                .parse()
1956                .map_err(|e| TryFromProtoError::invalid(BalanceChange::COIN_TYPE_FIELD, e))?,
1957            amount: value
1958                .amount()
1959                .parse()
1960                .map_err(|e| TryFromProtoError::invalid(BalanceChange::AMOUNT_FIELD, e))?,
1961        })
1962    }
1963}
1964
1965//
1966// Object
1967//
1968
1969pub const PACKAGE_TYPE: &str = "package";
1970
1971impl From<crate::object::Object> for Object {
1972    fn from(value: crate::object::Object) -> Self {
1973        Self::merge_from(&value, &FieldMaskTree::new_wildcard())
1974    }
1975}
1976
1977impl Merge<&crate::object::Object> for Object {
1978    fn merge(&mut self, source: &crate::object::Object, mask: &FieldMaskTree) {
1979        if mask.contains(Self::BCS_FIELD.name) {
1980            let mut bcs = Bcs::serialize(&source).unwrap();
1981            bcs.name = Some("Object".to_owned());
1982            self.bcs = Some(bcs);
1983        }
1984
1985        if mask.contains(Self::DIGEST_FIELD.name) {
1986            self.digest = Some(source.digest().to_string());
1987        }
1988
1989        if mask.contains(Self::OBJECT_ID_FIELD.name) {
1990            self.object_id = Some(source.id().to_canonical_string(true));
1991        }
1992
1993        if mask.contains(Self::VERSION_FIELD.name) {
1994            self.version = Some(source.version().value());
1995        }
1996
1997        if mask.contains(Self::OWNER_FIELD.name) {
1998            self.owner = Some(source.owner().to_owned().into());
1999        }
2000
2001        if mask.contains(Self::PREVIOUS_TRANSACTION_FIELD.name) {
2002            self.previous_transaction = Some(source.previous_transaction.to_string());
2003        }
2004
2005        if mask.contains(Self::STORAGE_REBATE_FIELD.name) {
2006            self.storage_rebate = Some(source.storage_rebate);
2007        }
2008
2009        if mask.contains(Self::BALANCE_FIELD) {
2010            self.balance = source.as_coin_maybe().map(|coin| coin.balance.value());
2011        }
2012
2013        self.merge(&source.data, mask);
2014    }
2015}
2016
2017impl Merge<&crate::object::MoveObject> for Object {
2018    fn merge(&mut self, source: &crate::object::MoveObject, mask: &FieldMaskTree) {
2019        self.object_id = Some(source.id().to_canonical_string(true));
2020        self.version = Some(source.version().value());
2021
2022        if mask.contains(Self::OBJECT_TYPE_FIELD.name) {
2023            self.object_type = Some(source.type_().to_canonical_string(true));
2024        }
2025
2026        if mask.contains(Self::HAS_PUBLIC_TRANSFER_FIELD.name) {
2027            self.has_public_transfer = Some(source.has_public_transfer());
2028        }
2029
2030        if mask.contains(Self::CONTENTS_FIELD.name) {
2031            let mut bcs = Bcs::from(source.contents().to_vec());
2032            bcs.name = Some(source.type_().to_canonical_string(true));
2033            self.contents = Some(bcs);
2034        }
2035    }
2036}
2037
2038impl Merge<&crate::move_package::MovePackage> for Object {
2039    fn merge(&mut self, source: &crate::move_package::MovePackage, mask: &FieldMaskTree) {
2040        self.object_id = Some(source.id().to_canonical_string(true));
2041        self.version = Some(source.version().value());
2042
2043        if mask.contains(Self::OBJECT_TYPE_FIELD.name) {
2044            self.object_type = Some(PACKAGE_TYPE.to_owned());
2045        }
2046
2047        if mask.contains(Self::PACKAGE_FIELD.name) {
2048            let mut package = Package::default();
2049            package.modules = source
2050                .serialized_module_map()
2051                .iter()
2052                .map(|(name, contents)| {
2053                    let mut module = Module::default();
2054                    module.name = Some(name.to_string());
2055                    module.contents = Some(contents.clone().into());
2056                    module
2057                })
2058                .collect();
2059            package.type_origins = source
2060                .type_origin_table()
2061                .clone()
2062                .into_iter()
2063                .map(Into::into)
2064                .collect();
2065            package.linkage = source
2066                .linkage_table()
2067                .iter()
2068                .map(
2069                    |(
2070                        original_id,
2071                        crate::move_package::UpgradeInfo {
2072                            upgraded_id,
2073                            upgraded_version,
2074                        },
2075                    )| {
2076                        let mut linkage = Linkage::default();
2077                        linkage.original_id = Some(original_id.to_canonical_string(true));
2078                        linkage.upgraded_id = Some(upgraded_id.to_canonical_string(true));
2079                        linkage.upgraded_version = Some(upgraded_version.value());
2080                        linkage
2081                    },
2082                )
2083                .collect();
2084
2085            self.package = Some(package);
2086        }
2087    }
2088}
2089
2090impl Merge<&crate::object::Data> for Object {
2091    fn merge(&mut self, source: &crate::object::Data, mask: &FieldMaskTree) {
2092        match source {
2093            crate::object::Data::Move(object) => self.merge(object, mask),
2094            crate::object::Data::Package(package) => self.merge(package, mask),
2095        }
2096    }
2097}
2098
2099//
2100// TypeOrigin
2101//
2102
2103impl From<crate::move_package::TypeOrigin> for TypeOrigin {
2104    fn from(value: crate::move_package::TypeOrigin) -> Self {
2105        let mut message = Self::default();
2106        message.module_name = Some(value.module_name.to_string());
2107        message.datatype_name = Some(value.datatype_name.to_string());
2108        message.package_id = Some(value.package.to_canonical_string(true));
2109        message
2110    }
2111}
2112
2113//
2114// GenesisObject
2115//
2116
2117impl From<crate::transaction::GenesisObject> for Object {
2118    fn from(value: crate::transaction::GenesisObject) -> Self {
2119        let crate::transaction::GenesisObject::RawObject { data, owner } = value;
2120        let mut message = Self::default();
2121        message.owner = Some(owner.into());
2122
2123        message.merge(&data, &FieldMaskTree::new_wildcard());
2124
2125        message
2126    }
2127}
2128
2129//
2130// ObjectReference
2131//
2132
2133pub trait ObjectRefExt {
2134    fn to_proto(self) -> ObjectReference;
2135}
2136
2137pub trait ObjectReferenceExt {
2138    fn try_to_object_ref(&self) -> Result<crate::base_types::ObjectRef, anyhow::Error>;
2139}
2140
2141impl ObjectRefExt for crate::base_types::ObjectRef {
2142    fn to_proto(self) -> ObjectReference {
2143        let (object_id, version, digest) = self;
2144        let mut message = ObjectReference::default();
2145        message.object_id = Some(object_id.to_canonical_string(true));
2146        message.version = Some(version.value());
2147        message.digest = Some(digest.to_string());
2148        message
2149    }
2150}
2151
2152impl ObjectReferenceExt for ObjectReference {
2153    fn try_to_object_ref(&self) -> Result<crate::base_types::ObjectRef, anyhow::Error> {
2154        use anyhow::Context;
2155
2156        let object_id = self
2157            .object_id_opt()
2158            .ok_or_else(|| anyhow::anyhow!("missing object_id"))?;
2159        let object_id = crate::base_types::ObjectID::from_hex_literal(object_id)
2160            .with_context(|| format!("Failed to parse object_id: {}", object_id))?;
2161
2162        let version = self
2163            .version_opt()
2164            .ok_or_else(|| anyhow::anyhow!("missing version"))?;
2165        let version = crate::base_types::SequenceNumber::from(version);
2166
2167        let digest = self
2168            .digest_opt()
2169            .ok_or_else(|| anyhow::anyhow!("missing digest"))?;
2170        let digest = digest
2171            .parse::<crate::digests::ObjectDigest>()
2172            .with_context(|| format!("Failed to parse digest: {}", digest))?;
2173
2174        Ok((object_id, version, digest))
2175    }
2176}
2177
2178impl From<&crate::storage::ObjectKey> for ObjectReference {
2179    fn from(value: &crate::storage::ObjectKey) -> Self {
2180        Self::default()
2181            .with_object_id(value.0.to_canonical_string(true))
2182            .with_version(value.1.value())
2183    }
2184}
2185
2186//
2187// Owner
2188//
2189
2190impl From<crate::object::Owner> for Owner {
2191    fn from(value: crate::object::Owner) -> Self {
2192        use crate::object::Owner as O;
2193        use owner::OwnerKind;
2194
2195        let mut message = Self::default();
2196
2197        let kind = match value {
2198            O::AddressOwner(address) => {
2199                message.address = Some(address.to_string());
2200                OwnerKind::Address
2201            }
2202            O::ObjectOwner(address) => {
2203                message.address = Some(address.to_string());
2204                OwnerKind::Object
2205            }
2206            O::Shared {
2207                initial_shared_version,
2208            } => {
2209                message.version = Some(initial_shared_version.value());
2210                OwnerKind::Shared
2211            }
2212            O::Immutable => OwnerKind::Immutable,
2213            O::ConsensusAddressOwner {
2214                start_version,
2215                owner,
2216            } => {
2217                message.version = Some(start_version.value());
2218                message.address = Some(owner.to_string());
2219                OwnerKind::ConsensusAddress
2220            }
2221            // TODO(Party WIP)
2222            O::Party { .. } => todo!("Party WIP"),
2223        };
2224
2225        message.set_kind(kind);
2226        message
2227    }
2228}
2229
2230//
2231// Transaction
2232//
2233
2234impl From<crate::transaction::TransactionData> for Transaction {
2235    fn from(value: crate::transaction::TransactionData) -> Self {
2236        Self::merge_from(&value, &FieldMaskTree::new_wildcard())
2237    }
2238}
2239
2240impl Merge<&crate::transaction::TransactionData> for Transaction {
2241    fn merge(&mut self, source: &crate::transaction::TransactionData, mask: &FieldMaskTree) {
2242        merge_transaction_data(self, source, None, mask);
2243    }
2244}
2245
2246fn merge_transaction_data(
2247    message: &mut Transaction,
2248    source: &crate::transaction::TransactionData,
2249    precomputed_digest_string: Option<String>,
2250    mask: &FieldMaskTree,
2251) {
2252    if mask.contains(Transaction::BCS_FIELD.name) {
2253        let mut bcs = Bcs::serialize(&source).unwrap();
2254        bcs.name = Some("TransactionData".to_owned());
2255        message.bcs = Some(bcs);
2256    }
2257
2258    if mask.contains(Transaction::DIGEST_FIELD.name) {
2259        message.digest =
2260            Some(precomputed_digest_string.unwrap_or_else(|| source.digest().base58_encode()));
2261    }
2262
2263    if mask.contains(Transaction::VERSION_FIELD.name) {
2264        message.version = Some(1);
2265    }
2266
2267    let crate::transaction::TransactionData::V1(source) = source;
2268
2269    if mask.contains(Transaction::KIND_FIELD.name) {
2270        message.kind = Some(source.kind.clone().into());
2271    }
2272
2273    if mask.contains(Transaction::SENDER_FIELD.name) {
2274        message.sender = Some(source.sender.to_string());
2275    }
2276
2277    if mask.contains(Transaction::GAS_PAYMENT_FIELD.name) {
2278        message.gas_payment = Some((&source.gas_data).into());
2279    }
2280
2281    if mask.contains(Transaction::EXPIRATION_FIELD.name) {
2282        message.expiration = Some(source.expiration.into());
2283    }
2284}
2285
2286//
2287// GasPayment
2288//
2289
2290impl From<&crate::transaction::GasData> for GasPayment {
2291    fn from(value: &crate::transaction::GasData) -> Self {
2292        let mut message = Self::default();
2293        message.objects = value
2294            .payment
2295            .iter()
2296            .map(|obj_ref| obj_ref.to_proto())
2297            .collect();
2298        message.owner = Some(value.owner.to_string());
2299        message.price = Some(value.price);
2300        message.budget = Some(value.budget);
2301        message
2302    }
2303}
2304
2305//
2306// TransactionExpiration
2307//
2308
2309impl From<crate::transaction::TransactionExpiration> for TransactionExpiration {
2310    fn from(value: crate::transaction::TransactionExpiration) -> Self {
2311        use crate::transaction::TransactionExpiration as E;
2312        use transaction_expiration::TransactionExpirationKind;
2313
2314        let mut message = Self::default();
2315
2316        let kind = match value {
2317            E::None => TransactionExpirationKind::None,
2318            E::Epoch(epoch) => {
2319                message.epoch = Some(epoch);
2320                TransactionExpirationKind::Epoch
2321            }
2322            E::ValidDuring {
2323                min_epoch,
2324                max_epoch,
2325                min_timestamp,
2326                max_timestamp,
2327                chain,
2328                nonce,
2329            } => {
2330                message.epoch = max_epoch;
2331                message.min_epoch = min_epoch;
2332                message.min_timestamp = min_timestamp.map(ms_to_timestamp);
2333                message.max_timestamp = max_timestamp.map(ms_to_timestamp);
2334                message.set_chain(sui_sdk_types::Digest::new(*chain.as_bytes()));
2335                message.set_nonce(nonce);
2336
2337                TransactionExpirationKind::ValidDuring
2338            }
2339        };
2340
2341        message.set_kind(kind);
2342        message
2343    }
2344}
2345
2346impl TryFrom<&TransactionExpiration> for crate::transaction::TransactionExpiration {
2347    type Error = &'static str;
2348
2349    fn try_from(value: &TransactionExpiration) -> Result<Self, Self::Error> {
2350        use transaction_expiration::TransactionExpirationKind;
2351
2352        Ok(match value.kind() {
2353            TransactionExpirationKind::None => Self::None,
2354            TransactionExpirationKind::Epoch => Self::Epoch(value.epoch()),
2355            TransactionExpirationKind::ValidDuring => {
2356                let chain_str = value
2357                    .chain
2358                    .as_deref()
2359                    .ok_or("ValidDuring expiration is missing chain")?;
2360                let chain_digest: sui_sdk_types::Digest = chain_str
2361                    .parse()
2362                    .map_err(|_| "ValidDuring expiration has invalid chain digest")?;
2363                let chain = crate::digests::ChainIdentifier::from(
2364                    crate::digests::CheckpointDigest::new(chain_digest.into_inner()),
2365                );
2366                let nonce = value
2367                    .nonce
2368                    .ok_or("ValidDuring expiration is missing nonce")?;
2369                let min_timestamp = value
2370                    .min_timestamp
2371                    .as_ref()
2372                    .map(timestamp_to_ms)
2373                    .transpose()?;
2374                let max_timestamp = value
2375                    .max_timestamp
2376                    .as_ref()
2377                    .map(timestamp_to_ms)
2378                    .transpose()?;
2379                Self::ValidDuring {
2380                    min_epoch: value.min_epoch,
2381                    max_epoch: value.epoch,
2382                    min_timestamp,
2383                    max_timestamp,
2384                    chain,
2385                    nonce,
2386                }
2387            }
2388            TransactionExpirationKind::Unknown | _ => {
2389                return Err("unknown TransactionExpirationKind");
2390            }
2391        })
2392    }
2393}
2394
2395//
2396// TransactionKind
2397//
2398
2399impl From<crate::transaction::TransactionKind> for TransactionKind {
2400    fn from(value: crate::transaction::TransactionKind) -> Self {
2401        use crate::transaction::TransactionKind as K;
2402        use transaction_kind::Kind;
2403
2404        let message = Self::default();
2405
2406        match value {
2407            K::ProgrammableTransaction(ptb) => message
2408                .with_programmable_transaction(ptb)
2409                .with_kind(Kind::ProgrammableTransaction),
2410            K::ChangeEpoch(change_epoch) => message
2411                .with_change_epoch(change_epoch)
2412                .with_kind(Kind::ChangeEpoch),
2413            K::Genesis(genesis) => message.with_genesis(genesis).with_kind(Kind::Genesis),
2414            K::ConsensusCommitPrologue(prologue) => message
2415                .with_consensus_commit_prologue(prologue)
2416                .with_kind(Kind::ConsensusCommitPrologueV1),
2417            K::AuthenticatorStateUpdate(update) => message
2418                .with_authenticator_state_update(update)
2419                .with_kind(Kind::AuthenticatorStateUpdate),
2420            K::EndOfEpochTransaction(transactions) => message
2421                .with_end_of_epoch({
2422                    EndOfEpochTransaction::default()
2423                        .with_transactions(transactions.into_iter().map(Into::into).collect())
2424                })
2425                .with_kind(Kind::EndOfEpoch),
2426            K::RandomnessStateUpdate(update) => message
2427                .with_randomness_state_update(update)
2428                .with_kind(Kind::RandomnessStateUpdate),
2429            K::ConsensusCommitPrologueV2(prologue) => message
2430                .with_consensus_commit_prologue(prologue)
2431                .with_kind(Kind::ConsensusCommitPrologueV2),
2432            K::ConsensusCommitPrologueV3(prologue) => message
2433                .with_consensus_commit_prologue(prologue)
2434                .with_kind(Kind::ConsensusCommitPrologueV3),
2435            K::ConsensusCommitPrologueV4(prologue) => message
2436                .with_consensus_commit_prologue(prologue)
2437                .with_kind(Kind::ConsensusCommitPrologueV4),
2438            K::ProgrammableSystemTransaction(ptb) => message
2439                .with_programmable_transaction(ptb)
2440                .with_kind(Kind::ProgrammableSystemTransaction),
2441        }
2442    }
2443}
2444
2445//
2446// ConsensusCommitPrologue
2447//
2448
2449impl From<crate::messages_consensus::ConsensusCommitPrologue> for ConsensusCommitPrologue {
2450    fn from(value: crate::messages_consensus::ConsensusCommitPrologue) -> Self {
2451        let mut message = Self::default();
2452        message.epoch = Some(value.epoch);
2453        message.round = Some(value.round);
2454        message.commit_timestamp = Some(sui_rpc::proto::timestamp_ms_to_proto(
2455            value.commit_timestamp_ms,
2456        ));
2457        message
2458    }
2459}
2460
2461impl From<crate::messages_consensus::ConsensusCommitPrologueV2> for ConsensusCommitPrologue {
2462    fn from(value: crate::messages_consensus::ConsensusCommitPrologueV2) -> Self {
2463        let mut message = Self::default();
2464        message.epoch = Some(value.epoch);
2465        message.round = Some(value.round);
2466        message.commit_timestamp = Some(sui_rpc::proto::timestamp_ms_to_proto(
2467            value.commit_timestamp_ms,
2468        ));
2469        message.consensus_commit_digest = Some(value.consensus_commit_digest.to_string());
2470        message
2471    }
2472}
2473
2474impl From<crate::messages_consensus::ConsensusCommitPrologueV3> for ConsensusCommitPrologue {
2475    fn from(value: crate::messages_consensus::ConsensusCommitPrologueV3) -> Self {
2476        let mut message = Self::default();
2477        message.epoch = Some(value.epoch);
2478        message.round = Some(value.round);
2479        message.commit_timestamp = Some(sui_rpc::proto::timestamp_ms_to_proto(
2480            value.commit_timestamp_ms,
2481        ));
2482        message.consensus_commit_digest = Some(value.consensus_commit_digest.to_string());
2483        message.sub_dag_index = value.sub_dag_index;
2484        message.consensus_determined_version_assignments =
2485            Some(value.consensus_determined_version_assignments.into());
2486        message
2487    }
2488}
2489
2490impl From<crate::messages_consensus::ConsensusCommitPrologueV4> for ConsensusCommitPrologue {
2491    fn from(
2492        crate::messages_consensus::ConsensusCommitPrologueV4 {
2493            epoch,
2494            round,
2495            sub_dag_index,
2496            commit_timestamp_ms,
2497            consensus_commit_digest,
2498            consensus_determined_version_assignments,
2499            additional_state_digest,
2500        }: crate::messages_consensus::ConsensusCommitPrologueV4,
2501    ) -> Self {
2502        let mut message = Self::default();
2503        message.epoch = Some(epoch);
2504        message.round = Some(round);
2505        message.commit_timestamp = Some(sui_rpc::proto::timestamp_ms_to_proto(commit_timestamp_ms));
2506        message.consensus_commit_digest = Some(consensus_commit_digest.to_string());
2507        message.sub_dag_index = sub_dag_index;
2508        message.consensus_determined_version_assignments =
2509            Some(consensus_determined_version_assignments.into());
2510        message.additional_state_digest = Some(additional_state_digest.to_string());
2511        message
2512    }
2513}
2514
2515//
2516// ConsensusDeterminedVersionAssignments
2517//
2518
2519impl From<crate::messages_consensus::ConsensusDeterminedVersionAssignments>
2520    for ConsensusDeterminedVersionAssignments
2521{
2522    fn from(value: crate::messages_consensus::ConsensusDeterminedVersionAssignments) -> Self {
2523        use crate::messages_consensus::ConsensusDeterminedVersionAssignments as A;
2524
2525        let mut message = Self::default();
2526
2527        let version = match value {
2528            A::CancelledTransactions(canceled_transactions) => {
2529                message.canceled_transactions = canceled_transactions
2530                    .into_iter()
2531                    .map(|(tx_digest, assignments)| {
2532                        let mut message = CanceledTransaction::default();
2533                        message.digest = Some(tx_digest.to_string());
2534                        message.version_assignments = assignments
2535                            .into_iter()
2536                            .map(|(id, version)| {
2537                                let mut message = VersionAssignment::default();
2538                                message.object_id = Some(id.to_canonical_string(true));
2539                                message.version = Some(version.value());
2540                                message
2541                            })
2542                            .collect();
2543                        message
2544                    })
2545                    .collect();
2546                1
2547            }
2548            A::CancelledTransactionsV2(canceled_transactions) => {
2549                message.canceled_transactions = canceled_transactions
2550                    .into_iter()
2551                    .map(|(tx_digest, assignments)| {
2552                        let mut message = CanceledTransaction::default();
2553                        message.digest = Some(tx_digest.to_string());
2554                        message.version_assignments = assignments
2555                            .into_iter()
2556                            .map(|((id, start_version), version)| {
2557                                let mut message = VersionAssignment::default();
2558                                message.object_id = Some(id.to_canonical_string(true));
2559                                message.start_version = Some(start_version.value());
2560                                message.version = Some(version.value());
2561                                message
2562                            })
2563                            .collect();
2564                        message
2565                    })
2566                    .collect();
2567                2
2568            }
2569        };
2570
2571        message.version = Some(version);
2572        message
2573    }
2574}
2575
2576//
2577// GenesisTransaction
2578//
2579
2580impl From<crate::transaction::GenesisTransaction> for GenesisTransaction {
2581    fn from(value: crate::transaction::GenesisTransaction) -> Self {
2582        let mut message = Self::default();
2583        message.objects = value.objects.into_iter().map(Into::into).collect();
2584        message
2585    }
2586}
2587
2588//
2589// RandomnessStateUpdate
2590//
2591
2592impl From<crate::transaction::RandomnessStateUpdate> for RandomnessStateUpdate {
2593    fn from(value: crate::transaction::RandomnessStateUpdate) -> Self {
2594        let mut message = Self::default();
2595        message.epoch = Some(value.epoch);
2596        message.randomness_round = Some(value.randomness_round.0);
2597        message.random_bytes = Some(value.random_bytes.into());
2598        message.randomness_object_initial_shared_version =
2599            Some(value.randomness_obj_initial_shared_version.value());
2600        message
2601    }
2602}
2603
2604//
2605// AuthenticatorStateUpdate
2606//
2607
2608impl From<crate::transaction::AuthenticatorStateUpdate> for AuthenticatorStateUpdate {
2609    fn from(value: crate::transaction::AuthenticatorStateUpdate) -> Self {
2610        let mut message = Self::default();
2611        message.epoch = Some(value.epoch);
2612        message.round = Some(value.round);
2613        message.new_active_jwks = value.new_active_jwks.into_iter().map(Into::into).collect();
2614        message.authenticator_object_initial_shared_version =
2615            Some(value.authenticator_obj_initial_shared_version.value());
2616        message
2617    }
2618}
2619
2620//
2621// ActiveJwk
2622//
2623
2624impl From<crate::authenticator_state::ActiveJwk> for ActiveJwk {
2625    fn from(value: crate::authenticator_state::ActiveJwk) -> Self {
2626        let mut jwk_id = JwkId::default();
2627        jwk_id.iss = Some(value.jwk_id.iss);
2628        jwk_id.kid = Some(value.jwk_id.kid);
2629
2630        let mut jwk = Jwk::default();
2631        jwk.kty = Some(value.jwk.kty);
2632        jwk.e = Some(value.jwk.e);
2633        jwk.n = Some(value.jwk.n);
2634        jwk.alg = Some(value.jwk.alg);
2635
2636        let mut message = Self::default();
2637        message.id = Some(jwk_id);
2638        message.jwk = Some(jwk);
2639        message.epoch = Some(value.epoch);
2640        message
2641    }
2642}
2643
2644//
2645// ChangeEpoch
2646//
2647
2648impl From<crate::transaction::ChangeEpoch> for ChangeEpoch {
2649    fn from(value: crate::transaction::ChangeEpoch) -> Self {
2650        let mut message = Self::default();
2651        message.epoch = Some(value.epoch);
2652        message.protocol_version = Some(value.protocol_version.as_u64());
2653        message.storage_charge = Some(value.storage_charge);
2654        message.computation_charge = Some(value.computation_charge);
2655        message.storage_rebate = Some(value.storage_rebate);
2656        message.non_refundable_storage_fee = Some(value.non_refundable_storage_fee);
2657        message.epoch_start_timestamp = Some(sui_rpc::proto::timestamp_ms_to_proto(
2658            value.epoch_start_timestamp_ms,
2659        ));
2660        message.system_packages = value
2661            .system_packages
2662            .into_iter()
2663            .map(|(version, modules, dependencies)| {
2664                let mut message = SystemPackage::default();
2665                message.version = Some(version.value());
2666                message.modules = modules.into_iter().map(Into::into).collect();
2667                message.dependencies = dependencies
2668                    .iter()
2669                    .map(|d| d.to_canonical_string(true))
2670                    .collect();
2671                message
2672            })
2673            .collect();
2674        message
2675    }
2676}
2677
2678//
2679// EndOfEpochTransactionkind
2680//
2681
2682impl From<crate::transaction::EndOfEpochTransactionKind> for EndOfEpochTransactionKind {
2683    fn from(value: crate::transaction::EndOfEpochTransactionKind) -> Self {
2684        use crate::transaction::EndOfEpochTransactionKind as K;
2685        use end_of_epoch_transaction_kind::Kind;
2686
2687        let message = Self::default();
2688
2689        match value {
2690            K::ChangeEpoch(change_epoch) => message
2691                .with_change_epoch(change_epoch)
2692                .with_kind(Kind::ChangeEpoch),
2693            K::AuthenticatorStateCreate => message.with_kind(Kind::AuthenticatorStateCreate),
2694            K::AuthenticatorStateExpire(expire) => message
2695                .with_authenticator_state_expire(expire)
2696                .with_kind(Kind::AuthenticatorStateExpire),
2697            K::RandomnessStateCreate => message.with_kind(Kind::RandomnessStateCreate),
2698            K::DenyListStateCreate => message.with_kind(Kind::DenyListStateCreate),
2699            K::BridgeStateCreate(chain_id) => message
2700                .with_bridge_chain_id(chain_id.to_string())
2701                .with_kind(Kind::BridgeStateCreate),
2702            K::BridgeCommitteeInit(bridge_object_version) => message
2703                .with_bridge_object_version(bridge_object_version.into())
2704                .with_kind(Kind::BridgeCommitteeInit),
2705            K::StoreExecutionTimeObservations(observations) => message
2706                .with_execution_time_observations(observations)
2707                .with_kind(Kind::StoreExecutionTimeObservations),
2708            K::AccumulatorRootCreate => message.with_kind(Kind::AccumulatorRootCreate),
2709            K::CoinRegistryCreate => message.with_kind(Kind::CoinRegistryCreate),
2710            K::DisplayRegistryCreate => message.with_kind(Kind::DisplayRegistryCreate),
2711            K::AddressAliasStateCreate => message.with_kind(Kind::AddressAliasStateCreate),
2712            K::WriteAccumulatorStorageCost(storage_cost) => message
2713                .with_kind(Kind::WriteAccumulatorStorageCost)
2714                .with_storage_cost(storage_cost.storage_cost),
2715        }
2716    }
2717}
2718
2719//
2720// AuthenticatorStateExpire
2721//
2722
2723impl From<crate::transaction::AuthenticatorStateExpire> for AuthenticatorStateExpire {
2724    fn from(value: crate::transaction::AuthenticatorStateExpire) -> Self {
2725        let mut message = Self::default();
2726        message.min_epoch = Some(value.min_epoch);
2727        message.authenticator_object_initial_shared_version =
2728            Some(value.authenticator_obj_initial_shared_version.value());
2729        message
2730    }
2731}
2732
2733// ExecutionTimeObservations
2734
2735impl From<crate::transaction::StoredExecutionTimeObservations> for ExecutionTimeObservations {
2736    fn from(value: crate::transaction::StoredExecutionTimeObservations) -> Self {
2737        let mut message = Self::default();
2738        match value {
2739            crate::transaction::StoredExecutionTimeObservations::V1(vec) => {
2740                message.version = Some(1);
2741                message.observations = vec
2742                    .into_iter()
2743                    .map(|(key, observation)| {
2744                        use crate::execution::ExecutionTimeObservationKey as K;
2745                        use execution_time_observation::ExecutionTimeObservationKind;
2746
2747                        let mut message = ExecutionTimeObservation::default();
2748
2749                        let kind = match key {
2750                            K::MoveEntryPoint {
2751                                package,
2752                                module,
2753                                function,
2754                                type_arguments,
2755                            } => {
2756                                message.move_entry_point = Some({
2757                                    let mut message = MoveCall::default();
2758                                    message.package = Some(package.to_canonical_string(true));
2759                                    message.module = Some(module);
2760                                    message.function = Some(function);
2761                                    message.type_arguments = type_arguments
2762                                        .into_iter()
2763                                        .map(|ty| ty.to_canonical_string(true))
2764                                        .collect();
2765                                    message
2766                                });
2767                                ExecutionTimeObservationKind::MoveEntryPoint
2768                            }
2769                            K::TransferObjects => ExecutionTimeObservationKind::TransferObjects,
2770                            K::SplitCoins => ExecutionTimeObservationKind::SplitCoins,
2771                            K::MergeCoins => ExecutionTimeObservationKind::MergeCoins,
2772                            K::Publish => ExecutionTimeObservationKind::Publish,
2773                            K::MakeMoveVec => ExecutionTimeObservationKind::MakeMoveVector,
2774                            K::Upgrade => ExecutionTimeObservationKind::Upgrade,
2775                        };
2776
2777                        message.validator_observations = observation
2778                            .into_iter()
2779                            .map(|(name, duration)| {
2780                                let mut message = ValidatorExecutionTimeObservation::default();
2781                                message.validator = Some(name.0.to_vec().into());
2782                                message.duration = Some(prost_types::Duration {
2783                                    seconds: duration.as_secs() as i64,
2784                                    nanos: duration.subsec_nanos() as i32,
2785                                });
2786                                message
2787                            })
2788                            .collect();
2789
2790                        message.set_kind(kind);
2791                        message
2792                    })
2793                    .collect();
2794            }
2795        }
2796
2797        message
2798    }
2799}
2800
2801//
2802// ProgrammableTransaction
2803//
2804
2805impl From<crate::transaction::ProgrammableTransaction> for ProgrammableTransaction {
2806    fn from(value: crate::transaction::ProgrammableTransaction) -> Self {
2807        let mut message = Self::default();
2808        message.inputs = value.inputs.into_iter().map(Into::into).collect();
2809        message.commands = value.commands.into_iter().map(Into::into).collect();
2810        message
2811    }
2812}
2813
2814//
2815// Input
2816//
2817
2818impl From<crate::transaction::CallArg> for Input {
2819    fn from(value: crate::transaction::CallArg) -> Self {
2820        use crate::transaction::CallArg as I;
2821        use crate::transaction::ObjectArg as O;
2822        use input::InputKind;
2823        use input::Mutability;
2824
2825        let mut message = Self::default();
2826
2827        let kind = match value {
2828            I::Pure(value) => {
2829                message.pure = Some(value.into());
2830                InputKind::Pure
2831            }
2832            I::Object(o) => match o {
2833                O::ImmOrOwnedObject((id, version, digest)) => {
2834                    message.object_id = Some(id.to_canonical_string(true));
2835                    message.version = Some(version.value());
2836                    message.digest = Some(digest.to_string());
2837                    InputKind::ImmutableOrOwned
2838                }
2839                O::SharedObject {
2840                    id,
2841                    initial_shared_version,
2842                    mutability,
2843                } => {
2844                    message.object_id = Some(id.to_canonical_string(true));
2845                    message.version = Some(initial_shared_version.value());
2846                    message.mutable = Some(mutability.is_exclusive());
2847                    message.set_mutability(match mutability {
2848                        crate::transaction::SharedObjectMutability::Immutable => {
2849                            Mutability::Immutable
2850                        }
2851                        crate::transaction::SharedObjectMutability::Mutable => Mutability::Mutable,
2852                        crate::transaction::SharedObjectMutability::NonExclusiveWrite => {
2853                            Mutability::NonExclusiveWrite
2854                        }
2855                    });
2856                    InputKind::Shared
2857                }
2858                O::Receiving((id, version, digest)) => {
2859                    message.object_id = Some(id.to_canonical_string(true));
2860                    message.version = Some(version.value());
2861                    message.digest = Some(digest.to_string());
2862                    InputKind::Receiving
2863                }
2864            },
2865            I::FundsWithdrawal(withdrawal) => {
2866                message.set_funds_withdrawal(withdrawal);
2867                InputKind::FundsWithdrawal
2868            }
2869        };
2870
2871        message.set_kind(kind);
2872        message
2873    }
2874}
2875
2876impl From<crate::transaction::FundsWithdrawalArg> for FundsWithdrawal {
2877    fn from(value: crate::transaction::FundsWithdrawalArg) -> Self {
2878        use funds_withdrawal::Source;
2879
2880        let mut message = Self::default();
2881
2882        message.amount = match value.reservation {
2883            crate::transaction::Reservation::MaxAmountU64(amount) => Some(amount),
2884        };
2885        let crate::transaction::WithdrawalTypeArg::Balance(coin_type) = value.type_arg;
2886        message.coin_type = Some(coin_type.to_canonical_string(true));
2887        message.set_source(match value.withdraw_from {
2888            crate::transaction::WithdrawFrom::Sender => Source::Sender,
2889            crate::transaction::WithdrawFrom::Sponsor => Source::Sponsor,
2890        });
2891
2892        message
2893    }
2894}
2895
2896//
2897// Argument
2898//
2899
2900impl From<crate::transaction::Argument> for Argument {
2901    fn from(value: crate::transaction::Argument) -> Self {
2902        use crate::transaction::Argument as A;
2903        use argument::ArgumentKind;
2904
2905        let mut message = Self::default();
2906
2907        let kind = match value {
2908            A::GasCoin => ArgumentKind::Gas,
2909            A::Input(input) => {
2910                message.input = Some(input.into());
2911                ArgumentKind::Input
2912            }
2913            A::Result(result) => {
2914                message.result = Some(result.into());
2915                ArgumentKind::Result
2916            }
2917            A::NestedResult(result, subresult) => {
2918                message.result = Some(result.into());
2919                message.subresult = Some(subresult.into());
2920                ArgumentKind::Result
2921            }
2922        };
2923
2924        message.set_kind(kind);
2925        message
2926    }
2927}
2928
2929//
2930// Command
2931//
2932
2933impl From<crate::transaction::Command> for Command {
2934    fn from(value: crate::transaction::Command) -> Self {
2935        use crate::transaction::Command as C;
2936        use command::Command;
2937
2938        let command = match value {
2939            C::MoveCall(move_call) => Command::MoveCall((*move_call).into()),
2940            C::TransferObjects(objects, address) => Command::TransferObjects({
2941                let mut message = TransferObjects::default();
2942                message.objects = objects.into_iter().map(Into::into).collect();
2943                message.address = Some(address.into());
2944                message
2945            }),
2946            C::SplitCoins(coin, amounts) => Command::SplitCoins({
2947                let mut message = SplitCoins::default();
2948                message.coin = Some(coin.into());
2949                message.amounts = amounts.into_iter().map(Into::into).collect();
2950                message
2951            }),
2952            C::MergeCoins(coin, coins_to_merge) => Command::MergeCoins({
2953                let mut message = MergeCoins::default();
2954                message.coin = Some(coin.into());
2955                message.coins_to_merge = coins_to_merge.into_iter().map(Into::into).collect();
2956                message
2957            }),
2958            C::Publish(modules, dependencies) => Command::Publish({
2959                let mut message = Publish::default();
2960                message.modules = modules.into_iter().map(Into::into).collect();
2961                message.dependencies = dependencies
2962                    .iter()
2963                    .map(|d| d.to_canonical_string(true))
2964                    .collect();
2965                message
2966            }),
2967            C::MakeMoveVec(element_type, elements) => Command::MakeMoveVector({
2968                let mut message = MakeMoveVector::default();
2969                message.element_type = element_type.map(|t| t.to_canonical_string(true));
2970                message.elements = elements.into_iter().map(Into::into).collect();
2971                message
2972            }),
2973            C::Upgrade(modules, dependencies, package, ticket) => Command::Upgrade({
2974                let mut message = Upgrade::default();
2975                message.modules = modules.into_iter().map(Into::into).collect();
2976                message.dependencies = dependencies
2977                    .iter()
2978                    .map(|d| d.to_canonical_string(true))
2979                    .collect();
2980                message.package = Some(package.to_canonical_string(true));
2981                message.ticket = Some(ticket.into());
2982                message
2983            }),
2984        };
2985
2986        let mut message = Self::default();
2987        message.command = Some(command);
2988        message
2989    }
2990}
2991
2992//
2993// MoveCall
2994//
2995
2996impl From<crate::transaction::ProgrammableMoveCall> for MoveCall {
2997    fn from(value: crate::transaction::ProgrammableMoveCall) -> Self {
2998        let mut message = Self::default();
2999        message.package = Some(value.package.to_canonical_string(true));
3000        message.module = Some(value.module.to_string());
3001        message.function = Some(value.function.to_string());
3002        message.type_arguments = value
3003            .type_arguments
3004            .iter()
3005            .map(|t| t.to_canonical_string(true))
3006            .collect();
3007        message.arguments = value.arguments.into_iter().map(Into::into).collect();
3008        message
3009    }
3010}
3011
3012//
3013// TransactionEffects
3014//
3015
3016impl From<crate::effects::TransactionEffects> for TransactionEffects {
3017    fn from(value: crate::effects::TransactionEffects) -> Self {
3018        Self::merge_from(&value, &FieldMaskTree::new_wildcard())
3019    }
3020}
3021
3022impl Merge<&crate::effects::TransactionEffects> for TransactionEffects {
3023    fn merge(&mut self, source: &crate::effects::TransactionEffects, mask: &FieldMaskTree) {
3024        if mask.contains(Self::BCS_FIELD.name) {
3025            let mut bcs = Bcs::serialize(&source).unwrap();
3026            bcs.name = Some("TransactionEffects".to_owned());
3027            self.bcs = Some(bcs);
3028        }
3029
3030        if mask.contains(Self::DIGEST_FIELD.name) {
3031            self.digest = Some(source.digest().to_string());
3032        }
3033
3034        match source {
3035            crate::effects::TransactionEffects::V1(v1) => self.merge(v1, mask),
3036            crate::effects::TransactionEffects::V2(v2) => self.merge(v2, mask),
3037        }
3038    }
3039}
3040
3041//
3042// TransactionEffectsV1
3043//
3044
3045impl Merge<&crate::effects::TransactionEffectsV1> for TransactionEffects {
3046    fn merge(&mut self, value: &crate::effects::TransactionEffectsV1, mask: &FieldMaskTree) {
3047        use crate::effects::TransactionEffectsAPI;
3048
3049        if mask.contains(Self::VERSION_FIELD.name) {
3050            self.version = Some(1);
3051        }
3052
3053        if mask.contains(Self::STATUS_FIELD.name) {
3054            self.status = Some(value.status().clone().into());
3055        }
3056
3057        if mask.contains(Self::EPOCH_FIELD.name) {
3058            self.epoch = Some(value.executed_epoch());
3059        }
3060
3061        if mask.contains(Self::GAS_USED_FIELD.name) {
3062            self.gas_used = Some(value.gas_cost_summary().clone().into());
3063        }
3064
3065        if mask.contains(Self::TRANSACTION_DIGEST_FIELD.name) {
3066            self.transaction_digest = Some(value.transaction_digest().to_string());
3067        }
3068
3069        if mask.contains(Self::EVENTS_DIGEST_FIELD.name) {
3070            self.events_digest = value.events_digest().map(|d| d.to_string());
3071        }
3072
3073        if mask.contains(Self::DEPENDENCIES_FIELD.name) {
3074            self.dependencies = value
3075                .dependencies()
3076                .iter()
3077                .map(ToString::to_string)
3078                .collect();
3079        }
3080
3081        if mask.contains(Self::CHANGED_OBJECTS_FIELD.name)
3082            || mask.contains(Self::UNCHANGED_CONSENSUS_OBJECTS_FIELD.name)
3083            || mask.contains(Self::GAS_OBJECT_FIELD.name)
3084        {
3085            let mut changed_objects = Vec::new();
3086            let mut unchanged_consensus_objects = Vec::new();
3087
3088            for ((id, version, digest), owner) in value.created() {
3089                let mut change = ChangedObject::default();
3090                change.object_id = Some(id.to_canonical_string(true));
3091                change.input_state = Some(changed_object::InputObjectState::DoesNotExist.into());
3092                change.output_state = Some(changed_object::OutputObjectState::ObjectWrite.into());
3093                change.output_version = Some(version.value());
3094                change.output_digest = Some(digest.to_string());
3095                change.output_owner = Some(owner.clone().into());
3096                change.id_operation = Some(changed_object::IdOperation::Created.into());
3097
3098                changed_objects.push(change);
3099            }
3100
3101            for ((id, version, digest), owner) in value.mutated() {
3102                let mut change = ChangedObject::default();
3103                change.object_id = Some(id.to_canonical_string(true));
3104                change.input_state = Some(changed_object::InputObjectState::Exists.into());
3105                change.output_state = Some(changed_object::OutputObjectState::ObjectWrite.into());
3106                change.output_version = Some(version.value());
3107                change.output_digest = Some(digest.to_string());
3108                change.output_owner = Some(owner.clone().into());
3109                change.id_operation = Some(changed_object::IdOperation::None.into());
3110
3111                changed_objects.push(change);
3112            }
3113
3114            for ((id, version, digest), owner) in value.unwrapped() {
3115                let mut change = ChangedObject::default();
3116                change.object_id = Some(id.to_canonical_string(true));
3117                change.input_state = Some(changed_object::InputObjectState::DoesNotExist.into());
3118                change.output_state = Some(changed_object::OutputObjectState::ObjectWrite.into());
3119                change.output_version = Some(version.value());
3120                change.output_digest = Some(digest.to_string());
3121                change.output_owner = Some(owner.clone().into());
3122                change.id_operation = Some(changed_object::IdOperation::None.into());
3123
3124                changed_objects.push(change);
3125            }
3126
3127            for (id, version, digest) in value.deleted() {
3128                let mut change = ChangedObject::default();
3129                change.object_id = Some(id.to_canonical_string(true));
3130                change.input_state = Some(changed_object::InputObjectState::Exists.into());
3131                change.output_state = Some(changed_object::OutputObjectState::DoesNotExist.into());
3132                change.output_version = Some(version.value());
3133                change.output_digest = Some(digest.to_string());
3134                change.id_operation = Some(changed_object::IdOperation::Deleted.into());
3135
3136                changed_objects.push(change);
3137            }
3138
3139            for (id, version, digest) in value.unwrapped_then_deleted() {
3140                let mut change = ChangedObject::default();
3141                change.object_id = Some(id.to_canonical_string(true));
3142                change.input_state = Some(changed_object::InputObjectState::DoesNotExist.into());
3143                change.output_state = Some(changed_object::OutputObjectState::DoesNotExist.into());
3144                change.output_version = Some(version.value());
3145                change.output_digest = Some(digest.to_string());
3146                change.id_operation = Some(changed_object::IdOperation::Deleted.into());
3147
3148                changed_objects.push(change);
3149            }
3150
3151            for (id, version, digest) in value.wrapped() {
3152                let mut change = ChangedObject::default();
3153                change.object_id = Some(id.to_canonical_string(true));
3154                change.input_state = Some(changed_object::InputObjectState::Exists.into());
3155                change.output_state = Some(changed_object::OutputObjectState::DoesNotExist.into());
3156                change.output_version = Some(version.value());
3157                change.output_digest = Some(digest.to_string());
3158                change.id_operation = Some(changed_object::IdOperation::Deleted.into());
3159
3160                changed_objects.push(change);
3161            }
3162
3163            for (object_id, version) in value.modified_at_versions() {
3164                let object_id = object_id.to_canonical_string(true);
3165                let version = version.value();
3166                if let Some(changed_object) = changed_objects
3167                    .iter_mut()
3168                    .find(|object| object.object_id() == object_id)
3169                {
3170                    changed_object.input_version = Some(version);
3171                }
3172            }
3173
3174            for (id, version, digest) in value.shared_objects() {
3175                let object_id = id.to_canonical_string(true);
3176                let version = version.value();
3177                let digest = digest.to_string();
3178
3179                if let Some(changed_object) = changed_objects
3180                    .iter_mut()
3181                    .find(|object| object.object_id() == object_id)
3182                {
3183                    changed_object.input_version = Some(version);
3184                    changed_object.input_digest = Some(digest);
3185                } else {
3186                    let mut unchanged_consensus_object = UnchangedConsensusObject::default();
3187                    unchanged_consensus_object.kind = Some(
3188                        unchanged_consensus_object::UnchangedConsensusObjectKind::ReadOnlyRoot
3189                            .into(),
3190                    );
3191                    unchanged_consensus_object.object_id = Some(object_id);
3192                    unchanged_consensus_object.version = Some(version);
3193                    unchanged_consensus_object.digest = Some(digest);
3194
3195                    unchanged_consensus_objects.push(unchanged_consensus_object);
3196                }
3197            }
3198
3199            if mask.contains(Self::GAS_OBJECT_FIELD.name)
3200                && let Some(((gas_id, _, _), _)) = value.gas_object()
3201            {
3202                let gas_object_id = gas_id.to_canonical_string(true);
3203                self.gas_object = changed_objects
3204                    .iter()
3205                    .find(|object| object.object_id() == gas_object_id)
3206                    .cloned();
3207            }
3208
3209            if mask.contains(Self::CHANGED_OBJECTS_FIELD.name) {
3210                self.changed_objects = changed_objects;
3211            }
3212
3213            if mask.contains(Self::UNCHANGED_CONSENSUS_OBJECTS_FIELD.name) {
3214                self.unchanged_consensus_objects = unchanged_consensus_objects;
3215            }
3216        }
3217    }
3218}
3219
3220//
3221// TransactionEffectsV2
3222//
3223
3224impl Merge<&crate::effects::TransactionEffectsV2> for TransactionEffects {
3225    fn merge(
3226        &mut self,
3227        crate::effects::TransactionEffectsV2 {
3228            status,
3229            executed_epoch,
3230            gas_used,
3231            transaction_digest,
3232            gas_object_index,
3233            events_digest,
3234            dependencies,
3235            lamport_version,
3236            changed_objects,
3237            unchanged_consensus_objects,
3238            aux_data_digest,
3239        }: &crate::effects::TransactionEffectsV2,
3240        mask: &FieldMaskTree,
3241    ) {
3242        if mask.contains(Self::VERSION_FIELD.name) {
3243            self.version = Some(2);
3244        }
3245
3246        if mask.contains(Self::STATUS_FIELD.name) {
3247            self.status = Some(status.clone().into());
3248        }
3249
3250        if mask.contains(Self::EPOCH_FIELD.name) {
3251            self.epoch = Some(*executed_epoch);
3252        }
3253
3254        if mask.contains(Self::GAS_USED_FIELD.name) {
3255            self.gas_used = Some(gas_used.clone().into());
3256        }
3257
3258        if mask.contains(Self::TRANSACTION_DIGEST_FIELD.name) {
3259            self.transaction_digest = Some(transaction_digest.to_string());
3260        }
3261
3262        if mask.contains(Self::GAS_OBJECT_FIELD.name) {
3263            self.gas_object = gas_object_index
3264                .map(|index| {
3265                    changed_objects
3266                        .get(index as usize)
3267                        .cloned()
3268                        .map(|(id, change)| {
3269                            let mut message = ChangedObject::from(change);
3270                            message.object_id = Some(id.to_canonical_string(true));
3271                            message
3272                        })
3273                })
3274                .flatten();
3275        }
3276
3277        if mask.contains(Self::EVENTS_DIGEST_FIELD.name) {
3278            self.events_digest = events_digest.map(|d| d.to_string());
3279        }
3280
3281        if mask.contains(Self::DEPENDENCIES_FIELD.name) {
3282            self.dependencies = dependencies.iter().map(ToString::to_string).collect();
3283        }
3284
3285        if mask.contains(Self::LAMPORT_VERSION_FIELD.name) {
3286            self.lamport_version = Some(lamport_version.value());
3287        }
3288
3289        if mask.contains(Self::CHANGED_OBJECTS_FIELD.name) {
3290            self.changed_objects = changed_objects
3291                .clone()
3292                .into_iter()
3293                .map(|(id, change)| {
3294                    let mut message = ChangedObject::from(change);
3295                    message.object_id = Some(id.to_canonical_string(true));
3296                    message
3297                })
3298                .collect();
3299        }
3300
3301        for object in self.changed_objects.iter_mut().chain(&mut self.gas_object) {
3302            if object.output_digest.is_some() && object.output_version.is_none() {
3303                object.output_version = Some(lamport_version.value());
3304            }
3305        }
3306
3307        if mask.contains(Self::UNCHANGED_CONSENSUS_OBJECTS_FIELD.name) {
3308            self.unchanged_consensus_objects = unchanged_consensus_objects
3309                .clone()
3310                .into_iter()
3311                .map(|(id, unchanged)| {
3312                    let mut message = UnchangedConsensusObject::from(unchanged);
3313                    message.object_id = Some(id.to_canonical_string(true));
3314                    message
3315                })
3316                .collect();
3317        }
3318
3319        if mask.contains(Self::AUXILIARY_DATA_DIGEST_FIELD.name) {
3320            self.auxiliary_data_digest = aux_data_digest.map(|d| d.to_string());
3321        }
3322    }
3323}
3324
3325//
3326// ChangedObject
3327//
3328
3329impl From<crate::effects::EffectsObjectChange> for ChangedObject {
3330    fn from(value: crate::effects::EffectsObjectChange) -> Self {
3331        use crate::effects::ObjectIn;
3332        use crate::effects::ObjectOut;
3333        use changed_object::InputObjectState;
3334        use changed_object::OutputObjectState;
3335
3336        let mut message = Self::default();
3337
3338        // Input State
3339        let input_state = match value.input_state {
3340            ObjectIn::NotExist => InputObjectState::DoesNotExist,
3341            ObjectIn::Exist(((version, digest), owner)) => {
3342                message.input_version = Some(version.value());
3343                message.input_digest = Some(digest.to_string());
3344                message.input_owner = Some(owner.into());
3345                InputObjectState::Exists
3346            }
3347        };
3348        message.set_input_state(input_state);
3349
3350        // Output State
3351        let output_state = match value.output_state {
3352            ObjectOut::NotExist => OutputObjectState::DoesNotExist,
3353            ObjectOut::ObjectWrite((digest, owner)) => {
3354                message.output_digest = Some(digest.to_string());
3355                message.output_owner = Some(owner.into());
3356                OutputObjectState::ObjectWrite
3357            }
3358            ObjectOut::PackageWrite((version, digest)) => {
3359                message.output_version = Some(version.value());
3360                message.output_digest = Some(digest.to_string());
3361                OutputObjectState::PackageWrite
3362            }
3363            ObjectOut::AccumulatorWriteV1(accumulator_write) => {
3364                message.set_accumulator_write(accumulator_write);
3365                OutputObjectState::AccumulatorWrite
3366            }
3367        };
3368        message.set_output_state(output_state);
3369
3370        message.set_id_operation(value.id_operation.into());
3371        message
3372    }
3373}
3374
3375impl From<crate::effects::AccumulatorWriteV1> for AccumulatorWrite {
3376    fn from(value: crate::effects::AccumulatorWriteV1) -> Self {
3377        use accumulator_write::AccumulatorOperation;
3378
3379        let mut message = Self::default();
3380
3381        message.set_address(value.address.address.to_string());
3382        message.set_accumulator_type(value.address.ty.to_canonical_string(true));
3383        message.set_operation(match value.operation {
3384            crate::effects::AccumulatorOperation::Merge => AccumulatorOperation::Merge,
3385            crate::effects::AccumulatorOperation::Split => AccumulatorOperation::Split,
3386        });
3387        match value.value {
3388            crate::effects::AccumulatorValue::Integer(value) => message.set_integer_value(value),
3389            //TODO unsupported value types
3390            crate::effects::AccumulatorValue::IntegerTuple(_, _)
3391            | crate::effects::AccumulatorValue::EventDigest(_) => {}
3392        }
3393
3394        message
3395    }
3396}
3397
3398//
3399// IdOperation
3400//
3401
3402impl From<crate::effects::IDOperation> for changed_object::IdOperation {
3403    fn from(value: crate::effects::IDOperation) -> Self {
3404        use crate::effects::IDOperation as I;
3405
3406        match value {
3407            I::None => Self::None,
3408            I::Created => Self::Created,
3409            I::Deleted => Self::Deleted,
3410        }
3411    }
3412}
3413
3414//
3415// UnchangedConsensusObject
3416//
3417
3418impl From<crate::effects::UnchangedConsensusKind> for UnchangedConsensusObject {
3419    fn from(value: crate::effects::UnchangedConsensusKind) -> Self {
3420        use crate::effects::UnchangedConsensusKind as K;
3421        use unchanged_consensus_object::UnchangedConsensusObjectKind;
3422
3423        let mut message = Self::default();
3424
3425        let kind = match value {
3426            K::ReadOnlyRoot((version, digest)) => {
3427                message.version = Some(version.value());
3428                message.digest = Some(digest.to_string());
3429                UnchangedConsensusObjectKind::ReadOnlyRoot
3430            }
3431            K::MutateConsensusStreamEnded(version) => {
3432                message.version = Some(version.value());
3433                UnchangedConsensusObjectKind::MutateConsensusStreamEnded
3434            }
3435            K::ReadConsensusStreamEnded(version) => {
3436                message.version = Some(version.value());
3437                UnchangedConsensusObjectKind::ReadConsensusStreamEnded
3438            }
3439            K::Cancelled(version) => {
3440                message.version = Some(version.value());
3441                UnchangedConsensusObjectKind::Canceled
3442            }
3443            K::PerEpochConfig => UnchangedConsensusObjectKind::PerEpochConfig,
3444            // PerEpochConfigWithSequenceNumber { version } => {
3445            //     message.version = Some(version);
3446            //     UnchangedSharedObjectKind::PerEpochConfig
3447            // }
3448        };
3449
3450        message.set_kind(kind);
3451        message
3452    }
3453}
3454
3455//
3456// TransactionChecks
3457//
3458
3459impl From<simulate_transaction_request::TransactionChecks>
3460    for crate::transaction_executor::TransactionChecks
3461{
3462    fn from(value: simulate_transaction_request::TransactionChecks) -> Self {
3463        match value {
3464            simulate_transaction_request::TransactionChecks::Enabled => Self::Enabled,
3465            simulate_transaction_request::TransactionChecks::Disabled => Self::Disabled,
3466            // Default to enabled
3467            _ => Self::Enabled,
3468        }
3469    }
3470}
3471
3472//
3473// Coin-related conversions
3474//
3475
3476impl From<crate::coin_registry::MetadataCapState> for coin_metadata::MetadataCapState {
3477    fn from(value: crate::coin_registry::MetadataCapState) -> Self {
3478        match value {
3479            crate::coin_registry::MetadataCapState::Claimed(_) => {
3480                coin_metadata::MetadataCapState::Claimed
3481            }
3482            crate::coin_registry::MetadataCapState::Unclaimed => {
3483                coin_metadata::MetadataCapState::Unclaimed
3484            }
3485            crate::coin_registry::MetadataCapState::Deleted => {
3486                coin_metadata::MetadataCapState::Deleted
3487            }
3488        }
3489    }
3490}
3491
3492impl From<&crate::coin_registry::Currency> for CoinMetadata {
3493    fn from(value: &crate::coin_registry::Currency) -> Self {
3494        let mut metadata = CoinMetadata::default();
3495        metadata.id = Some(sui_sdk_types::Address::from(value.id.into_bytes()).to_string());
3496        metadata.decimals = Some(value.decimals.into());
3497        metadata.name = Some(value.name.clone());
3498        metadata.symbol = Some(value.symbol.clone());
3499        metadata.description = Some(value.description.clone());
3500        metadata.icon_url = Some(value.icon_url.clone());
3501
3502        match &value.metadata_cap_id {
3503            crate::coin_registry::MetadataCapState::Claimed(id) => {
3504                metadata.metadata_cap_state = Some(coin_metadata::MetadataCapState::Claimed as i32);
3505                metadata.metadata_cap_id = Some(sui_sdk_types::Address::from(*id).to_string());
3506            }
3507            crate::coin_registry::MetadataCapState::Unclaimed => {
3508                metadata.metadata_cap_state =
3509                    Some(coin_metadata::MetadataCapState::Unclaimed as i32);
3510            }
3511            crate::coin_registry::MetadataCapState::Deleted => {
3512                metadata.metadata_cap_state = Some(coin_metadata::MetadataCapState::Deleted as i32);
3513            }
3514        }
3515
3516        metadata
3517    }
3518}
3519
3520impl From<crate::coin::CoinMetadata> for CoinMetadata {
3521    fn from(value: crate::coin::CoinMetadata) -> Self {
3522        let mut metadata = CoinMetadata::default();
3523        metadata.id = Some(sui_sdk_types::Address::from(value.id.id.bytes).to_string());
3524        metadata.decimals = Some(value.decimals.into());
3525        metadata.name = Some(value.name);
3526        metadata.symbol = Some(value.symbol);
3527        metadata.description = Some(value.description);
3528        metadata.icon_url = value.icon_url;
3529        metadata
3530    }
3531}
3532
3533impl From<crate::coin_registry::SupplyState> for coin_treasury::SupplyState {
3534    fn from(value: crate::coin_registry::SupplyState) -> Self {
3535        match value {
3536            crate::coin_registry::SupplyState::Fixed(_) => coin_treasury::SupplyState::Fixed,
3537            crate::coin_registry::SupplyState::BurnOnly(_) => coin_treasury::SupplyState::BurnOnly,
3538            crate::coin_registry::SupplyState::Unknown => coin_treasury::SupplyState::Unknown,
3539        }
3540    }
3541}
3542
3543impl From<crate::coin::TreasuryCap> for CoinTreasury {
3544    fn from(value: crate::coin::TreasuryCap) -> Self {
3545        let mut treasury = CoinTreasury::default();
3546        treasury.id = Some(sui_sdk_types::Address::from(value.id.id.bytes).to_string());
3547        treasury.total_supply = Some(value.total_supply.value);
3548        treasury
3549    }
3550}
3551
3552impl From<&crate::coin_registry::RegulatedState> for RegulatedCoinMetadata {
3553    fn from(value: &crate::coin_registry::RegulatedState) -> Self {
3554        let mut regulated = RegulatedCoinMetadata::default();
3555
3556        match value {
3557            crate::coin_registry::RegulatedState::Regulated {
3558                cap,
3559                allow_global_pause,
3560                variant,
3561            } => {
3562                regulated.deny_cap_object = Some(sui_sdk_types::Address::from(*cap).to_string());
3563                regulated.allow_global_pause = *allow_global_pause;
3564                regulated.variant = Some(*variant as u32);
3565                regulated.coin_regulated_state =
3566                    Some(regulated_coin_metadata::CoinRegulatedState::Regulated as i32);
3567            }
3568            crate::coin_registry::RegulatedState::Unregulated => {
3569                regulated.coin_regulated_state =
3570                    Some(regulated_coin_metadata::CoinRegulatedState::Unregulated as i32);
3571            }
3572            crate::coin_registry::RegulatedState::Unknown => {
3573                regulated.coin_regulated_state =
3574                    Some(regulated_coin_metadata::CoinRegulatedState::Unknown as i32);
3575            }
3576        }
3577
3578        regulated
3579    }
3580}
3581
3582impl From<crate::coin_registry::RegulatedState> for RegulatedCoinMetadata {
3583    fn from(value: crate::coin_registry::RegulatedState) -> Self {
3584        (&value).into()
3585    }
3586}
3587
3588impl From<crate::coin::RegulatedCoinMetadata> for RegulatedCoinMetadata {
3589    fn from(value: crate::coin::RegulatedCoinMetadata) -> Self {
3590        let mut message = RegulatedCoinMetadata::default();
3591        message.id = Some(sui_sdk_types::Address::from(value.id.id.bytes).to_string());
3592        message.coin_metadata_object =
3593            Some(sui_sdk_types::Address::from(value.coin_metadata_object.bytes).to_string());
3594        message.deny_cap_object =
3595            Some(sui_sdk_types::Address::from(value.deny_cap_object.bytes).to_string());
3596        message.coin_regulated_state =
3597            Some(regulated_coin_metadata::CoinRegulatedState::Regulated as i32);
3598        message
3599    }
3600}
3601
3602impl TryFrom<&ObjectSet> for crate::full_checkpoint_content::ObjectSet {
3603    type Error = TryFromProtoError;
3604
3605    fn try_from(value: &ObjectSet) -> Result<Self, Self::Error> {
3606        let mut objects = Self::default();
3607
3608        for o in value.objects() {
3609            objects.insert(
3610                o.bcs()
3611                    .deserialize()
3612                    .map_err(|e| TryFromProtoError::invalid("object.bcs", e))?,
3613            );
3614        }
3615
3616        Ok(objects)
3617    }
3618}