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