1use 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 move_core::{Identifier, StructTag, TypeParseError, TypeTag},
23 object::Object,
24 transaction::SignedTransaction,
25 validator::{ValidatorAggregatedSignature, ValidatorCommittee, ValidatorCommitteeMember},
26};
27use tap::Pipe;
28
29use crate::object::ObjectInner;
30
31#[derive(Debug)]
32pub struct SdkTypeConversionError(pub String);
33
34impl std::fmt::Display for SdkTypeConversionError {
35 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36 f.write_str(&self.0)
37 }
38}
39
40impl std::error::Error for SdkTypeConversionError {}
41
42impl From<TypeParseError> for SdkTypeConversionError {
43 fn from(value: TypeParseError) -> Self {
44 Self(value.to_string())
45 }
46}
47
48impl From<anyhow::Error> for SdkTypeConversionError {
49 fn from(value: anyhow::Error) -> Self {
50 Self(value.to_string())
51 }
52}
53
54impl From<bcs::Error> for SdkTypeConversionError {
55 fn from(value: bcs::Error) -> Self {
56 Self(value.to_string())
57 }
58}
59
60impl TryFrom<crate::object::Object> for Object {
61 type Error = SdkTypeConversionError;
62
63 fn try_from(value: crate::object::Object) -> Result<Self, Self::Error> {
64 Self {
65 data: value.data.clone(),
66 owner: value.owner,
67 previous_transaction: value.previous_transaction,
68 storage_rebate: value.storage_rebate,
69 }
70 .pipe(Ok)
71 }
72}
73
74impl TryFrom<Object> for crate::object::Object {
75 type Error = SdkTypeConversionError;
76
77 fn try_from(value: Object) -> Result<Self, Self::Error> {
78 Self::from(ObjectInner {
79 data: value.data,
80 owner: value.owner,
81 previous_transaction: value.previous_transaction,
82 storage_rebate: value.storage_rebate,
83 })
84 .pipe(Ok)
85 }
86}
87
88impl TryFrom<crate::messages_checkpoint::CheckpointContents> for CheckpointContents {
89 type Error = SdkTypeConversionError;
90
91 fn try_from(
92 value: crate::messages_checkpoint::CheckpointContents,
93 ) -> Result<Self, Self::Error> {
94 Self(
95 value
96 .into_iter_with_signatures()
97 .map(|(digests, signatures)| {
98 let signatures_result = signatures
99 .into_iter()
100 .map(TryInto::try_into)
101 .collect::<Result<Vec<UserSignature>, _>>();
102
103 match signatures_result {
104 Ok(signatures) => Ok(CheckpointTransactionInfo {
105 transaction: digests.transaction,
106 effects: digests.effects,
107 signatures,
108 }),
109 Err(e) => Err(SdkTypeConversionError::from(e)),
110 }
111 })
112 .collect::<Result<Vec<_>, _>>()?,
113 )
114 .pipe(Ok)
115 }
116}
117
118impl TryFrom<CheckpointContents> for crate::messages_checkpoint::CheckpointContents {
119 type Error = SdkTypeConversionError;
120
121 fn try_from(value: CheckpointContents) -> Result<Self, Self::Error> {
122 let (transactions, user_signatures) = value.0.into_iter().fold(
123 (Vec::new(), Vec::new()),
124 |(mut transactions, mut user_signatures), info| {
125 transactions.push(crate::base_types::ExecutionDigests {
126 transaction: info.transaction,
127 effects: info.effects,
128 });
129 user_signatures.push(
130 info.signatures
131 .into_iter()
132 .map(TryInto::try_into)
133 .collect::<Result<_, _>>(),
134 );
135 (transactions, user_signatures)
136 },
137 );
138 crate::messages_checkpoint::CheckpointContents::new_with_digests_and_signatures(
139 transactions,
140 user_signatures.into_iter().collect::<Result<Vec<_>, _>>()?,
141 )
142 .pipe(Ok)
143 }
144}
145
146impl TryFrom<crate::full_checkpoint_content::CheckpointData> for CheckpointData {
147 type Error = SdkTypeConversionError;
148
149 fn try_from(
150 value: crate::full_checkpoint_content::CheckpointData,
151 ) -> Result<Self, Self::Error> {
152 Self {
153 checkpoint_summary: value.checkpoint_summary.try_into()?,
154 checkpoint_contents: value.checkpoint_contents.try_into()?,
155 transactions: value
156 .transactions
157 .into_iter()
158 .map(TryInto::try_into)
159 .collect::<Result<_, _>>()?,
160 }
161 .pipe(Ok)
162 }
163}
164
165impl TryFrom<CheckpointData> for crate::full_checkpoint_content::CheckpointData {
166 type Error = SdkTypeConversionError;
167
168 fn try_from(value: CheckpointData) -> Result<Self, Self::Error> {
169 Self {
170 checkpoint_summary: value.checkpoint_summary.try_into()?,
171 checkpoint_contents: value.checkpoint_contents.try_into()?,
172 transactions: value
173 .transactions
174 .into_iter()
175 .map(TryInto::try_into)
176 .collect::<Result<_, _>>()?,
177 }
178 .pipe(Ok)
179 }
180}
181
182impl TryFrom<crate::full_checkpoint_content::CheckpointTransaction> for CheckpointTransaction {
183 type Error = SdkTypeConversionError;
184
185 fn try_from(
186 value: crate::full_checkpoint_content::CheckpointTransaction,
187 ) -> Result<Self, Self::Error> {
188 let input_objects = value
189 .input_objects
190 .into_iter()
191 .map(TryInto::try_into)
192 .collect::<Result<_, _>>();
193 let output_objects = value
194 .output_objects
195 .into_iter()
196 .map(TryInto::try_into)
197 .collect::<Result<_, _>>();
198 match (input_objects, output_objects) {
199 (Ok(input_objects), Ok(output_objects)) => Ok(Self {
200 transaction: value.transaction.try_into()?,
201 effects: value.effects,
202 events: value.events,
203 input_objects,
204 output_objects,
205 }),
206 (Err(e), _) | (_, Err(e)) => Err(e),
207 }
208 }
209}
210
211impl TryFrom<CheckpointTransaction> for crate::full_checkpoint_content::CheckpointTransaction {
212 type Error = SdkTypeConversionError;
213
214 fn try_from(value: CheckpointTransaction) -> Result<Self, Self::Error> {
215 let input_objects = value
216 .input_objects
217 .into_iter()
218 .map(TryInto::try_into)
219 .collect::<Result<_, _>>();
220 let output_objects = value
221 .output_objects
222 .into_iter()
223 .map(TryInto::try_into)
224 .collect::<Result<_, _>>();
225
226 match (input_objects, output_objects) {
227 (Ok(input_objects), Ok(output_objects)) => Ok(Self {
228 transaction: value.transaction.try_into()?,
229 effects: value.effects,
230 events: value.events,
231 input_objects,
232 output_objects,
233 }),
234 (Err(e), _) | (_, Err(e)) => Err(e),
235 }
236 }
237}
238
239impl TryFrom<crate::signature::GenericSignature> for UserSignature {
240 type Error = bcs::Error;
241
242 fn try_from(value: crate::signature::GenericSignature) -> Result<Self, Self::Error> {
243 bcs::from_bytes(&bcs::to_bytes(&value)?)
244 }
245}
246
247impl TryFrom<UserSignature> for crate::signature::GenericSignature {
248 type Error = bcs::Error;
249
250 fn try_from(value: UserSignature) -> Result<Self, Self::Error> {
251 bcs::from_bytes(&bcs::to_bytes(&value)?)
252 }
253}
254
255impl From<crate::messages_checkpoint::EndOfEpochData> for EndOfEpochData {
256 fn from(value: crate::messages_checkpoint::EndOfEpochData) -> Self {
257 Self {
258 next_epoch_committee: value
259 .next_epoch_committee
260 .into_iter()
261 .map(|(public_key, stake)| ValidatorCommitteeMember {
262 public_key: Bls12381PublicKey::new(public_key.0),
263 stake,
264 })
265 .collect(),
266 next_epoch_protocol_version: value.next_epoch_protocol_version.as_u64(),
267 epoch_commitments: value
268 .epoch_commitments
269 .into_iter()
270 .map(Into::into)
271 .collect(),
272 epoch_supply_change: value.epoch_supply_change,
273 }
274 }
275}
276
277impl From<EndOfEpochData> for crate::messages_checkpoint::EndOfEpochData {
278 fn from(value: EndOfEpochData) -> Self {
279 Self {
280 next_epoch_committee: value
281 .next_epoch_committee
282 .into_iter()
283 .map(|v| (v.public_key.into(), v.stake))
284 .collect(),
285 next_epoch_protocol_version: value.next_epoch_protocol_version.into(),
286 epoch_commitments: value
287 .epoch_commitments
288 .into_iter()
289 .map(Into::into)
290 .collect(),
291 epoch_supply_change: value.epoch_supply_change,
292 }
293 }
294}
295
296impl From<crate::messages_checkpoint::CheckpointCommitment> for CheckpointCommitment {
297 fn from(value: crate::messages_checkpoint::CheckpointCommitment) -> Self {
298 let crate::messages_checkpoint::CheckpointCommitment::ECMHLiveObjectSetDigest(digest) =
299 value;
300 Self::EcmhLiveObjectSet {
301 digest: Digest::new(digest.digest.into_inner()),
302 }
303 }
304}
305
306impl From<CheckpointCommitment> for crate::messages_checkpoint::CheckpointCommitment {
307 fn from(value: CheckpointCommitment) -> Self {
308 match value {
309 CheckpointCommitment::EcmhLiveObjectSet { digest } => {
310 Self::ECMHLiveObjectSetDigest(crate::messages_checkpoint::ECMHLiveObjectSetDigest {
311 digest: crate::digests::Digest::new(digest.into_inner()),
312 })
313 }
314 _ => unimplemented!(
315 "a new CheckpointCommitment enum variant was added and needs to be handled"
316 ),
317 }
318 }
319}
320
321impl TryFrom<crate::messages_checkpoint::CheckpointSummary> for CheckpointSummary {
322 type Error = SdkTypeConversionError;
323
324 fn try_from(value: crate::messages_checkpoint::CheckpointSummary) -> Result<Self, Self::Error> {
325 Self {
326 epoch: value.epoch,
327 sequence_number: value.sequence_number,
328 network_total_transactions: value.network_total_transactions,
329 content_digest: value.content_digest,
330 previous_digest: value.previous_digest,
331 epoch_rolling_gas_cost_summary: value.epoch_rolling_gas_cost_summary,
332 timestamp_ms: value.timestamp_ms,
333 checkpoint_commitments: value
334 .checkpoint_commitments
335 .into_iter()
336 .map(Into::into)
337 .collect(),
338 end_of_epoch_data: value.end_of_epoch_data.map(Into::into),
339 version_specific_data: value.version_specific_data,
340 }
341 .pipe(Ok)
342 }
343}
344
345impl TryFrom<CheckpointSummary> for crate::messages_checkpoint::CheckpointSummary {
346 type Error = SdkTypeConversionError;
347
348 fn try_from(value: CheckpointSummary) -> Result<Self, Self::Error> {
349 Self {
350 epoch: value.epoch,
351 sequence_number: value.sequence_number,
352 network_total_transactions: value.network_total_transactions,
353 content_digest: value.content_digest,
354 previous_digest: value.previous_digest,
355 epoch_rolling_gas_cost_summary: value.epoch_rolling_gas_cost_summary,
356 timestamp_ms: value.timestamp_ms,
357 checkpoint_commitments: value
358 .checkpoint_commitments
359 .into_iter()
360 .map(Into::into)
361 .collect(),
362 end_of_epoch_data: value.end_of_epoch_data.map(Into::into),
363 version_specific_data: value.version_specific_data,
364 }
365 .pipe(Ok)
366 }
367}
368
369impl TryFrom<crate::messages_checkpoint::CertifiedCheckpointSummary> for SignedCheckpointSummary {
370 type Error = SdkTypeConversionError;
371
372 fn try_from(
373 value: crate::messages_checkpoint::CertifiedCheckpointSummary,
374 ) -> Result<Self, Self::Error> {
375 let (data, sig) = value.into_data_and_sig();
376 Self {
377 checkpoint: data.try_into()?,
378 signature: sig.into(),
379 }
380 .pipe(Ok)
381 }
382}
383
384impl TryFrom<SignedCheckpointSummary> for crate::messages_checkpoint::CertifiedCheckpointSummary {
385 type Error = SdkTypeConversionError;
386
387 fn try_from(value: SignedCheckpointSummary) -> Result<Self, Self::Error> {
388 Self::new_from_data_and_sig(
389 crate::messages_checkpoint::CheckpointSummary::try_from(value.checkpoint)?,
390 crate::crypto::AuthorityQuorumSignInfo::<true>::from(value.signature),
391 )
392 .pipe(Ok)
393 }
394}
395
396impl<const T: bool> From<crate::crypto::AuthorityQuorumSignInfo<T>>
397 for ValidatorAggregatedSignature
398{
399 fn from(value: crate::crypto::AuthorityQuorumSignInfo<T>) -> Self {
400 let crate::crypto::AuthorityQuorumSignInfo {
401 epoch,
402 signature,
403 signers_map,
404 } = value;
405
406 Self {
407 epoch,
408 signature: Bls12381Signature::from_bytes(signature.as_ref()).unwrap(),
409 bitmap: signers_map,
410 }
411 }
412}
413
414impl<const T: bool> From<ValidatorAggregatedSignature>
415 for crate::crypto::AuthorityQuorumSignInfo<T>
416{
417 fn from(value: ValidatorAggregatedSignature) -> Self {
418 let ValidatorAggregatedSignature {
419 epoch,
420 signature,
421 bitmap,
422 } = value;
423
424 Self {
425 epoch,
426 signature: crate::crypto::AggregateAuthoritySignature::from_bytes(signature.as_bytes())
427 .unwrap(),
428 signers_map: bitmap,
429 }
430 }
431}
432
433impl TryFrom<crate::transaction::SenderSignedData> for SignedTransaction {
434 type Error = SdkTypeConversionError;
435
436 fn try_from(value: crate::transaction::SenderSignedData) -> Result<Self, Self::Error> {
437 let crate::transaction::SenderSignedTransaction {
438 intent_message,
439 tx_signatures,
440 } = value.into_inner();
441
442 Self {
443 transaction: intent_message.value,
444 signatures: tx_signatures
445 .into_iter()
446 .map(TryInto::try_into)
447 .collect::<Result<_, _>>()?,
448 }
449 .pipe(Ok)
450 }
451}
452
453impl TryFrom<SignedTransaction> for crate::transaction::SenderSignedData {
454 type Error = SdkTypeConversionError;
455
456 fn try_from(value: SignedTransaction) -> Result<Self, Self::Error> {
457 let SignedTransaction {
458 transaction,
459 signatures,
460 } = value;
461
462 Self::new(
463 transaction,
464 signatures
465 .into_iter()
466 .map(TryInto::try_into)
467 .collect::<Result<_, _>>()?,
468 )
469 .pipe(Ok)
470 }
471}
472
473impl TryFrom<crate::transaction::Transaction> for SignedTransaction {
474 type Error = SdkTypeConversionError;
475
476 fn try_from(value: crate::transaction::Transaction) -> Result<Self, Self::Error> {
477 value.into_data().try_into()
478 }
479}
480
481impl TryFrom<SignedTransaction> for crate::transaction::Transaction {
482 type Error = SdkTypeConversionError;
483
484 fn try_from(value: SignedTransaction) -> Result<Self, Self::Error> {
485 Ok(Self::new(value.try_into()?))
486 }
487}
488
489pub fn type_tag_core_to_sdk(value: &move_core_types::language_storage::TypeTag) -> TypeTag {
490 match value {
491 move_core_types::language_storage::TypeTag::Bool => TypeTag::Bool,
492 move_core_types::language_storage::TypeTag::U8 => TypeTag::U8,
493 move_core_types::language_storage::TypeTag::U64 => TypeTag::U64,
494 move_core_types::language_storage::TypeTag::U128 => TypeTag::U128,
495 move_core_types::language_storage::TypeTag::Address => TypeTag::Address,
496 move_core_types::language_storage::TypeTag::Signer => TypeTag::Signer,
497 move_core_types::language_storage::TypeTag::Vector(type_tag) => {
498 TypeTag::Vector(Box::new(type_tag_core_to_sdk(type_tag)))
499 }
500 move_core_types::language_storage::TypeTag::Struct(struct_tag) => {
501 TypeTag::Struct(Box::new(struct_tag_core_to_sdk(struct_tag)))
502 }
503 move_core_types::language_storage::TypeTag::U16 => TypeTag::U16,
504 move_core_types::language_storage::TypeTag::U32 => TypeTag::U32,
505 move_core_types::language_storage::TypeTag::U256 => TypeTag::U256,
506 }
507}
508
509pub fn type_tag_sdk_to_core(value: &TypeTag) -> move_core_types::language_storage::TypeTag {
510 match value {
511 TypeTag::Bool => move_core_types::language_storage::TypeTag::Bool,
512 TypeTag::U8 => move_core_types::language_storage::TypeTag::U8,
513 TypeTag::U64 => move_core_types::language_storage::TypeTag::U64,
514 TypeTag::U128 => move_core_types::language_storage::TypeTag::U128,
515 TypeTag::Address => move_core_types::language_storage::TypeTag::Address,
516 TypeTag::Signer => move_core_types::language_storage::TypeTag::Signer,
517 TypeTag::Vector(type_tag) => move_core_types::language_storage::TypeTag::Vector(Box::new(
518 type_tag_sdk_to_core(type_tag),
519 )),
520 TypeTag::Struct(struct_tag) => move_core_types::language_storage::TypeTag::Struct(
521 Box::new(struct_tag_sdk_to_core(struct_tag)),
522 ),
523 TypeTag::U16 => move_core_types::language_storage::TypeTag::U16,
524 TypeTag::U32 => move_core_types::language_storage::TypeTag::U32,
525 TypeTag::U256 => move_core_types::language_storage::TypeTag::U256,
526 }
527}
528
529pub fn struct_tag_core_to_sdk(value: &move_core_types::language_storage::StructTag) -> StructTag {
530 let move_core_types::language_storage::StructTag {
531 address,
532 module,
533 name,
534 type_params,
535 } = value;
536
537 let address = Address::new(address.into_bytes());
538 let module = Identifier::new_unchecked(module.as_str());
539 let name = Identifier::new_unchecked(name.as_str());
540 let type_params = type_params.iter().map(type_tag_core_to_sdk).collect();
541 StructTag::new(address, module, name, type_params)
542}
543
544pub fn struct_tag_sdk_to_core(value: &StructTag) -> move_core_types::language_storage::StructTag {
545 let address =
546 move_core_types::account_address::AccountAddress::new(value.address().into_bytes());
547 let module = move_core_types::identifier::Identifier::new(value.module().as_str()).unwrap();
548 let name = move_core_types::identifier::Identifier::new(value.name().as_str()).unwrap();
549 let type_params = value
550 .type_params()
551 .iter()
552 .map(type_tag_sdk_to_core)
553 .collect();
554 move_core_types::language_storage::StructTag {
555 address,
556 module,
557 name,
558 type_params,
559 }
560}
561
562impl From<crate::committee::Committee> for ValidatorCommittee {
563 fn from(value: crate::committee::Committee) -> Self {
564 Self {
565 epoch: value.epoch(),
566 members: value
567 .voting_rights
568 .into_iter()
569 .map(|(name, stake)| ValidatorCommitteeMember {
570 public_key: name.into(),
571 stake,
572 })
573 .collect(),
574 }
575 }
576}
577
578impl From<ValidatorCommittee> for crate::committee::Committee {
579 fn from(value: ValidatorCommittee) -> Self {
580 let ValidatorCommittee { epoch, members } = value;
581
582 Self::new(
583 epoch,
584 members
585 .into_iter()
586 .map(|member| (member.public_key.into(), member.stake))
587 .collect(),
588 )
589 }
590}
591
592impl From<crate::crypto::AuthorityPublicKeyBytes> for Bls12381PublicKey {
593 fn from(value: crate::crypto::AuthorityPublicKeyBytes) -> Self {
594 Self::new(value.0)
595 }
596}
597
598impl From<Bls12381PublicKey> for crate::crypto::AuthorityPublicKeyBytes {
599 fn from(value: Bls12381PublicKey) -> Self {
600 Self::new(value.into_inner())
601 }
602}