diff --git a/crates/iota-rest-api/src/accounts.rs b/crates/iota-rest-api/src/accounts.rs index 3911da863c3..248089b7e52 100644 --- a/crates/iota-rest-api/src/accounts.rs +++ b/crates/iota-rest-api/src/accounts.rs @@ -58,14 +58,17 @@ async fn list_account_objects( let mut object_info = state .inner() .account_owned_objects_info_iter(address.into(), start)? - .map(|info| AccountOwnedObjectInfo { - owner: info.owner.into(), - object_id: info.object_id.into(), - version: info.version.into(), - type_: struct_tag_core_to_sdk(info.type_.into()), - }) .take(limit + 1) - .collect::>(); + .map(|info| { + AccountOwnedObjectInfo { + owner: info.owner.into(), + object_id: info.object_id.into(), + version: info.version.into(), + type_: struct_tag_core_to_sdk(info.type_.into())?, + } + .pipe(Ok) + }) + .collect::>>()?; let cursor = if object_info.len() > limit { // SAFETY: We've already verified that object_info is greater than limit, which diff --git a/crates/iota-rest-api/src/checkpoints.rs b/crates/iota-rest-api/src/checkpoints.rs index 4c825d21980..720393dc677 100644 --- a/crates/iota-rest-api/src/checkpoints.rs +++ b/crates/iota-rest-api/src/checkpoints.rs @@ -153,7 +153,7 @@ async fn get_checkpoint( }? .ok_or(CheckpointNotFoundError(checkpoint_id))? .into_inner() - .into(); + .try_into()?; match accept { AcceptFormat::Json => ResponseContent::Json(summary), @@ -279,11 +279,15 @@ async fn list_checkpoints( let checkpoints = state .checkpoint_iter(direction, start) + .take(limit) .map(|result| { - result.map(|(checkpoint, _contents)| SignedCheckpointSummary::from(checkpoint)) + result + .map_err(Into::into) + .and_then(|(checkpoint, _contents)| { + SignedCheckpointSummary::try_from(checkpoint).map_err(Into::into) + }) }) - .take(limit) - .collect::, _>>()?; + .collect::>>()?; let cursor = checkpoints.last().and_then(|checkpoint| match direction { Direction::Ascending => checkpoint.checkpoint.sequence_number.checked_add(1), diff --git a/crates/iota-rest-api/src/client/mod.rs b/crates/iota-rest-api/src/client/mod.rs index 7461df52299..479f009c4fc 100644 --- a/crates/iota-rest-api/src/client/mod.rs +++ b/crates/iota-rest-api/src/client/mod.rs @@ -37,7 +37,7 @@ impl Client { .get_latest_checkpoint() .await .map(Response::into_inner) - .map(Into::into) + .and_then(|checkpoint| checkpoint.try_into().map_err(Into::into)) } pub async fn get_full_checkpoint( @@ -68,7 +68,7 @@ impl Client { .get_checkpoint(checkpoint_sequence_number) .await .map(Response::into_inner) - .map(Into::into) + .and_then(|checkpoint| checkpoint.try_into().map_err(Into::into)) } pub async fn get_object(&self, object_id: ObjectID) -> Result { @@ -76,7 +76,7 @@ impl Client { .get_object(object_id.into()) .await .map(Response::into_inner) - .map(Into::into) + .and_then(|object| object.try_into().map_err(Into::into)) } pub async fn get_object_with_version( @@ -88,7 +88,7 @@ impl Client { .get_object_with_version(object_id.into(), version.into()) .await .map(Response::into_inner) - .map(Into::into) + .and_then(|object| object.try_into().map_err(Into::into)) } pub async fn execute_transaction( diff --git a/crates/iota-rest-api/src/client/sdk.rs b/crates/iota-rest-api/src/client/sdk.rs index 89ae4df822a..ae07648445b 100644 --- a/crates/iota-rest-api/src/client/sdk.rs +++ b/crates/iota-rest-api/src/client/sdk.rs @@ -652,3 +652,9 @@ impl From for Error { Self::from_error(error) } } + +impl From for Error { + fn from(value: iota_types::iota_sdk2_conversions::SdkTypeConversionError) -> Self { + Self::from_error(value) + } +} diff --git a/crates/iota-rest-api/src/coins.rs b/crates/iota-rest-api/src/coins.rs index 4562e563ec0..2b684e4ca1f 100644 --- a/crates/iota-rest-api/src/coins.rs +++ b/crates/iota-rest-api/src/coins.rs @@ -55,7 +55,7 @@ async fn get_coin_info( Path(coin_type): Path, State(state): State, ) -> Result> { - let core_coin_type = struct_tag_sdk_to_core(coin_type.clone()); + let core_coin_type = struct_tag_sdk_to_core(coin_type.clone())?; let iota_types::storage::CoinInfo { coin_metadata_object_id, diff --git a/crates/iota-rest-api/src/error.rs b/crates/iota-rest-api/src/error.rs index a2c2bb45b24..b6c07b47026 100644 --- a/crates/iota-rest-api/src/error.rs +++ b/crates/iota-rest-api/src/error.rs @@ -48,6 +48,24 @@ impl From for RestError { } } +impl From for RestError { + fn from(value: iota_types::iota_sdk2_conversions::SdkTypeConversionError) -> Self { + Self { + status: StatusCode::INTERNAL_SERVER_ERROR, + message: Some(value.to_string()), + } + } +} + +impl From for RestError { + fn from(value: bcs::Error) -> Self { + Self { + status: StatusCode::INTERNAL_SERVER_ERROR, + message: Some(value.to_string()), + } + } +} + impl From for RestError { fn from(error: iota_types::quorum_driver_types::QuorumDriverError) -> Self { use iota_types::{error::IotaError, quorum_driver_types::QuorumDriverError::*}; diff --git a/crates/iota-rest-api/src/objects.rs b/crates/iota-rest-api/src/objects.rs index 6a0088be245..09ebf8f6e83 100644 --- a/crates/iota-rest-api/src/objects.rs +++ b/crates/iota-rest-api/src/objects.rs @@ -5,7 +5,7 @@ use axum::extract::{Path, Query, State}; use iota_sdk2::types::{Object, ObjectId, TypeTag, Version}; use iota_types::{ - iota_sdk2_conversions::type_tag_core_to_sdk, + iota_sdk2_conversions::{SdkTypeConversionError, type_tag_core_to_sdk}, storage::{DynamicFieldIndexInfo, DynamicFieldKey}, }; use serde::{Deserialize, Serialize}; @@ -222,8 +222,8 @@ async fn list_dynamic_fields( .inner() .dynamic_field_iter(parent.into(), start)? .take(limit + 1) - .map(DynamicFieldInfo::from) - .collect::>(); + .map(DynamicFieldInfo::try_from) + .collect::, _>>()?; let cursor = if dynamic_fields.len() > limit { // SAFETY: We've already verified that object_keys is greater than limit, which @@ -275,8 +275,10 @@ pub struct DynamicFieldInfo { pub dynamic_object_id: Option, } -impl From<(DynamicFieldKey, DynamicFieldIndexInfo)> for DynamicFieldInfo { - fn from(value: (DynamicFieldKey, DynamicFieldIndexInfo)) -> Self { +impl TryFrom<(DynamicFieldKey, DynamicFieldIndexInfo)> for DynamicFieldInfo { + type Error = SdkTypeConversionError; + + fn try_from(value: (DynamicFieldKey, DynamicFieldIndexInfo)) -> Result { let DynamicFieldKey { parent, field_id } = value.0; let DynamicFieldIndexInfo { dynamic_field_type, @@ -289,10 +291,11 @@ impl From<(DynamicFieldKey, DynamicFieldIndexInfo)> for DynamicFieldInfo { parent: parent.into(), field_id: field_id.into(), dynamic_field_type: dynamic_field_type.into(), - name_type: type_tag_core_to_sdk(name_type), + name_type: type_tag_core_to_sdk(name_type)?, name_value, dynamic_object_id: dynamic_object_id.map(Into::into), } + .pipe(Ok) } } diff --git a/crates/iota-rest-api/src/reader.rs b/crates/iota-rest-api/src/reader.rs index 0446a499a3f..d7c1966c800 100644 --- a/crates/iota-rest-api/src/reader.rs +++ b/crates/iota-rest-api/src/reader.rs @@ -30,20 +30,22 @@ impl StateReader { &self.inner } - pub fn get_object(&self, object_id: ObjectId) -> Result> { + pub fn get_object(&self, object_id: ObjectId) -> crate::Result> { self.inner .get_object(&object_id.into()) - .map(|maybe| maybe.map(Into::into)) + .map_err(Into::into) + .and_then(|maybe| maybe.map(TryInto::try_into).transpose().map_err(Into::into)) } pub fn get_object_with_version( &self, object_id: ObjectId, version: Version, - ) -> Result> { + ) -> crate::Result> { self.inner .get_object_by_key(&object_id.into(), version.into()) - .map(|maybe| maybe.map(Into::into)) + .map_err(Into::into) + .and_then(|maybe| maybe.map(TryInto::try_into).transpose().map_err(Into::into)) } pub fn get_committee(&self, epoch: EpochId) -> Result> { @@ -95,7 +97,11 @@ impl StateReader { None }; - Ok((transaction.into(), effects.into(), events.map(Into::into))) + Ok(( + transaction.try_into()?, + effects.try_into()?, + events.map(TryInto::try_into).transpose()?, + )) } pub fn get_transaction_response( diff --git a/crates/iota-rest-api/src/transactions/execution.rs b/crates/iota-rest-api/src/transactions/execution.rs index 4a4c9cdfa60..aea78a4dfb1 100644 --- a/crates/iota-rest-api/src/transactions/execution.rs +++ b/crates/iota-rest-api/src/transactions/execution.rs @@ -74,7 +74,7 @@ async fn execute_transaction( ) -> Result> { let executor = state.ok_or_else(|| anyhow::anyhow!("No Transaction Executor"))?; let request = iota_types::quorum_driver_types::ExecuteTransactionRequestV1 { - transaction: transaction.into(), + transaction: transaction.try_into()?, include_events: parameters.events, include_input_objects: parameters.input_objects || parameters.balance_changes, include_output_objects: parameters.output_objects || parameters.balance_changes, @@ -108,19 +108,31 @@ async fn execute_transaction( ) => EffectsFinality::Checkpointed { checkpoint }, }; - (effects.into(), finality) + (effects.try_into()?, finality) }; let events = if parameters.events { - events.map(Into::into) + events.map(TryInto::try_into).transpose()? } else { None }; - let input_objects = - input_objects.map(|objects| objects.into_iter().map(Into::into).collect::>()); - let output_objects = - output_objects.map(|objects| objects.into_iter().map(Into::into).collect::>()); + let input_objects = input_objects + .map(|objects| { + objects + .into_iter() + .map(TryInto::try_into) + .collect::, _>>() + }) + .transpose()?; + let output_objects = output_objects + .map(|objects| { + objects + .into_iter() + .map(TryInto::try_into) + .collect::, _>>() + }) + .transpose()?; let balance_changes = match (parameters.balance_changes, &input_objects, &output_objects) { (true, Some(input_objects), Some(output_objects)) => Some(derive_balance_changes( diff --git a/crates/iota-types/src/iota_sdk2_conversions.rs b/crates/iota-types/src/iota_sdk2_conversions.rs index 4ca1631cc76..50a906cf058 100644 --- a/crates/iota-types/src/iota_sdk2_conversions.rs +++ b/crates/iota-types/src/iota_sdk2_conversions.rs @@ -16,47 +16,89 @@ use iota_sdk2::types::{ *, }; use move_core_types::language_storage::ModuleId; +use tap::Pipe; use crate::transaction::TransactionDataAPI as _; -impl From for Object { - fn from(value: crate::object::Object) -> Self { +#[derive(Debug)] +pub struct SdkTypeConversionError(pub String); + +impl std::fmt::Display for SdkTypeConversionError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(&self.0) + } +} + +impl std::error::Error for SdkTypeConversionError {} + +impl From for SdkTypeConversionError { + fn from(value: TypeParseError) -> Self { + Self(value.to_string()) + } +} + +impl From for SdkTypeConversionError { + fn from(value: anyhow::Error) -> Self { + Self(value.to_string()) + } +} + +impl From for SdkTypeConversionError { + fn from(value: bcs::Error) -> Self { + Self(value.to_string()) + } +} + +impl TryFrom for Object { + type Error = SdkTypeConversionError; + + fn try_from(value: crate::object::Object) -> Result { Self { - data: value.data.clone().into(), + data: value.data.clone().try_into()?, owner: value.owner.into(), previous_transaction: value.previous_transaction.into(), storage_rebate: value.storage_rebate, } + .pipe(Ok) } } -impl From for crate::object::Object { - fn from(value: Object) -> Self { +impl TryFrom for crate::object::Object { + type Error = SdkTypeConversionError; + + fn try_from(value: Object) -> Result { Self::new_from_genesis( - value.data.into(), + value.data.try_into()?, value.owner.into(), value.previous_transaction.into(), ) + .pipe(Ok) } } -impl From for ObjectData { - fn from(value: crate::object::Data) -> Self { +impl TryFrom for ObjectData { + type Error = SdkTypeConversionError; + + fn try_from(value: crate::object::Data) -> Result { match value { crate::object::Data::Move(move_object) => Self::Struct(move_object_to_sdk(move_object)), crate::object::Data::Package(move_package) => { Self::Package(move_package_to_sdk(move_package)) } } + .pipe(Ok) } } -impl From for crate::object::Data { - fn from(value: ObjectData) -> Self { +impl TryFrom for crate::object::Data { + type Error = SdkTypeConversionError; + + fn try_from(value: ObjectData) -> Result { match value { - ObjectData::Struct(move_object) => Self::Move(sdk_object_to_move(move_object)), + ObjectData::Struct(move_object) => Self::Move(sdk_object_to_move(move_object)?), ObjectData::Package(move_package) => Self::Package(sdk_package_to_move(move_package)), } + .pipe(Ok) } } @@ -149,12 +191,15 @@ fn move_object_to_sdk(obj: crate::object::MoveObject) -> MoveStruct { } } -fn sdk_object_to_move(obj: MoveStruct) -> crate::object::MoveObject { +fn sdk_object_to_move( + obj: MoveStruct, +) -> Result { crate::object::MoveObject { - type_: sdk_object_type_to_move(obj.type_), + type_: sdk_object_type_to_move(obj.type_)?, version: obj.version.into(), contents: obj.contents, } + .pipe(Ok) } fn move_object_type_to_sdk(type_: crate::base_types::MoveObjectType) -> StructTag { @@ -166,18 +211,20 @@ fn move_object_type_to_sdk(type_: crate::base_types::MoveObjectType) -> StructTa }) } -fn sdk_object_type_to_move(type_: StructTag) -> crate::base_types::MoveObjectType { +fn sdk_object_type_to_move( + type_: StructTag, +) -> Result { crate::base_types::MoveObjectType::from(move_core_types::language_storage::StructTag { address: move_core_types::account_address::AccountAddress::new(type_.address.into_inner()), - module: crate::Identifier::new(type_.module.as_str()) - .expect("struct module name conversion failed"), - name: crate::Identifier::new(type_.name.as_str()).expect("struct name conversion failed"), + module: crate::Identifier::new(type_.module.as_str())?, + name: crate::Identifier::new(type_.name.as_str())?, type_params: type_ .type_params .into_iter() .map(type_tag_sdk_to_core) - .collect(), + .collect::>()?, }) + .pipe(Ok) } fn move_type_origin_to_sdk(origin: crate::move_package::TypeOrigin) -> TypeOrigin { @@ -212,8 +259,10 @@ fn sdk_upgrade_info_to_move(info: UpgradeInfo) -> crate::move_package::UpgradeIn } } -impl From for Transaction { - fn from(value: crate::transaction::TransactionData) -> Self { +impl TryFrom for Transaction { + type Error = SdkTypeConversionError; + + fn try_from(value: crate::transaction::TransactionData) -> Result { Self { sender: Address::new(value.sender().to_inner()), gas_payment: GasPayment { @@ -234,15 +283,18 @@ impl From for Transaction { TransactionExpiration::Epoch(*e) } }, - kind: value.into_kind().into(), + kind: value.into_kind().try_into()?, } + .pipe(Ok) } } -impl From for crate::transaction::TransactionData { - fn from(value: Transaction) -> Self { +impl TryFrom for crate::transaction::TransactionData { + type Error = SdkTypeConversionError; + + fn try_from(value: Transaction) -> Result { Self::new_with_gas_data( - value.kind.into(), + value.kind.try_into()?, value.sender.into(), crate::transaction::GasData { payment: value @@ -257,12 +309,16 @@ impl From for crate::transaction::TransactionData { budget: value.gas_payment.budget, }, ) + .pipe(Ok) } } -impl From for TransactionKind { - fn from(value: crate::transaction::TransactionKind) -> Self { +impl TryFrom for TransactionKind { + type Error = SdkTypeConversionError; + + fn try_from(value: crate::transaction::TransactionKind) -> Result { use crate::transaction::TransactionKind as InternalTxnKind; + match value { InternalTxnKind::ProgrammableTransaction(programmable_transaction) => { TransactionKind::ProgrammableTransaction(ProgrammableTransaction { @@ -274,8 +330,8 @@ impl From for TransactionKind { commands: programmable_transaction .commands .into_iter() - .map(Into::into) - .collect(), + .map(TryInto::try_into) + .collect::>()?, }) } InternalTxnKind::Genesis(genesis_transaction) => { @@ -285,25 +341,37 @@ impl From for TransactionKind { .into_iter() .map(|obj| match obj { crate::transaction::GenesisObject::RawObject { data, owner } => { - GenesisObject { - data: data.into(), - owner: owner.into(), + match data.try_into() { + Ok(data) => Ok(GenesisObject { + data, + owner: owner.into(), + }), + Err(e) => Err(e), } } }) - .collect(), + .collect::>()?, events: genesis_transaction .events .into_iter() - .map(|event| Event { - package_id: event.package_id.into(), - module: Identifier::new(event.transaction_module.as_str()) - .expect("invalid transaction module"), - sender: event.sender.into(), - type_: struct_tag_core_to_sdk(event.type_), - contents: event.contents, + .map(|event| { + let module = Identifier::new(event.transaction_module.as_str()); + let type_ = struct_tag_core_to_sdk(event.type_); + + match (module, type_) { + (Ok(module), Ok(type_)) => Ok(Event { + package_id: event.package_id.into(), + module, + sender: event.sender.into(), + type_, + contents: event.contents, + }), + _ => Err(SdkTypeConversionError( + "invalid transaction module or struct tag".to_string(), + )), + } }) - .collect(), + .collect::>()?, }) } InternalTxnKind::ConsensusCommitPrologueV1(consensus_commit_prologue_v1) => { @@ -372,11 +440,14 @@ impl From for TransactionKind { }) } } + .pipe(Ok) } } -impl From for crate::transaction::TransactionKind { - fn from(value: TransactionKind) -> Self { +impl TryFrom for crate::transaction::TransactionKind { + type Error = SdkTypeConversionError; + + fn try_from(value: TransactionKind) -> Result { match value { TransactionKind::ProgrammableTransaction(programmable_transaction) => { Self::ProgrammableTransaction(crate::transaction::ProgrammableTransaction { @@ -388,8 +459,8 @@ impl From for crate::transaction::TransactionKind { commands: programmable_transaction .commands .into_iter() - .map(Into::into) - .collect(), + .map(TryInto::try_into) + .collect::>()?, }) } TransactionKind::Genesis(genesis_transaction) => { @@ -397,23 +468,37 @@ impl From for crate::transaction::TransactionKind { objects: genesis_transaction .objects .into_iter() - .map(|obj| crate::transaction::GenesisObject::RawObject { - data: obj.data.into(), - owner: obj.owner.into(), + .map(|obj| { + match obj.data.try_into() { + Ok(data) => Ok(crate::transaction::GenesisObject::RawObject { + data, + owner: obj.owner.into(), + }), + Err(e) => Err(e), + } }) - .collect(), + .collect::>()?, events: genesis_transaction .events .into_iter() - .map(|event| crate::event::Event { - package_id: event.package_id.into(), - transaction_module: crate::Identifier::new(event.module.as_str()) - .expect("invalid transaction module"), - sender: event.sender.into(), - type_: struct_tag_sdk_to_core(event.type_), - contents: event.contents, + .map(|event| { + let transaction_module = crate::Identifier::new(event.module.as_str()); + let type_ = struct_tag_sdk_to_core(event.type_); + + match (transaction_module, type_) { + (Ok(transaction_module), Ok(type_)) => Ok(crate::event::Event { + package_id: event.package_id.into(), + transaction_module, + sender: event.sender.into(), + type_, + contents: event.contents, + }), + _ => Err(SdkTypeConversionError( + "invalid transaction module or struct tag".to_string(), + )), + } }) - .collect(), + .collect::>()?, }) } TransactionKind::ConsensusCommitPrologueV1(consensus_commit_prologue_v1) => { @@ -487,6 +572,7 @@ impl From for crate::transaction::TransactionKind { }) } } + .pipe(Ok) } } @@ -640,8 +726,10 @@ fn sdk_obj_ref_to_core(obj_ref: ObjectReference) -> crate::base_types::ObjectRef (id.into(), seq.into(), digest.into()) } -impl From for TransactionEffects { - fn from(value: crate::effects::TransactionEffects) -> Self { +impl TryFrom for TransactionEffects { + type Error = SdkTypeConversionError; + + fn try_from(value: crate::effects::TransactionEffects) -> Result { match value { crate::effects::TransactionEffects::V1(effects) => { Self::V1(Box::new(TransactionEffectsV1 { @@ -734,104 +822,120 @@ impl From for TransactionEffects { auxiliary_data_digest: effects.aux_data_digest.map(Into::into), status: effects.status.into(), })) + .pipe(Ok) } } } } -impl From for crate::effects::TransactionEffects { - fn from(value: TransactionEffects) -> Self { +impl TryFrom for crate::effects::TransactionEffects { + type Error = SdkTypeConversionError; + + fn try_from(value: TransactionEffects) -> Result { match value { TransactionEffects::V1(transaction_effects_v1) => { - crate::effects::effects_v1::TransactionEffectsV1 { - status: transaction_effects_v1.status.into(), - executed_epoch: transaction_effects_v1.epoch, - gas_used: crate::gas::GasCostSummary::new( - transaction_effects_v1.gas_used.computation_cost, - transaction_effects_v1.gas_used.computation_cost_burned, - transaction_effects_v1.gas_used.storage_cost, - transaction_effects_v1.gas_used.storage_rebate, - transaction_effects_v1.gas_used.non_refundable_storage_fee, - ), - transaction_digest: transaction_effects_v1.transaction_digest.into(), - gas_object_index: transaction_effects_v1.gas_object_index, - events_digest: transaction_effects_v1.events_digest.map(Into::into), - dependencies: transaction_effects_v1 - .dependencies - .into_iter() - .map(Into::into) - .collect(), - lamport_version: transaction_effects_v1.lamport_version.into(), - changed_objects: transaction_effects_v1 - .changed_objects - .into_iter() - .map(|obj| { - (obj.object_id.into(), crate::effects::EffectsObjectChange { - input_state: match obj.change.input_state { - ObjectIn::NotExist => crate::effects::ObjectIn::NotExist, - ObjectIn::Exist { - version, - digest, - owner, - } => crate::effects::ObjectIn::Exist(( - (version.into(), digest.into()), - owner.into(), - )), - }, - output_state: match obj.change.output_state { - ObjectOut::NotExist => crate::effects::ObjectOut::NotExist, - ObjectOut::ObjectWrite { digest, owner } => { - crate::effects::ObjectOut::ObjectWrite(( - digest.into(), + let effects: crate::effects::TransactionEffects = + crate::effects::effects_v1::TransactionEffectsV1 { + status: transaction_effects_v1.status.into(), + executed_epoch: transaction_effects_v1.epoch, + gas_used: crate::gas::GasCostSummary::new( + transaction_effects_v1.gas_used.computation_cost, + transaction_effects_v1.gas_used.computation_cost_burned, + transaction_effects_v1.gas_used.storage_cost, + transaction_effects_v1.gas_used.storage_rebate, + transaction_effects_v1.gas_used.non_refundable_storage_fee, + ), + transaction_digest: transaction_effects_v1.transaction_digest.into(), + gas_object_index: transaction_effects_v1.gas_object_index, + events_digest: transaction_effects_v1.events_digest.map(Into::into), + dependencies: transaction_effects_v1 + .dependencies + .into_iter() + .map(Into::into) + .collect(), + lamport_version: transaction_effects_v1.lamport_version.into(), + changed_objects: transaction_effects_v1 + .changed_objects + .into_iter() + .map(|obj| { + (obj.object_id.into(), crate::effects::EffectsObjectChange { + input_state: match obj.change.input_state { + ObjectIn::NotExist => crate::effects::ObjectIn::NotExist, + ObjectIn::Exist { + version, + digest, + owner, + } => crate::effects::ObjectIn::Exist(( + (version.into(), digest.into()), owner.into(), - )) - } - ObjectOut::PackageWrite { version, digest } => { - crate::effects::ObjectOut::PackageWrite(( + )), + }, + output_state: match obj.change.output_state { + ObjectOut::NotExist => crate::effects::ObjectOut::NotExist, + ObjectOut::ObjectWrite { digest, owner } => { + crate::effects::ObjectOut::ObjectWrite(( + digest.into(), + owner.into(), + )) + } + ObjectOut::PackageWrite { version, digest } => { + crate::effects::ObjectOut::PackageWrite(( + version.into(), + digest.into(), + )) + } + }, + id_operation: match obj.change.id_operation { + IdOperation::None => crate::effects::IDOperation::None, + IdOperation::Created => { + crate::effects::IDOperation::Created + } + IdOperation::Deleted => { + crate::effects::IDOperation::Deleted + } + }, + }) + }) + .collect(), + unchanged_shared_objects: transaction_effects_v1 + .unchanged_shared_objects + .into_iter() + .map(|obj| { + (obj.object_id.into(), match obj.kind { + UnchangedSharedKind::ReadOnlyRoot { version, digest } => { + crate::effects::UnchangedSharedKind::ReadOnlyRoot(( version.into(), digest.into(), )) } - }, - id_operation: match obj.change.id_operation { - IdOperation::None => crate::effects::IDOperation::None, - IdOperation::Created => crate::effects::IDOperation::Created, - IdOperation::Deleted => crate::effects::IDOperation::Deleted, - }, - }) - }) - .collect(), - unchanged_shared_objects: transaction_effects_v1 - .unchanged_shared_objects - .into_iter() - .map(|obj| { - (obj.object_id.into(), match obj.kind { - UnchangedSharedKind::ReadOnlyRoot { version, digest } => { - crate::effects::UnchangedSharedKind::ReadOnlyRoot(( - version.into(), - digest.into(), - )) - } - UnchangedSharedKind::MutateDeleted { version } => { - crate::effects::UnchangedSharedKind::MutateDeleted( - version.into(), - ) - } - UnchangedSharedKind::ReadDeleted { version } => { - crate::effects::UnchangedSharedKind::ReadDeleted(version.into()) - } - UnchangedSharedKind::Cancelled { version } => { - crate::effects::UnchangedSharedKind::Cancelled(version.into()) - } - UnchangedSharedKind::PerEpochConfig => { - crate::effects::UnchangedSharedKind::PerEpochConfig - } + UnchangedSharedKind::MutateDeleted { version } => { + crate::effects::UnchangedSharedKind::MutateDeleted( + version.into(), + ) + } + UnchangedSharedKind::ReadDeleted { version } => { + crate::effects::UnchangedSharedKind::ReadDeleted( + version.into(), + ) + } + UnchangedSharedKind::Cancelled { version } => { + crate::effects::UnchangedSharedKind::Cancelled( + version.into(), + ) + } + UnchangedSharedKind::PerEpochConfig => { + crate::effects::UnchangedSharedKind::PerEpochConfig + } + }) }) - }) - .collect(), - aux_data_digest: transaction_effects_v1.auxiliary_data_digest.map(Into::into), - } - .into() + .collect(), + aux_data_digest: transaction_effects_v1 + .auxiliary_data_digest + .map(Into::into), + } + .into(); + + Ok(effects) } } } @@ -1319,23 +1423,40 @@ impl From for crate::execution_status::MoveLocation { } } -impl From for CheckpointContents { - fn from(value: crate::messages_checkpoint::CheckpointContents) -> Self { +impl TryFrom for CheckpointContents { + type Error = SdkTypeConversionError; + + fn try_from( + value: crate::messages_checkpoint::CheckpointContents, + ) -> Result { Self( value .into_iter_with_signatures() - .map(|(digests, signatures)| CheckpointTransactionInfo { - transaction: digests.transaction.into(), - effects: digests.effects.into(), - signatures: signatures.into_iter().map(Into::into).collect(), + .map(|(digests, signatures)| { + let signatures_result = signatures + .into_iter() + .map(TryInto::try_into) + .collect::, _>>(); + + match signatures_result { + Ok(signatures) => Ok(CheckpointTransactionInfo { + transaction: digests.transaction.into(), + effects: digests.effects.into(), + signatures, + }), + Err(e) => Err(SdkTypeConversionError::from(e)), + } }) - .collect(), + .collect::, _>>()?, ) + .pipe(Ok) } } -impl From for crate::messages_checkpoint::CheckpointContents { - fn from(value: CheckpointContents) -> Self { +impl TryFrom for crate::messages_checkpoint::CheckpointContents { + type Error = SdkTypeConversionError; + + fn try_from(value: CheckpointContents) -> Result { let (transactions, user_signatures) = value.0.into_iter().fold( (Vec::new(), Vec::new()), |(mut transactions, mut user_signatures), info| { @@ -1343,130 +1464,207 @@ impl From for crate::messages_checkpoint::CheckpointContents transaction: info.transaction.into(), effects: info.effects.into(), }); - user_signatures.push(info.signatures.into_iter().map(Into::into).collect()); + user_signatures.push( + info.signatures + .into_iter() + .map(TryInto::try_into) + .collect::>(), + ); (transactions, user_signatures) }, ); crate::messages_checkpoint::CheckpointContents::new_with_digests_and_signatures( transactions, - user_signatures, + user_signatures.into_iter().collect::, _>>()?, ) + .pipe(Ok) } } -impl From for CheckpointData { - fn from(value: crate::full_checkpoint_content::CheckpointData) -> Self { +impl TryFrom for CheckpointData { + type Error = SdkTypeConversionError; + + fn try_from( + value: crate::full_checkpoint_content::CheckpointData, + ) -> Result { Self { - checkpoint_summary: value.checkpoint_summary.into(), - checkpoint_contents: value.checkpoint_contents.into(), - transactions: value.transactions.into_iter().map(Into::into).collect(), + checkpoint_summary: value.checkpoint_summary.try_into()?, + checkpoint_contents: value.checkpoint_contents.try_into()?, + transactions: value + .transactions + .into_iter() + .map(TryInto::try_into) + .collect::>()?, } + .pipe(Ok) } } -impl From for crate::full_checkpoint_content::CheckpointData { - fn from(value: CheckpointData) -> Self { +impl TryFrom for crate::full_checkpoint_content::CheckpointData { + type Error = SdkTypeConversionError; + + fn try_from(value: CheckpointData) -> Result { Self { - checkpoint_summary: value.checkpoint_summary.into(), - checkpoint_contents: value.checkpoint_contents.into(), - transactions: value.transactions.into_iter().map(Into::into).collect(), + checkpoint_summary: value.checkpoint_summary.try_into()?, + checkpoint_contents: value.checkpoint_contents.try_into()?, + transactions: value + .transactions + .into_iter() + .map(TryInto::try_into) + .collect::>()?, } + .pipe(Ok) } } -impl From for CheckpointTransaction { - fn from(value: crate::full_checkpoint_content::CheckpointTransaction) -> Self { - Self { - transaction: value.transaction.into(), - effects: value.effects.into(), - events: value.events.map(Into::into), - input_objects: value.input_objects.into_iter().map(Into::into).collect(), - output_objects: value.output_objects.into_iter().map(Into::into).collect(), +impl TryFrom for CheckpointTransaction { + type Error = SdkTypeConversionError; + + fn try_from( + value: crate::full_checkpoint_content::CheckpointTransaction, + ) -> Result { + let input_objects = value + .input_objects + .into_iter() + .map(TryInto::try_into) + .collect::>(); + let output_objects = value + .output_objects + .into_iter() + .map(TryInto::try_into) + .collect::>(); + match (input_objects, output_objects) { + (Ok(input_objects), Ok(output_objects)) => Ok(Self { + transaction: value.transaction.try_into()?, + effects: value.effects.try_into()?, + events: value.events.map(TryInto::try_into).transpose()?, + input_objects, + output_objects, + }), + (Err(e), _) | (_, Err(e)) => Err(e), } } } -impl From for crate::full_checkpoint_content::CheckpointTransaction { - fn from(value: CheckpointTransaction) -> Self { - Self { - transaction: value.transaction.into(), - effects: value.effects.into(), - events: value.events.map(Into::into), - input_objects: value.input_objects.into_iter().map(Into::into).collect(), - output_objects: value.output_objects.into_iter().map(Into::into).collect(), +impl TryFrom for crate::full_checkpoint_content::CheckpointTransaction { + type Error = SdkTypeConversionError; + + fn try_from(value: CheckpointTransaction) -> Result { + let input_objects = value + .input_objects + .into_iter() + .map(TryInto::try_into) + .collect::>(); + let output_objects = value + .output_objects + .into_iter() + .map(TryInto::try_into) + .collect::>(); + + match (input_objects, output_objects) { + (Ok(input_objects), Ok(output_objects)) => Ok(Self { + transaction: value.transaction.try_into()?, + effects: value.effects.try_into()?, + events: value.events.map(TryInto::try_into).transpose()?, + input_objects, + output_objects, + }), + (Err(e), _) | (_, Err(e)) => Err(e), } } } -impl From for UserSignature { - fn from(value: crate::signature::GenericSignature) -> Self { - bcs::from_bytes(&bcs::to_bytes(&value).expect("invalid signature")) - .expect("invalid signature") +impl TryFrom for UserSignature { + type Error = bcs::Error; + + fn try_from(value: crate::signature::GenericSignature) -> Result { + bcs::from_bytes(&bcs::to_bytes(&value)?) } } -impl From for crate::signature::GenericSignature { - fn from(value: UserSignature) -> Self { - bcs::from_bytes(&bcs::to_bytes(&value).expect("invalid signature")) - .expect("invalid signature") +impl TryFrom for crate::signature::GenericSignature { + type Error = bcs::Error; + + fn try_from(value: UserSignature) -> Result { + bcs::from_bytes(&bcs::to_bytes(&value)?) } } -impl From for TransactionEvents { - fn from(value: crate::effects::TransactionEvents) -> Self { - Self(value.data.into_iter().map(Into::into).collect()) +impl TryFrom for TransactionEvents { + type Error = SdkTypeConversionError; + + fn try_from(value: crate::effects::TransactionEvents) -> Result { + Self( + value + .data + .into_iter() + .map(TryInto::try_into) + .collect::, _>>()?, + ) + .pipe(Ok) } } -impl From for crate::effects::TransactionEvents { - fn from(value: TransactionEvents) -> Self { +impl TryFrom for crate::effects::TransactionEvents { + type Error = SdkTypeConversionError; + + fn try_from(value: TransactionEvents) -> Result { Self { - data: value.0.into_iter().map(Into::into).collect(), + data: value + .0 + .into_iter() + .map(TryInto::try_into) + .collect::>()?, } + .pipe(Ok) } } -impl From for Event { - fn from(value: crate::event::Event) -> Self { +impl TryFrom for Event { + type Error = SdkTypeConversionError; + + fn try_from(value: crate::event::Event) -> Result { Self { package_id: value.package_id.into(), - module: Identifier::new(value.transaction_module.as_str()) - .expect("invalid event module identifier"), + module: Identifier::new(value.transaction_module.as_str())?, sender: value.sender.into(), - type_: struct_tag_core_to_sdk(value.type_), + type_: struct_tag_core_to_sdk(value.type_)?, contents: value.contents, } + .pipe(Ok) } } -impl From for crate::event::Event { - fn from(value: Event) -> Self { +impl TryFrom for crate::event::Event { + type Error = SdkTypeConversionError; + + fn try_from(value: Event) -> Result { Self { package_id: value.package_id.into(), - transaction_module: crate::Identifier::new(value.module.as_str()) - .expect("invalid event module identifier"), + transaction_module: crate::Identifier::new(value.module.as_str())?, sender: value.sender.into(), - type_: struct_tag_sdk_to_core(value.type_), + type_: struct_tag_sdk_to_core(value.type_)?, contents: value.contents, } + .pipe(Ok) } } -impl From for Command { - fn from(value: crate::transaction::Command) -> Self { +impl TryFrom for Command { + type Error = SdkTypeConversionError; + + fn try_from(value: crate::transaction::Command) -> Result { use crate::transaction::Command as InternalCmd; match value { InternalCmd::MoveCall(programmable_move_call) => Self::MoveCall(MoveCall { package: programmable_move_call.package.into(), - module: Identifier::new(programmable_move_call.module.as_str()) - .expect("invalid move call module identifier"), - function: Identifier::new(programmable_move_call.function.as_str()) - .expect("invalid move call function identifier"), + module: Identifier::new(programmable_move_call.module.as_str())?, + function: Identifier::new(programmable_move_call.function.as_str())?, type_arguments: programmable_move_call .type_arguments .into_iter() .map(type_tag_core_to_sdk) - .collect(), + .collect::>()?, arguments: programmable_move_call .arguments .into_iter() @@ -1492,7 +1690,7 @@ impl From for Command { dependencies: dependencies.into_iter().map(Into::into).collect(), }), InternalCmd::MakeMoveVec(type_tag, elements) => Self::MakeMoveVector(MakeMoveVector { - type_: type_tag.map(type_tag_core_to_sdk), + type_: type_tag.map(type_tag_core_to_sdk).transpose()?, elements: elements.into_iter().map(Into::into).collect(), }), InternalCmd::Upgrade(modules, dependencies, package, ticket) => { @@ -1504,11 +1702,14 @@ impl From for Command { }) } } + .pipe(Ok) } } -impl From for crate::transaction::Command { - fn from(value: Command) -> Self { +impl TryFrom for crate::transaction::Command { + type Error = SdkTypeConversionError; + + fn try_from(value: Command) -> Result { match value { Command::MoveCall(move_call) => { Self::MoveCall(Box::new(crate::transaction::ProgrammableMoveCall { @@ -1521,7 +1722,7 @@ impl From for crate::transaction::Command { .type_arguments .into_iter() .map(type_tag_sdk_to_core) - .collect(), + .collect::>()?, arguments: move_call.arguments.into_iter().map(Into::into).collect(), })) } @@ -1550,7 +1751,10 @@ impl From for crate::transaction::Command { publish.dependencies.into_iter().map(Into::into).collect(), ), Command::MakeMoveVector(make_move_vector) => Self::MakeMoveVec( - make_move_vector.type_.map(type_tag_sdk_to_core), + make_move_vector + .type_ + .map(type_tag_sdk_to_core) + .transpose()?, make_move_vector .elements .into_iter() @@ -1564,6 +1768,7 @@ impl From for crate::transaction::Command { upgrade.ticket.into(), ), } + .pipe(Ok) } } @@ -1675,8 +1880,10 @@ impl From for crate::messages_checkpoint::CheckpointCommit } } -impl From for CheckpointSummary { - fn from(value: crate::messages_checkpoint::CheckpointSummary) -> Self { +impl TryFrom for CheckpointSummary { + type Error = SdkTypeConversionError; + + fn try_from(value: crate::messages_checkpoint::CheckpointSummary) -> Result { Self { epoch: value.epoch, sequence_number: value.sequence_number, @@ -1693,11 +1900,14 @@ impl From for CheckpointSummary { end_of_epoch_data: value.end_of_epoch_data.map(Into::into), version_specific_data: value.version_specific_data, } + .pipe(Ok) } } -impl From for crate::messages_checkpoint::CheckpointSummary { - fn from(value: CheckpointSummary) -> Self { +impl TryFrom for crate::messages_checkpoint::CheckpointSummary { + type Error = SdkTypeConversionError; + + fn try_from(value: CheckpointSummary) -> Result { Self { epoch: value.epoch, sequence_number: value.sequence_number, @@ -1714,25 +1924,34 @@ impl From for crate::messages_checkpoint::CheckpointSummary { end_of_epoch_data: value.end_of_epoch_data.map(Into::into), version_specific_data: value.version_specific_data, } + .pipe(Ok) } } -impl From for SignedCheckpointSummary { - fn from(value: crate::messages_checkpoint::CertifiedCheckpointSummary) -> Self { +impl TryFrom for SignedCheckpointSummary { + type Error = SdkTypeConversionError; + + fn try_from( + value: crate::messages_checkpoint::CertifiedCheckpointSummary, + ) -> Result { let (data, sig) = value.into_data_and_sig(); Self { - checkpoint: data.into(), + checkpoint: data.try_into()?, signature: sig.into(), } + .pipe(Ok) } } -impl From for crate::messages_checkpoint::CertifiedCheckpointSummary { - fn from(value: SignedCheckpointSummary) -> Self { +impl TryFrom for crate::messages_checkpoint::CertifiedCheckpointSummary { + type Error = SdkTypeConversionError; + + fn try_from(value: SignedCheckpointSummary) -> Result { Self::new_from_data_and_sig( - crate::messages_checkpoint::CheckpointSummary::from(value.checkpoint), + crate::messages_checkpoint::CheckpointSummary::try_from(value.checkpoint)?, crate::crypto::AuthorityQuorumSignInfo::::from(value.signature), ) + .pipe(Ok) } } @@ -1835,47 +2054,65 @@ impl From for crate::base_types::IotaAddress { } } -impl From for SignedTransaction { - fn from(value: crate::transaction::SenderSignedData) -> Self { +impl TryFrom for SignedTransaction { + type Error = SdkTypeConversionError; + + fn try_from(value: crate::transaction::SenderSignedData) -> Result { let crate::transaction::SenderSignedTransaction { intent_message, tx_signatures, } = value.into_inner(); Self { - transaction: intent_message.value.into(), - signatures: tx_signatures.into_iter().map(Into::into).collect(), + transaction: intent_message.value.try_into()?, + signatures: tx_signatures + .into_iter() + .map(TryInto::try_into) + .collect::>()?, } + .pipe(Ok) } } -impl From for crate::transaction::SenderSignedData { - fn from(value: SignedTransaction) -> Self { +impl TryFrom for crate::transaction::SenderSignedData { + type Error = SdkTypeConversionError; + + fn try_from(value: SignedTransaction) -> Result { let SignedTransaction { transaction, signatures, } = value; Self::new( - transaction.into(), - signatures.into_iter().map(Into::into).collect(), + transaction.try_into()?, + signatures + .into_iter() + .map(TryInto::try_into) + .collect::>()?, ) + .pipe(Ok) } } -impl From for SignedTransaction { - fn from(value: crate::transaction::Transaction) -> Self { - value.into_data().into() +impl TryFrom for SignedTransaction { + type Error = SdkTypeConversionError; + + fn try_from(value: crate::transaction::Transaction) -> Result { + value.into_data().try_into() } } -impl From for crate::transaction::Transaction { - fn from(value: SignedTransaction) -> Self { - Self::new(value.into()) +impl TryFrom for crate::transaction::Transaction { + type Error = SdkTypeConversionError; + + fn try_from(value: SignedTransaction) -> Result { + Ok(Self::new(value.try_into()?)) } } -pub fn type_tag_core_to_sdk(value: move_core_types::language_storage::TypeTag) -> TypeTag { +pub fn type_tag_core_to_sdk( + value: move_core_types::language_storage::TypeTag, +) -> Result { match value { move_core_types::language_storage::TypeTag::Bool => TypeTag::Bool, move_core_types::language_storage::TypeTag::U8 => TypeTag::U8, @@ -1884,18 +2121,21 @@ pub fn type_tag_core_to_sdk(value: move_core_types::language_storage::TypeTag) - move_core_types::language_storage::TypeTag::Address => TypeTag::Address, move_core_types::language_storage::TypeTag::Signer => TypeTag::Signer, move_core_types::language_storage::TypeTag::Vector(type_tag) => { - TypeTag::Vector(Box::new(type_tag_core_to_sdk(*type_tag))) + TypeTag::Vector(Box::new(type_tag_core_to_sdk(*type_tag)?)) } move_core_types::language_storage::TypeTag::Struct(struct_tag) => { - TypeTag::Struct(Box::new(struct_tag_core_to_sdk(*struct_tag))) + TypeTag::Struct(Box::new(struct_tag_core_to_sdk(*struct_tag)?)) } move_core_types::language_storage::TypeTag::U16 => TypeTag::U16, move_core_types::language_storage::TypeTag::U32 => TypeTag::U32, move_core_types::language_storage::TypeTag::U256 => TypeTag::U256, } + .pipe(Ok) } -pub fn type_tag_sdk_to_core(value: TypeTag) -> move_core_types::language_storage::TypeTag { +pub fn type_tag_sdk_to_core( + value: TypeTag, +) -> Result { match value { TypeTag::Bool => move_core_types::language_storage::TypeTag::Bool, TypeTag::U8 => move_core_types::language_storage::TypeTag::U8, @@ -1904,18 +2144,21 @@ pub fn type_tag_sdk_to_core(value: TypeTag) -> move_core_types::language_storage TypeTag::Address => move_core_types::language_storage::TypeTag::Address, TypeTag::Signer => move_core_types::language_storage::TypeTag::Signer, TypeTag::Vector(type_tag) => move_core_types::language_storage::TypeTag::Vector(Box::new( - type_tag_sdk_to_core(*type_tag), + type_tag_sdk_to_core(*type_tag)?, )), TypeTag::Struct(struct_tag) => move_core_types::language_storage::TypeTag::Struct( - Box::new(struct_tag_sdk_to_core(*struct_tag)), + Box::new(struct_tag_sdk_to_core(*struct_tag)?), ), TypeTag::U16 => move_core_types::language_storage::TypeTag::U16, TypeTag::U32 => move_core_types::language_storage::TypeTag::U32, TypeTag::U256 => move_core_types::language_storage::TypeTag::U256, } + .pipe(Ok) } -pub fn struct_tag_core_to_sdk(value: move_core_types::language_storage::StructTag) -> StructTag { +pub fn struct_tag_core_to_sdk( + value: move_core_types::language_storage::StructTag, +) -> Result { let move_core_types::language_storage::StructTag { address, module, @@ -1924,18 +2167,24 @@ pub fn struct_tag_core_to_sdk(value: move_core_types::language_storage::StructTa } = value; let address = Address::new(address.into_bytes()); - let module = Identifier::new(module.as_str()).unwrap(); - let name = Identifier::new(name.as_str()).unwrap(); - let type_params = type_params.into_iter().map(type_tag_core_to_sdk).collect(); + let module = Identifier::new(module.as_str())?; + let name = Identifier::new(name.as_str())?; + let type_params = type_params + .into_iter() + .map(type_tag_core_to_sdk) + .collect::>()?; StructTag { address, module, name, type_params, } + .pipe(Ok) } -pub fn struct_tag_sdk_to_core(value: StructTag) -> move_core_types::language_storage::StructTag { +pub fn struct_tag_sdk_to_core( + value: StructTag, +) -> Result { let StructTag { address, module, @@ -1944,15 +2193,19 @@ pub fn struct_tag_sdk_to_core(value: StructTag) -> move_core_types::language_sto } = value; let address = move_core_types::account_address::AccountAddress::new(address.into_inner()); - let module = move_core_types::identifier::Identifier::new(module.into_inner()).unwrap(); - let name = move_core_types::identifier::Identifier::new(name.into_inner()).unwrap(); - let type_params = type_params.into_iter().map(type_tag_sdk_to_core).collect(); + let module = move_core_types::identifier::Identifier::new(module.into_inner())?; + let name = move_core_types::identifier::Identifier::new(name.into_inner())?; + let type_params = type_params + .into_iter() + .map(type_tag_sdk_to_core) + .collect::>()?; move_core_types::language_storage::StructTag { address, module, name, type_params, } + .pipe(Ok) } impl From for ValidatorCommittee {