iota_types/
iota_sdk_types_conversions.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5//! Module for conversions between iota-core types and iota-sdk types
6//!
7//! For now this module makes heavy use of the `bcs_convert_impl` macro to
8//! implement the `From` trait for converting between core and external sdk
9//! types, relying on the fact that the BCS format of these types are strictly
10//! identical. As time goes on we'll slowly hand implement these impls
11//! directly to avoid going through the BCS machinery.
12
13use fastcrypto::traits::ToFromBytes;
14use iota_sdk_types::{
15    address::Address,
16    checkpoint::{
17        CheckpointCommitment, CheckpointContents, CheckpointData, CheckpointSummary,
18        CheckpointTransaction, CheckpointTransactionInfo, EndOfEpochData, SignedCheckpointSummary,
19    },
20    crypto::{Bls12381PublicKey, Bls12381Signature, UserSignature},
21    digest::Digest,
22    effects::{
23        ChangedObject, IdOperation, ObjectIn, ObjectOut, TransactionEffects, TransactionEffectsV1,
24        UnchangedSharedObject,
25    },
26    events::TransactionEvents,
27    gas::GasCostSummary,
28    move_core::{Identifier, StructTag, TypeParseError, TypeTag},
29    object::Object,
30    transaction::SignedTransaction,
31    validator::{ValidatorAggregatedSignature, ValidatorCommittee, ValidatorCommitteeMember},
32};
33use tap::Pipe;
34
35use crate::object::ObjectInner;
36
37#[derive(Debug)]
38pub struct SdkTypeConversionError(pub String);
39
40impl std::fmt::Display for SdkTypeConversionError {
41    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42        f.write_str(&self.0)
43    }
44}
45
46impl std::error::Error for SdkTypeConversionError {}
47
48impl From<TypeParseError> for SdkTypeConversionError {
49    fn from(value: TypeParseError) -> Self {
50        Self(value.to_string())
51    }
52}
53
54impl From<anyhow::Error> for SdkTypeConversionError {
55    fn from(value: anyhow::Error) -> Self {
56        Self(value.to_string())
57    }
58}
59
60impl From<bcs::Error> for SdkTypeConversionError {
61    fn from(value: bcs::Error) -> Self {
62        Self(value.to_string())
63    }
64}
65
66impl TryFrom<crate::object::Object> for Object {
67    type Error = SdkTypeConversionError;
68
69    fn try_from(value: crate::object::Object) -> Result<Self, Self::Error> {
70        Self {
71            data: value.data.clone(),
72            owner: value.owner,
73            previous_transaction: value.previous_transaction,
74            storage_rebate: value.storage_rebate,
75        }
76        .pipe(Ok)
77    }
78}
79
80impl TryFrom<Object> for crate::object::Object {
81    type Error = SdkTypeConversionError;
82
83    fn try_from(value: Object) -> Result<Self, Self::Error> {
84        Self::from(ObjectInner {
85            data: value.data,
86            owner: value.owner,
87            previous_transaction: value.previous_transaction,
88            storage_rebate: value.storage_rebate,
89        })
90        .pipe(Ok)
91    }
92}
93
94impl TryFrom<crate::effects::TransactionEffects> for TransactionEffects {
95    type Error = SdkTypeConversionError;
96
97    fn try_from(value: crate::effects::TransactionEffects) -> Result<Self, Self::Error> {
98        match value {
99            crate::effects::TransactionEffects::V1(effects) => {
100                Self::V1(Box::new(TransactionEffectsV1 {
101                    epoch: effects.executed_epoch,
102                    gas_used: GasCostSummary::new(
103                        effects.gas_used.computation_cost,
104                        effects.gas_used.computation_cost_burned,
105                        effects.gas_used.storage_cost,
106                        effects.gas_used.storage_rebate,
107                        effects.gas_used.non_refundable_storage_fee,
108                    ),
109                    gas_object_index: effects.gas_object_index,
110                    transaction_digest: effects.transaction_digest,
111                    events_digest: effects.events_digest,
112                    dependencies: effects.dependencies,
113                    lamport_version: effects.lamport_version,
114                    changed_objects: effects
115                        .changed_objects
116                        .into_iter()
117                        .map(|(id, change)| ChangedObject {
118                            object_id: id,
119                            input_state: match change.input_state {
120                                crate::effects::ObjectIn::NotExist => ObjectIn::Missing,
121                                crate::effects::ObjectIn::Exist(((version, digest), owner)) => {
122                                    ObjectIn::Data {
123                                        version,
124                                        digest,
125                                        owner,
126                                    }
127                                }
128                            },
129                            output_state: match change.output_state {
130                                crate::effects::ObjectOut::NotExist => ObjectOut::Missing,
131                                crate::effects::ObjectOut::ObjectWrite((digest, owner)) => {
132                                    ObjectOut::ObjectWrite { digest, owner }
133                                }
134                                crate::effects::ObjectOut::PackageWrite((seq, digest)) => {
135                                    ObjectOut::PackageWrite {
136                                        version: seq,
137                                        digest,
138                                    }
139                                }
140                            },
141                            id_operation: match change.id_operation {
142                                crate::effects::IDOperation::None => IdOperation::None,
143                                crate::effects::IDOperation::Created => IdOperation::Created,
144                                crate::effects::IDOperation::Deleted => IdOperation::Deleted,
145                            },
146                        })
147                        .collect(),
148                    unchanged_shared_objects: effects
149                        .unchanged_shared_objects
150                        .into_iter()
151                        .map(|(id, kind)| UnchangedSharedObject {
152                            object_id: id,
153                            kind,
154                        })
155                        .collect(),
156                    auxiliary_data_digest: effects.aux_data_digest,
157                    status: effects.status,
158                }))
159                .pipe(Ok)
160            }
161        }
162    }
163}
164
165impl TryFrom<TransactionEffects> for crate::effects::TransactionEffects {
166    type Error = SdkTypeConversionError;
167
168    fn try_from(value: TransactionEffects) -> Result<Self, Self::Error> {
169        match value {
170            TransactionEffects::V1(transaction_effects_v1) => {
171                let effects: crate::effects::TransactionEffects =
172                    crate::effects::effects_v1::TransactionEffectsV1 {
173                        status: transaction_effects_v1.status,
174                        executed_epoch: transaction_effects_v1.epoch,
175                        gas_used: crate::gas::GasCostSummary::new(
176                            transaction_effects_v1.gas_used.computation_cost,
177                            transaction_effects_v1.gas_used.computation_cost_burned,
178                            transaction_effects_v1.gas_used.storage_cost,
179                            transaction_effects_v1.gas_used.storage_rebate,
180                            transaction_effects_v1.gas_used.non_refundable_storage_fee,
181                        ),
182                        transaction_digest: transaction_effects_v1.transaction_digest,
183                        gas_object_index: transaction_effects_v1.gas_object_index,
184                        events_digest: transaction_effects_v1.events_digest,
185                        dependencies: transaction_effects_v1
186                            .dependencies
187                            .into_iter().collect(),
188                        lamport_version: transaction_effects_v1.lamport_version,
189                        changed_objects: transaction_effects_v1
190                            .changed_objects
191                            .into_iter()
192                            .map(|obj| {
193                                (
194                                    obj.object_id,
195                                    crate::effects::EffectsObjectChange {
196                                        input_state: match obj.input_state {
197                                            ObjectIn::Missing => crate::effects::ObjectIn::NotExist,
198                                            ObjectIn::Data {
199                                                version,
200                                                digest,
201                                                owner,
202                                            } => crate::effects::ObjectIn::Exist((
203                                                (version, digest),
204                                                owner,
205                                            )),
206                                            _ => unimplemented!("a new enum variant was added and needs to be handled"),
207                                        },
208                                        output_state: match obj.output_state {
209                                            ObjectOut::Missing => {
210                                                crate::effects::ObjectOut::NotExist
211                                            }
212                                            ObjectOut::ObjectWrite { digest, owner } => {
213                                                crate::effects::ObjectOut::ObjectWrite((
214                                                    digest,
215                                                    owner,
216                                                ))
217                                            }
218                                            ObjectOut::PackageWrite { version, digest } => {
219                                                crate::effects::ObjectOut::PackageWrite((
220                                                    version,
221                                                    digest,
222                                                ))
223                                            }
224                                            _ => unimplemented!("a new enum variant was added and needs to be handled"),
225                                        },
226                                        id_operation: match obj.id_operation {
227                                            IdOperation::None => crate::effects::IDOperation::None,
228                                            IdOperation::Created => {
229                                                crate::effects::IDOperation::Created
230                                            }
231                                            IdOperation::Deleted => {
232                                                crate::effects::IDOperation::Deleted
233                                            }
234                                            _ => unimplemented!("a new enum variant was added and needs to be handled"),
235                                        },
236                                    },
237                                )
238                            })
239                            .collect(),
240                        unchanged_shared_objects: transaction_effects_v1
241                            .unchanged_shared_objects
242                            .into_iter()
243                            .map(|obj| {
244                                (
245                                    obj.object_id,
246                                    obj.kind,
247                                )
248                            })
249                            .collect(),
250                        aux_data_digest: transaction_effects_v1
251                            .auxiliary_data_digest,
252                    }
253                    .into();
254
255                Ok(effects)
256            }
257            _ => unimplemented!("a new enum variant was added and needs to be handled"),
258        }
259    }
260}
261
262impl TryFrom<crate::messages_checkpoint::CheckpointContents> for CheckpointContents {
263    type Error = SdkTypeConversionError;
264
265    fn try_from(
266        value: crate::messages_checkpoint::CheckpointContents,
267    ) -> Result<Self, Self::Error> {
268        Self(
269            value
270                .into_iter_with_signatures()
271                .map(|(digests, signatures)| {
272                    let signatures_result = signatures
273                        .into_iter()
274                        .map(TryInto::try_into)
275                        .collect::<Result<Vec<UserSignature>, _>>();
276
277                    match signatures_result {
278                        Ok(signatures) => Ok(CheckpointTransactionInfo {
279                            transaction: digests.transaction,
280                            effects: digests.effects,
281                            signatures,
282                        }),
283                        Err(e) => Err(SdkTypeConversionError::from(e)),
284                    }
285                })
286                .collect::<Result<Vec<_>, _>>()?,
287        )
288        .pipe(Ok)
289    }
290}
291
292impl TryFrom<CheckpointContents> for crate::messages_checkpoint::CheckpointContents {
293    type Error = SdkTypeConversionError;
294
295    fn try_from(value: CheckpointContents) -> Result<Self, Self::Error> {
296        let (transactions, user_signatures) = value.0.into_iter().fold(
297            (Vec::new(), Vec::new()),
298            |(mut transactions, mut user_signatures), info| {
299                transactions.push(crate::base_types::ExecutionDigests {
300                    transaction: info.transaction,
301                    effects: info.effects,
302                });
303                user_signatures.push(
304                    info.signatures
305                        .into_iter()
306                        .map(TryInto::try_into)
307                        .collect::<Result<_, _>>(),
308                );
309                (transactions, user_signatures)
310            },
311        );
312        crate::messages_checkpoint::CheckpointContents::new_with_digests_and_signatures(
313            transactions,
314            user_signatures.into_iter().collect::<Result<Vec<_>, _>>()?,
315        )
316        .pipe(Ok)
317    }
318}
319
320impl TryFrom<crate::full_checkpoint_content::CheckpointData> for CheckpointData {
321    type Error = SdkTypeConversionError;
322
323    fn try_from(
324        value: crate::full_checkpoint_content::CheckpointData,
325    ) -> Result<Self, Self::Error> {
326        Self {
327            checkpoint_summary: value.checkpoint_summary.try_into()?,
328            checkpoint_contents: value.checkpoint_contents.try_into()?,
329            transactions: value
330                .transactions
331                .into_iter()
332                .map(TryInto::try_into)
333                .collect::<Result<_, _>>()?,
334        }
335        .pipe(Ok)
336    }
337}
338
339impl TryFrom<CheckpointData> for crate::full_checkpoint_content::CheckpointData {
340    type Error = SdkTypeConversionError;
341
342    fn try_from(value: CheckpointData) -> Result<Self, Self::Error> {
343        Self {
344            checkpoint_summary: value.checkpoint_summary.try_into()?,
345            checkpoint_contents: value.checkpoint_contents.try_into()?,
346            transactions: value
347                .transactions
348                .into_iter()
349                .map(TryInto::try_into)
350                .collect::<Result<_, _>>()?,
351        }
352        .pipe(Ok)
353    }
354}
355
356impl TryFrom<crate::full_checkpoint_content::CheckpointTransaction> for CheckpointTransaction {
357    type Error = SdkTypeConversionError;
358
359    fn try_from(
360        value: crate::full_checkpoint_content::CheckpointTransaction,
361    ) -> Result<Self, Self::Error> {
362        let input_objects = value
363            .input_objects
364            .into_iter()
365            .map(TryInto::try_into)
366            .collect::<Result<_, _>>();
367        let output_objects = value
368            .output_objects
369            .into_iter()
370            .map(TryInto::try_into)
371            .collect::<Result<_, _>>();
372        match (input_objects, output_objects) {
373            (Ok(input_objects), Ok(output_objects)) => Ok(Self {
374                transaction: value.transaction.try_into()?,
375                effects: value.effects.try_into()?,
376                events: value.events.map(Into::into),
377                input_objects,
378                output_objects,
379            }),
380            (Err(e), _) | (_, Err(e)) => Err(e),
381        }
382    }
383}
384
385impl TryFrom<CheckpointTransaction> for crate::full_checkpoint_content::CheckpointTransaction {
386    type Error = SdkTypeConversionError;
387
388    fn try_from(value: CheckpointTransaction) -> Result<Self, Self::Error> {
389        let input_objects = value
390            .input_objects
391            .into_iter()
392            .map(TryInto::try_into)
393            .collect::<Result<_, _>>();
394        let output_objects = value
395            .output_objects
396            .into_iter()
397            .map(TryInto::try_into)
398            .collect::<Result<_, _>>();
399
400        match (input_objects, output_objects) {
401            (Ok(input_objects), Ok(output_objects)) => Ok(Self {
402                transaction: value.transaction.try_into()?,
403                effects: value.effects.try_into()?,
404                events: value.events.map(Into::into),
405                input_objects,
406                output_objects,
407            }),
408            (Err(e), _) | (_, Err(e)) => Err(e),
409        }
410    }
411}
412
413impl TryFrom<crate::signature::GenericSignature> for UserSignature {
414    type Error = bcs::Error;
415
416    fn try_from(value: crate::signature::GenericSignature) -> Result<Self, Self::Error> {
417        bcs::from_bytes(&bcs::to_bytes(&value)?)
418    }
419}
420
421impl TryFrom<UserSignature> for crate::signature::GenericSignature {
422    type Error = bcs::Error;
423
424    fn try_from(value: UserSignature) -> Result<Self, Self::Error> {
425        bcs::from_bytes(&bcs::to_bytes(&value)?)
426    }
427}
428
429impl From<crate::effects::TransactionEvents> for TransactionEvents {
430    fn from(value: crate::effects::TransactionEvents) -> Self {
431        Self(value.data)
432    }
433}
434
435impl From<TransactionEvents> for crate::effects::TransactionEvents {
436    fn from(value: TransactionEvents) -> Self {
437        Self { data: value.0 }
438    }
439}
440
441impl From<crate::messages_checkpoint::EndOfEpochData> for EndOfEpochData {
442    fn from(value: crate::messages_checkpoint::EndOfEpochData) -> Self {
443        Self {
444            next_epoch_committee: value
445                .next_epoch_committee
446                .into_iter()
447                .map(|(public_key, stake)| ValidatorCommitteeMember {
448                    public_key: Bls12381PublicKey::new(public_key.0),
449                    stake,
450                })
451                .collect(),
452            next_epoch_protocol_version: value.next_epoch_protocol_version.as_u64(),
453            epoch_commitments: value
454                .epoch_commitments
455                .into_iter()
456                .map(Into::into)
457                .collect(),
458            epoch_supply_change: value.epoch_supply_change,
459        }
460    }
461}
462
463impl From<EndOfEpochData> for crate::messages_checkpoint::EndOfEpochData {
464    fn from(value: EndOfEpochData) -> Self {
465        Self {
466            next_epoch_committee: value
467                .next_epoch_committee
468                .into_iter()
469                .map(|v| (v.public_key.into(), v.stake))
470                .collect(),
471            next_epoch_protocol_version: value.next_epoch_protocol_version.into(),
472            epoch_commitments: value
473                .epoch_commitments
474                .into_iter()
475                .map(Into::into)
476                .collect(),
477            epoch_supply_change: value.epoch_supply_change,
478        }
479    }
480}
481
482impl From<crate::messages_checkpoint::CheckpointCommitment> for CheckpointCommitment {
483    fn from(value: crate::messages_checkpoint::CheckpointCommitment) -> Self {
484        let crate::messages_checkpoint::CheckpointCommitment::ECMHLiveObjectSetDigest(digest) =
485            value;
486        Self::EcmhLiveObjectSet {
487            digest: Digest::new(digest.digest.into_inner()),
488        }
489    }
490}
491
492impl From<CheckpointCommitment> for crate::messages_checkpoint::CheckpointCommitment {
493    fn from(value: CheckpointCommitment) -> Self {
494        match value {
495            CheckpointCommitment::EcmhLiveObjectSet { digest } => {
496                Self::ECMHLiveObjectSetDigest(crate::messages_checkpoint::ECMHLiveObjectSetDigest {
497                    digest: crate::digests::Digest::new(digest.into_inner()),
498                })
499            }
500            _ => unimplemented!("a new enum variant was added and needs to be handled"),
501        }
502    }
503}
504
505impl TryFrom<crate::messages_checkpoint::CheckpointSummary> for CheckpointSummary {
506    type Error = SdkTypeConversionError;
507
508    fn try_from(value: crate::messages_checkpoint::CheckpointSummary) -> Result<Self, Self::Error> {
509        Self {
510            epoch: value.epoch,
511            sequence_number: value.sequence_number,
512            network_total_transactions: value.network_total_transactions,
513            content_digest: value.content_digest,
514            previous_digest: value.previous_digest,
515            epoch_rolling_gas_cost_summary: value.epoch_rolling_gas_cost_summary,
516            timestamp_ms: value.timestamp_ms,
517            checkpoint_commitments: value
518                .checkpoint_commitments
519                .into_iter()
520                .map(Into::into)
521                .collect(),
522            end_of_epoch_data: value.end_of_epoch_data.map(Into::into),
523            version_specific_data: value.version_specific_data,
524        }
525        .pipe(Ok)
526    }
527}
528
529impl TryFrom<CheckpointSummary> for crate::messages_checkpoint::CheckpointSummary {
530    type Error = SdkTypeConversionError;
531
532    fn try_from(value: CheckpointSummary) -> Result<Self, Self::Error> {
533        Self {
534            epoch: value.epoch,
535            sequence_number: value.sequence_number,
536            network_total_transactions: value.network_total_transactions,
537            content_digest: value.content_digest,
538            previous_digest: value.previous_digest,
539            epoch_rolling_gas_cost_summary: value.epoch_rolling_gas_cost_summary,
540            timestamp_ms: value.timestamp_ms,
541            checkpoint_commitments: value
542                .checkpoint_commitments
543                .into_iter()
544                .map(Into::into)
545                .collect(),
546            end_of_epoch_data: value.end_of_epoch_data.map(Into::into),
547            version_specific_data: value.version_specific_data,
548        }
549        .pipe(Ok)
550    }
551}
552
553impl TryFrom<crate::messages_checkpoint::CertifiedCheckpointSummary> for SignedCheckpointSummary {
554    type Error = SdkTypeConversionError;
555
556    fn try_from(
557        value: crate::messages_checkpoint::CertifiedCheckpointSummary,
558    ) -> Result<Self, Self::Error> {
559        let (data, sig) = value.into_data_and_sig();
560        Self {
561            checkpoint: data.try_into()?,
562            signature: sig.into(),
563        }
564        .pipe(Ok)
565    }
566}
567
568impl TryFrom<SignedCheckpointSummary> for crate::messages_checkpoint::CertifiedCheckpointSummary {
569    type Error = SdkTypeConversionError;
570
571    fn try_from(value: SignedCheckpointSummary) -> Result<Self, Self::Error> {
572        Self::new_from_data_and_sig(
573            crate::messages_checkpoint::CheckpointSummary::try_from(value.checkpoint)?,
574            crate::crypto::AuthorityQuorumSignInfo::<true>::from(value.signature),
575        )
576        .pipe(Ok)
577    }
578}
579
580impl<const T: bool> From<crate::crypto::AuthorityQuorumSignInfo<T>>
581    for ValidatorAggregatedSignature
582{
583    fn from(value: crate::crypto::AuthorityQuorumSignInfo<T>) -> Self {
584        let crate::crypto::AuthorityQuorumSignInfo {
585            epoch,
586            signature,
587            signers_map,
588        } = value;
589
590        Self {
591            epoch,
592            signature: Bls12381Signature::from_bytes(signature.as_ref()).unwrap(),
593            bitmap: signers_map,
594        }
595    }
596}
597
598impl<const T: bool> From<ValidatorAggregatedSignature>
599    for crate::crypto::AuthorityQuorumSignInfo<T>
600{
601    fn from(value: ValidatorAggregatedSignature) -> Self {
602        let ValidatorAggregatedSignature {
603            epoch,
604            signature,
605            bitmap,
606        } = value;
607
608        Self {
609            epoch,
610            signature: crate::crypto::AggregateAuthoritySignature::from_bytes(signature.as_bytes())
611                .unwrap(),
612            signers_map: bitmap,
613        }
614    }
615}
616
617impl TryFrom<crate::transaction::SenderSignedData> for SignedTransaction {
618    type Error = SdkTypeConversionError;
619
620    fn try_from(value: crate::transaction::SenderSignedData) -> Result<Self, Self::Error> {
621        let crate::transaction::SenderSignedTransaction {
622            intent_message,
623            tx_signatures,
624        } = value.into_inner();
625
626        Self {
627            transaction: intent_message.value,
628            signatures: tx_signatures
629                .into_iter()
630                .map(TryInto::try_into)
631                .collect::<Result<_, _>>()?,
632        }
633        .pipe(Ok)
634    }
635}
636
637impl TryFrom<SignedTransaction> for crate::transaction::SenderSignedData {
638    type Error = SdkTypeConversionError;
639
640    fn try_from(value: SignedTransaction) -> Result<Self, Self::Error> {
641        let SignedTransaction {
642            transaction,
643            signatures,
644        } = value;
645
646        Self::new(
647            transaction,
648            signatures
649                .into_iter()
650                .map(TryInto::try_into)
651                .collect::<Result<_, _>>()?,
652        )
653        .pipe(Ok)
654    }
655}
656
657impl TryFrom<crate::transaction::Transaction> for SignedTransaction {
658    type Error = SdkTypeConversionError;
659
660    fn try_from(value: crate::transaction::Transaction) -> Result<Self, Self::Error> {
661        value.into_data().try_into()
662    }
663}
664
665impl TryFrom<SignedTransaction> for crate::transaction::Transaction {
666    type Error = SdkTypeConversionError;
667
668    fn try_from(value: SignedTransaction) -> Result<Self, Self::Error> {
669        Ok(Self::new(value.try_into()?))
670    }
671}
672
673pub fn type_tag_core_to_sdk(value: &move_core_types::language_storage::TypeTag) -> TypeTag {
674    match value {
675        move_core_types::language_storage::TypeTag::Bool => TypeTag::Bool,
676        move_core_types::language_storage::TypeTag::U8 => TypeTag::U8,
677        move_core_types::language_storage::TypeTag::U64 => TypeTag::U64,
678        move_core_types::language_storage::TypeTag::U128 => TypeTag::U128,
679        move_core_types::language_storage::TypeTag::Address => TypeTag::Address,
680        move_core_types::language_storage::TypeTag::Signer => TypeTag::Signer,
681        move_core_types::language_storage::TypeTag::Vector(type_tag) => {
682            TypeTag::Vector(Box::new(type_tag_core_to_sdk(type_tag)))
683        }
684        move_core_types::language_storage::TypeTag::Struct(struct_tag) => {
685            TypeTag::Struct(Box::new(struct_tag_core_to_sdk(struct_tag)))
686        }
687        move_core_types::language_storage::TypeTag::U16 => TypeTag::U16,
688        move_core_types::language_storage::TypeTag::U32 => TypeTag::U32,
689        move_core_types::language_storage::TypeTag::U256 => TypeTag::U256,
690    }
691}
692
693pub fn type_tag_sdk_to_core(value: &TypeTag) -> move_core_types::language_storage::TypeTag {
694    match value {
695        TypeTag::Bool => move_core_types::language_storage::TypeTag::Bool,
696        TypeTag::U8 => move_core_types::language_storage::TypeTag::U8,
697        TypeTag::U64 => move_core_types::language_storage::TypeTag::U64,
698        TypeTag::U128 => move_core_types::language_storage::TypeTag::U128,
699        TypeTag::Address => move_core_types::language_storage::TypeTag::Address,
700        TypeTag::Signer => move_core_types::language_storage::TypeTag::Signer,
701        TypeTag::Vector(type_tag) => move_core_types::language_storage::TypeTag::Vector(Box::new(
702            type_tag_sdk_to_core(type_tag),
703        )),
704        TypeTag::Struct(struct_tag) => move_core_types::language_storage::TypeTag::Struct(
705            Box::new(struct_tag_sdk_to_core(struct_tag)),
706        ),
707        TypeTag::U16 => move_core_types::language_storage::TypeTag::U16,
708        TypeTag::U32 => move_core_types::language_storage::TypeTag::U32,
709        TypeTag::U256 => move_core_types::language_storage::TypeTag::U256,
710    }
711}
712
713pub fn struct_tag_core_to_sdk(value: &move_core_types::language_storage::StructTag) -> StructTag {
714    let move_core_types::language_storage::StructTag {
715        address,
716        module,
717        name,
718        type_params,
719    } = value;
720
721    let address = Address::new(address.into_bytes());
722    let module = Identifier::new_unchecked(module.as_str());
723    let name = Identifier::new_unchecked(name.as_str());
724    let type_params = type_params.iter().map(type_tag_core_to_sdk).collect();
725    StructTag::new(address, module, name, type_params)
726}
727
728pub fn struct_tag_sdk_to_core(value: &StructTag) -> move_core_types::language_storage::StructTag {
729    let address =
730        move_core_types::account_address::AccountAddress::new(value.address().into_bytes());
731    let module = move_core_types::identifier::Identifier::new(value.module().as_str()).unwrap();
732    let name = move_core_types::identifier::Identifier::new(value.name().as_str()).unwrap();
733    let type_params = value
734        .type_params()
735        .iter()
736        .map(type_tag_sdk_to_core)
737        .collect();
738    move_core_types::language_storage::StructTag {
739        address,
740        module,
741        name,
742        type_params,
743    }
744}
745
746impl From<crate::committee::Committee> for ValidatorCommittee {
747    fn from(value: crate::committee::Committee) -> Self {
748        Self {
749            epoch: value.epoch(),
750            members: value
751                .voting_rights
752                .into_iter()
753                .map(|(name, stake)| ValidatorCommitteeMember {
754                    public_key: name.into(),
755                    stake,
756                })
757                .collect(),
758        }
759    }
760}
761
762impl From<ValidatorCommittee> for crate::committee::Committee {
763    fn from(value: ValidatorCommittee) -> Self {
764        let ValidatorCommittee { epoch, members } = value;
765
766        Self::new(
767            epoch,
768            members
769                .into_iter()
770                .map(|member| (member.public_key.into(), member.stake))
771                .collect(),
772        )
773    }
774}
775
776impl From<crate::crypto::AuthorityPublicKeyBytes> for Bls12381PublicKey {
777    fn from(value: crate::crypto::AuthorityPublicKeyBytes) -> Self {
778        Self::new(value.0)
779    }
780}
781
782impl From<Bls12381PublicKey> for crate::crypto::AuthorityPublicKeyBytes {
783    fn from(value: Bls12381PublicKey) -> Self {
784        Self::new(value.into_inner())
785    }
786}