diff --git a/bindings/core/src/method/client.rs b/bindings/core/src/method/client.rs index 20f12efe31..509aec0c54 100644 --- a/bindings/core/src/method/client.rs +++ b/bindings/core/src/method/client.rs @@ -16,8 +16,8 @@ use iota_sdk::{ types::block::{ address::{Bech32Address, Hrp}, output::{ - dto::OutputDto, feature::Feature, unlock_condition::dto::UnlockConditionDto, AccountId, AnchorId, - DelegationId, FoundryId, NftId, OutputId, TokenScheme, + feature::Feature, unlock_condition::dto::UnlockConditionDto, AccountId, AnchorId, DelegationId, FoundryId, + NftId, Output, OutputId, TokenScheme, }, payload::{dto::PayloadDto, signed_transaction::TransactionId}, BlockDto, BlockId, @@ -356,7 +356,7 @@ pub enum ClientMethod { /// Calculate the minimum required amount for an output. /// Expected response: /// [`OutputAmount`](crate::Response::OutputAmount) - ComputeMinimumOutputAmount { output: OutputDto }, + ComputeMinimumOutputAmount { output: Output }, /// Requests funds for a given address from the faucet, for example `https://faucet.testnet.shimmer.network/api/enqueue` or `http://localhost:8091/api/enqueue`. RequestFundsFromFaucet { /// Faucet URL diff --git a/bindings/core/src/method/utils.rs b/bindings/core/src/method/utils.rs index 245f33f691..1a4a1db599 100644 --- a/bindings/core/src/method/utils.rs +++ b/bindings/core/src/method/utils.rs @@ -6,7 +6,7 @@ use iota_sdk::{ client::secret::types::InputSigningDataDto, types::block::{ address::{Bech32Address, Hrp}, - output::{dto::OutputDto, AccountId, NftId, OutputId, StorageScoreParameters}, + output::{AccountId, NftId, Output, OutputId, StorageScoreParameters}, payload::signed_transaction::{ dto::{SignedTransactionPayloadDto, TransactionDto}, TransactionId, @@ -134,7 +134,7 @@ pub enum UtilsMethod { /// Computes the minimum required amount of an output. #[serde(rename_all = "camelCase")] ComputeMinimumOutputAmount { - output: OutputDto, + output: Output, storage_score_parameters: StorageScoreParameters, }, /// Checks if the given mnemonic is valid. @@ -163,7 +163,7 @@ pub enum UtilsMethod { ComputeSlotCommitmentId { slot_commitment: SlotCommitment }, /// Returns the hex representation of the serialized output bytes. #[serde(rename_all = "camelCase")] - OutputHexBytes { output: OutputDto }, + OutputHexBytes { output: Output }, /// Verifies the semantic of a transaction. VerifyTransactionSemantic { inputs: Vec, diff --git a/bindings/core/src/method/wallet.rs b/bindings/core/src/method/wallet.rs index 8c0170286f..5d36fc79eb 100644 --- a/bindings/core/src/method/wallet.rs +++ b/bindings/core/src/method/wallet.rs @@ -21,7 +21,7 @@ use iota_sdk::{ }, types::block::{ address::{Bech32Address, Hrp}, - output::{dto::OutputDto, OutputId, TokenId}, + output::{Output, OutputId, TokenId}, payload::signed_transaction::TransactionId, }, wallet::{ @@ -321,7 +321,7 @@ pub enum WalletMethod { /// Prepare transaction. /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) PrepareTransaction { - outputs: Vec, + outputs: Vec, options: Option, }, /// Vote for a participation event. @@ -371,7 +371,7 @@ pub enum WalletMethod { /// Send outputs in a transaction. /// Expected response: [`SentTransaction`](crate::Response::SentTransaction) SendOutputs { - outputs: Vec, + outputs: Vec, options: Option, }, /// Set the alias of the wallet. diff --git a/bindings/core/src/method_handler/client.rs b/bindings/core/src/method_handler/client.rs index cb9a955938..028bc06079 100644 --- a/bindings/core/src/method_handler/client.rs +++ b/bindings/core/src/method_handler/client.rs @@ -9,8 +9,7 @@ use iota_sdk::{ api::core::OutputWithMetadataResponse, block::{ output::{ - dto::OutputDto, AccountOutput, BasicOutput, FoundryOutput, MinimumOutputAmount, NftOutput, Output, - OutputBuilderAmount, + AccountOutput, BasicOutput, FoundryOutput, MinimumOutputAmount, NftOutput, Output, OutputBuilderAmount, }, payload::Payload, Block, BlockDto, UnsignedBlockDto, @@ -79,7 +78,7 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM immutable_features, )?); - Response::Output(OutputDto::from(&output)) + Response::Output(output) } ClientMethod::BuildBasicOutput { amount, @@ -98,7 +97,7 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM features, )?); - Response::Output(OutputDto::from(&output)) + Response::Output(output) } ClientMethod::BuildFoundryOutput { amount, @@ -121,7 +120,7 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM immutable_features, )?); - Response::Output(OutputDto::from(&output)) + Response::Output(output) } ClientMethod::BuildNftOutput { amount, @@ -144,7 +143,7 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM immutable_features, )?); - Response::Output(OutputDto::from(&output)) + Response::Output(output) } ClientMethod::BuildBasicBlock { issuer_id, payload } => { let payload = if let Some(payload) = payload { @@ -285,7 +284,6 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM Response::Bech32Address(client.hex_public_key_to_bech32_address(&hex, bech32_hrp).await?) } ClientMethod::ComputeMinimumOutputAmount { output } => { - let output = Output::try_from(output)?; let storage_score_params = client.get_storage_score_parameters().await?; Response::OutputAmount(output.minimum_amount(storage_score_params)) diff --git a/bindings/core/src/method_handler/utils.rs b/bindings/core/src/method_handler/utils.rs index 96a37495ca..f10f56065c 100644 --- a/bindings/core/src/method_handler/utils.rs +++ b/bindings/core/src/method_handler/utils.rs @@ -11,7 +11,7 @@ use iota_sdk::{ block::{ address::{AccountAddress, Address, ToBech32Ext}, input::UtxoInput, - output::{AccountId, FoundryId, MinimumOutputAmount, NftId, Output, OutputId, TokenId}, + output::{AccountId, FoundryId, MinimumOutputAmount, NftId, OutputId, TokenId}, payload::{signed_transaction::Transaction, SignedTransactionPayload}, Block, }, @@ -78,10 +78,7 @@ pub(crate) fn call_utils_method_internal(method: UtilsMethod) -> Result { - let out = Output::try_from(output)?; - Response::OutputAmount(out.minimum_amount(storage_params)) - } + } => Response::OutputAmount(output.minimum_amount(storage_params)), UtilsMethod::VerifyMnemonic { mnemonic } => { let mnemonic = Mnemonic::from(mnemonic); verify_mnemonic(mnemonic)?; @@ -107,10 +104,7 @@ pub(crate) fn call_utils_method_internal(method: UtilsMethod) -> Result Response::Input(UtxoInput::from(output_id)), UtilsMethod::ComputeSlotCommitmentId { slot_commitment } => Response::SlotCommitmentId(slot_commitment.id()), - UtilsMethod::OutputHexBytes { output } => { - let output = Output::try_from(output)?; - Response::HexBytes(prefix_hex::encode(output.pack_to_vec())) - } + UtilsMethod::OutputHexBytes { output } => Response::HexBytes(prefix_hex::encode(output.pack_to_vec())), UtilsMethod::VerifyTransactionSemantic { inputs, transaction } => { let conflict = verify_semantic( &inputs diff --git a/bindings/core/src/method_handler/wallet.rs b/bindings/core/src/method_handler/wallet.rs index 9367a5228f..ffdb7b9331 100644 --- a/bindings/core/src/method_handler/wallet.rs +++ b/bindings/core/src/method_handler/wallet.rs @@ -7,13 +7,7 @@ use iota_sdk::{ client::api::{ PreparedTransactionData, PreparedTransactionDataDto, SignedTransactionData, SignedTransactionDataDto, }, - types::{ - block::{ - address::ToBech32Ext, - output::{dto::OutputDto, Output}, - }, - TryFromDto, - }, + types::{block::address::ToBech32Ext, TryFromDto}, wallet::{types::TransactionWithMetadataDto, OutputDataDto, PreparedCreateNativeTokenTransactionDto, Wallet}, }; @@ -158,7 +152,7 @@ pub(crate) async fn call_wallet_method_internal(wallet: &Wallet, method: WalletM WalletMethod::GetBalance => Response::Balance(wallet.balance().await?), WalletMethod::GetFoundryOutput { token_id } => { let output = wallet.get_foundry_output(token_id).await?; - Response::Output(OutputDto::from(&output)) + Response::Output(output) } WalletMethod::GetIncomingTransaction { transaction_id } => { let transaction = wallet.get_incoming_transaction(&transaction_id).await; @@ -285,7 +279,7 @@ pub(crate) async fn call_wallet_method_internal(wallet: &Wallet, method: WalletM transaction_options, } => { let output = wallet.prepare_output(*params, transaction_options).await?; - Response::Output(OutputDto::from(&output)) + Response::Output(output) } WalletMethod::PrepareSend { params, options } => { let data = wallet.prepare_send(params, options).await?; @@ -305,15 +299,7 @@ pub(crate) async fn call_wallet_method_internal(wallet: &Wallet, method: WalletM Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) } WalletMethod::PrepareTransaction { outputs, options } => { - let data = wallet - .prepare_transaction( - outputs - .into_iter() - .map(Output::try_from) - .collect::, _>>()?, - options, - ) - .await?; + let data = wallet.prepare_transaction(outputs, options).await?; Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) } #[cfg(feature = "participation")] @@ -349,15 +335,7 @@ pub(crate) async fn call_wallet_method_internal(wallet: &Wallet, method: WalletM Response::SentTransaction(TransactionWithMetadataDto::from(&transaction)) } WalletMethod::SendOutputs { outputs, options } => { - let transaction = wallet - .send_outputs( - outputs - .into_iter() - .map(Output::try_from) - .collect::, _>>()?, - options, - ) - .await?; + let transaction = wallet.send_outputs(outputs, options).await?; Response::SentTransaction(TransactionWithMetadataDto::from(&transaction)) } WalletMethod::SetAlias { alias } => { diff --git a/bindings/core/src/response.rs b/bindings/core/src/response.rs index 03df850853..1b5d92f9fe 100644 --- a/bindings/core/src/response.rs +++ b/bindings/core/src/response.rs @@ -24,7 +24,7 @@ use iota_sdk::{ block::{ address::{Address, Bech32Address, Hrp}, input::UtxoInput, - output::{dto::OutputDto, AccountId, FoundryId, NftId, OutputId, OutputMetadata, TokenId}, + output::{AccountId, FoundryId, NftId, Output, OutputId, OutputMetadata, TokenId}, payload::{dto::SignedTransactionPayloadDto, signed_transaction::TransactionId}, protocol::ProtocolParameters, semantic::TransactionFailureReason, @@ -206,7 +206,7 @@ pub enum Response { /// - [`BuildNftOutput`](crate::method::ClientMethod::BuildNftOutput) /// - [`GetFoundryOutput`](crate::method::WalletMethod::GetFoundryOutput) /// - [`PrepareOutput`](crate::method::WalletMethod::PrepareOutput) - Output(OutputDto), + Output(Output), /// Response for: /// - [`AccountIdToBech32`](crate::method::ClientMethod::AccountIdToBech32) /// - [`HexPublicKeyToBech32Address`](crate::method::ClientMethod::HexPublicKeyToBech32Address) diff --git a/sdk/examples/how_tos/outputs/features.rs b/sdk/examples/how_tos/outputs/features.rs index a8689592cc..ca51095bb4 100644 --- a/sdk/examples/how_tos/outputs/features.rs +++ b/sdk/examples/how_tos/outputs/features.rs @@ -13,7 +13,6 @@ use iota_sdk::{ types::block::{ address::Address, output::{ - dto::OutputDto, feature::{IssuerFeature, MetadataFeature, SenderFeature, TagFeature}, unlock_condition::AddressUnlockCondition, NftId, NftOutputBuilder, @@ -66,7 +65,7 @@ async fn main() -> Result<()> { ]; // Convert output array to json array - let json_outputs = serde_json::to_string_pretty(&outputs.iter().map(OutputDto::from).collect::>())?; + let json_outputs = serde_json::to_string_pretty(&outputs)?; println!("{json_outputs}"); Ok(()) diff --git a/sdk/examples/how_tos/outputs/unlock_conditions.rs b/sdk/examples/how_tos/outputs/unlock_conditions.rs index 8ebba721ed..0683de7f86 100644 --- a/sdk/examples/how_tos/outputs/unlock_conditions.rs +++ b/sdk/examples/how_tos/outputs/unlock_conditions.rs @@ -13,7 +13,6 @@ use iota_sdk::{ types::block::{ address::Address, output::{ - dto::OutputDto, unlock_condition::{ AddressUnlockCondition, ExpirationUnlockCondition, ImmutableAccountAddressUnlockCondition, StorageDepositReturnUnlockCondition, TimelockUnlockCondition, @@ -70,7 +69,7 @@ async fn main() -> Result<()> { ]; // Convert output array to json array - let json_outputs = serde_json::to_string_pretty(&outputs.iter().map(OutputDto::from).collect::>())?; + let json_outputs = serde_json::to_string_pretty(&outputs)?; println!("{json_outputs}"); Ok(()) diff --git a/sdk/src/client/api/types.rs b/sdk/src/client/api/types.rs index 6df3cb6b2d..1c251175bf 100644 --- a/sdk/src/client/api/types.rs +++ b/sdk/src/client/api/types.rs @@ -9,7 +9,7 @@ use crate::{ types::{ block::{ address::Address, - output::{dto::OutputDto, Output}, + output::Output, payload::{ signed_transaction::{ dto::{SignedTransactionPayloadDto, TransactionDto}, @@ -147,7 +147,7 @@ pub struct RemainderData { #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] pub struct RemainderDataDto { /// The remainder output - pub output: OutputDto, + pub output: Output, /// The chain derived from seed, for the remainder addresses #[serde(with = "option_bip44", default)] pub chain: Option, @@ -160,7 +160,7 @@ impl TryFrom for RemainderData { fn try_from(dto: RemainderDataDto) -> Result { Ok(Self { - output: Output::try_from(dto.output)?, + output: dto.output, chain: dto.chain, address: dto.address, }) @@ -169,7 +169,7 @@ impl TryFrom for RemainderData { impl From<&RemainderData> for RemainderDataDto { fn from(remainder: &RemainderData) -> Self { Self { - output: OutputDto::from(&remainder.output), + output: remainder.output.clone(), chain: remainder.chain, address: remainder.address.clone(), } diff --git a/sdk/src/client/node_api/core/routes.rs b/sdk/src/client/node_api/core/routes.rs index 06916d35a9..aace690693 100644 --- a/sdk/src/client/node_api/core/routes.rs +++ b/sdk/src/client/node_api/core/routes.rs @@ -22,7 +22,7 @@ use crate::{ }, block::{ address::ToBech32Ext, - output::{dto::OutputDto, AccountId, Output, OutputId, OutputMetadata}, + output::{AccountId, Output, OutputId, OutputMetadata}, payload::signed_transaction::TransactionId, slot::{EpochIndex, SlotCommitment, SlotCommitmentId, SlotIndex}, Block, BlockDto, BlockId, @@ -237,9 +237,7 @@ impl ClientInner { pub async fn get_output(&self, output_id: &OutputId) -> Result { let path = &format!("api/core/v3/outputs/{output_id}"); - Ok(Output::try_from( - self.get_request::(path, None, false, true).await?, - )?) + self.get_request(path, None, false, true).await } /// Finds an output by its ID and returns it as raw bytes. diff --git a/sdk/src/client/secret/types.rs b/sdk/src/client/secret/types.rs index 352869b3ab..4fee1c4ce4 100644 --- a/sdk/src/client/secret/types.rs +++ b/sdk/src/client/secret/types.rs @@ -7,7 +7,7 @@ use crypto::keys::bip44::Bip44; use serde::{Deserialize, Serialize}; use crate::{ - types::block::output::{dto::OutputDto, Output, OutputId, OutputMetadata}, + types::block::output::{Output, OutputId, OutputMetadata}, utils::serde::bip44::option_bip44, }; @@ -156,7 +156,7 @@ impl InputSigningData { #[serde(rename_all = "camelCase")] pub struct InputSigningDataDto { /// The output - pub output: OutputDto, + pub output: Output, /// The output metadata pub output_metadata: OutputMetadata, /// The chain derived from seed, only for ed25519 addresses @@ -169,7 +169,7 @@ impl TryFrom for InputSigningData { fn try_from(dto: InputSigningDataDto) -> Result { Ok(Self { - output: Output::try_from(dto.output)?, + output: dto.output, output_metadata: dto.output_metadata, chain: dto.chain, }) @@ -179,7 +179,7 @@ impl TryFrom for InputSigningData { impl From<&InputSigningData> for InputSigningDataDto { fn from(input: &InputSigningData) -> Self { Self { - output: OutputDto::from(&input.output), + output: input.output.clone(), output_metadata: input.output_metadata, chain: input.chain, } diff --git a/sdk/src/types/api/core.rs b/sdk/src/types/api/core.rs index e2c6c0af24..25ec2548a7 100644 --- a/sdk/src/types/api/core.rs +++ b/sdk/src/types/api/core.rs @@ -14,7 +14,7 @@ use crate::{ types::block::{ address::Bech32Address, core::Parents, - output::{dto::OutputDto, OutputId, OutputMetadata, OutputWithMetadata}, + output::{Output, OutputId, OutputMetadata, OutputWithMetadata}, protocol::{ProtocolParameters, ProtocolParametersHash}, semantic::TransactionFailureReason, slot::{EpochIndex, SlotCommitment, SlotCommitmentId, SlotIndex}, @@ -418,14 +418,14 @@ pub struct BlockWithMetadataResponse { #[serde(rename_all = "camelCase")] pub struct OutputWithMetadataResponse { pub metadata: OutputMetadata, - pub output: OutputDto, + pub output: Output, } impl From<&OutputWithMetadata> for OutputWithMetadataResponse { fn from(value: &OutputWithMetadata) -> Self { Self { metadata: value.metadata, - output: OutputDto::from(value.output()), + output: value.output().clone(), } } } diff --git a/sdk/src/types/block/output/account.rs b/sdk/src/types/block/output/account.rs index b3219008d3..1513952096 100644 --- a/sdk/src/types/block/output/account.rs +++ b/sdk/src/types/block/output/account.rs @@ -617,7 +617,7 @@ pub(crate) mod dto { /// Describes an account in the ledger that can be controlled by the state and governance controllers. #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] - pub struct AccountOutputDto { + pub(crate) struct AccountOutputDto { #[serde(rename = "type")] pub kind: u8, #[serde(with = "string")] @@ -706,6 +706,8 @@ pub(crate) mod dto { builder.finish() } } + + crate::impl_serde_typed_dto!(AccountOutput, AccountOutputDto, "account output"); } #[cfg(test)] @@ -714,7 +716,7 @@ mod tests { use super::*; use crate::types::block::{ - output::dto::OutputDto, + output::account::dto::AccountOutputDto, protocol::protocol_parameters, rand::output::{ feature::rand_allowed_features, rand_account_id, rand_account_output, @@ -725,24 +727,22 @@ mod tests { #[test] fn to_from_dto() { let protocol_parameters = protocol_parameters(); - let output = rand_account_output(protocol_parameters.token_supply()); - let dto = OutputDto::Account((&output).into()); - let output_unver = Output::try_from(dto.clone()).unwrap(); - assert_eq!(&output, output_unver.as_account()); - let output_ver = Output::try_from(dto).unwrap(); - assert_eq!(&output, output_ver.as_account()); + let account_output = rand_account_output(protocol_parameters.token_supply()); + let dto = AccountOutputDto::from(&account_output); + let output = Output::Account(AccountOutput::try_from(dto).unwrap()); + assert_eq!(&account_output, output.as_account()); let output_split = AccountOutput::try_from_dtos( - OutputBuilderAmount::Amount(output.amount()), - output.mana(), - output.account_id(), - output.foundry_counter().into(), - output.unlock_conditions().iter().map(Into::into).collect(), - Some(output.features().to_vec()), - Some(output.immutable_features().to_vec()), + OutputBuilderAmount::Amount(account_output.amount()), + account_output.mana(), + account_output.account_id(), + account_output.foundry_counter().into(), + account_output.unlock_conditions().iter().map(Into::into).collect(), + Some(account_output.features().to_vec()), + Some(account_output.immutable_features().to_vec()), ) .unwrap(); - assert_eq!(output, output_split); + assert_eq!(account_output, output_split); let account_id = rand_account_id(); let address = rand_address_unlock_condition_different_from_account_id(&account_id); diff --git a/sdk/src/types/block/output/anchor.rs b/sdk/src/types/block/output/anchor.rs index ae5608035a..d3e821a991 100644 --- a/sdk/src/types/block/output/anchor.rs +++ b/sdk/src/types/block/output/anchor.rs @@ -665,7 +665,7 @@ pub(crate) mod dto { /// Describes an anchor in the ledger that can be controlled by the state and governance controllers. #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] - pub struct AnchorOutputDto { + pub(crate) struct AnchorOutputDto { #[serde(rename = "type")] pub kind: u8, #[serde(with = "string")] @@ -751,13 +751,15 @@ pub(crate) mod dto { builder.finish() } } + + crate::impl_serde_typed_dto!(AnchorOutput, AnchorOutputDto, "anchor output"); } #[cfg(test)] mod tests { use super::*; use crate::types::block::{ - output::dto::OutputDto, + output::anchor::dto::AnchorOutputDto, protocol::protocol_parameters, rand::output::{ feature::rand_allowed_features, @@ -772,24 +774,22 @@ mod tests { #[test] fn to_from_dto() { let protocol_parameters = protocol_parameters(); - let output = rand_anchor_output(protocol_parameters.token_supply()); - let dto = OutputDto::Anchor((&output).into()); - let output_unver = Output::try_from(dto.clone()).unwrap(); - assert_eq!(&output, output_unver.as_anchor()); - let output_ver = Output::try_from(dto).unwrap(); - assert_eq!(&output, output_ver.as_anchor()); + let anchor_output = rand_anchor_output(protocol_parameters.token_supply()); + let dto = AnchorOutputDto::from(&anchor_output); + let output = Output::Anchor(AnchorOutput::try_from(dto).unwrap()); + assert_eq!(&anchor_output, output.as_anchor()); let output_split = AnchorOutput::try_from_dtos( OutputBuilderAmount::Amount(output.amount()), - output.mana(), - output.anchor_id(), - output.state_index(), - output.unlock_conditions().iter().map(Into::into).collect(), - Some(output.features().to_vec()), - Some(output.immutable_features().to_vec()), + anchor_output.mana(), + anchor_output.anchor_id(), + anchor_output.state_index(), + anchor_output.unlock_conditions().iter().map(Into::into).collect(), + Some(anchor_output.features().to_vec()), + Some(anchor_output.immutable_features().to_vec()), ) .unwrap(); - assert_eq!(output, output_split); + assert_eq!(anchor_output, output_split); let anchor_id = rand_anchor_id(); let gov_address = rand_governor_address_unlock_condition_different_from(&anchor_id); diff --git a/sdk/src/types/block/output/basic.rs b/sdk/src/types/block/output/basic.rs index 24c5083673..4393c90b35 100644 --- a/sdk/src/types/block/output/basic.rs +++ b/sdk/src/types/block/output/basic.rs @@ -421,7 +421,7 @@ pub(crate) mod dto { #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] - pub struct BasicOutputDto { + pub(crate) struct BasicOutputDto { #[serde(rename = "type")] pub kind: u8, #[serde(with = "string")] @@ -487,6 +487,8 @@ pub(crate) mod dto { builder.finish() } } + + crate::impl_serde_typed_dto!(BasicOutput, BasicOutputDto, "basic output"); } #[cfg(test)] @@ -495,7 +497,7 @@ mod tests { use super::*; use crate::types::block::{ - output::{dto::OutputDto, FoundryId, SimpleTokenScheme, TokenId}, + output::{basic::dto::BasicOutputDto, FoundryId, SimpleTokenScheme, TokenId}, protocol::protocol_parameters, rand::{ address::rand_account_address, @@ -508,21 +510,19 @@ mod tests { #[test] fn to_from_dto() { let protocol_parameters = protocol_parameters(); - let output = rand_basic_output(protocol_parameters.token_supply()); - let dto = OutputDto::Basic((&output).into()); - let output_unver = Output::try_from(dto.clone()).unwrap(); - assert_eq!(&output, output_unver.as_basic()); - let output_ver = Output::try_from(dto).unwrap(); - assert_eq!(&output, output_ver.as_basic()); + let basic_output = rand_basic_output(protocol_parameters.token_supply()); + let dto = BasicOutputDto::from(&basic_output); + let output = Output::Basic(BasicOutput::try_from(dto).unwrap()); + assert_eq!(&basic_output, output.as_basic()); let output_split = BasicOutput::try_from_dtos( - OutputBuilderAmount::Amount(output.amount()), - output.mana(), - output.unlock_conditions().iter().map(Into::into).collect(), - Some(output.features().to_vec()), + OutputBuilderAmount::Amount(basic_output.amount()), + basic_output.mana(), + basic_output.unlock_conditions().iter().map(Into::into).collect(), + Some(basic_output.features().to_vec()), ) .unwrap(); - assert_eq!(output, output_split); + assert_eq!(basic_output, output_split); let foundry_id = FoundryId::build(&rand_account_address(), 0, SimpleTokenScheme::KIND); let address = rand_address_unlock_condition(); diff --git a/sdk/src/types/block/output/delegation.rs b/sdk/src/types/block/output/delegation.rs index 61bdb1464a..d55c7dd704 100644 --- a/sdk/src/types/block/output/delegation.rs +++ b/sdk/src/types/block/output/delegation.rs @@ -433,7 +433,7 @@ fn verify_unlock_conditions_packable( } #[cfg(feature = "serde")] -pub(crate) mod dto { +mod dto { use alloc::vec::Vec; use serde::{Deserialize, Serialize}; @@ -449,7 +449,7 @@ pub(crate) mod dto { #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] - pub struct DelegationOutputDto { + struct DelegationOutputDto { #[serde(rename = "type")] pub kind: u8, #[serde(with = "string")] @@ -536,4 +536,6 @@ pub(crate) mod dto { builder.finish() } } + + crate::impl_serde_typed_dto!(DelegationOutput, DelegationOutputDto, "delegation output"); } diff --git a/sdk/src/types/block/output/foundry.rs b/sdk/src/types/block/output/foundry.rs index ea3c61ea57..6178529398 100644 --- a/sdk/src/types/block/output/foundry.rs +++ b/sdk/src/types/block/output/foundry.rs @@ -673,7 +673,7 @@ pub(crate) mod dto { #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] - pub struct FoundryOutputDto { + pub(crate) struct FoundryOutputDto { #[serde(rename = "type")] pub kind: u8, #[serde(with = "string")] @@ -760,6 +760,8 @@ pub(crate) mod dto { builder.finish() } } + + crate::impl_serde_typed_dto!(FoundryOutput, FoundryOutputDto, "foundry output"); } #[cfg(test)] @@ -769,8 +771,8 @@ mod tests { use super::*; use crate::types::block::{ output::{ - dto::OutputDto, unlock_condition::ImmutableAccountAddressUnlockCondition, FoundryId, SimpleTokenScheme, - TokenId, + foundry::dto::FoundryOutputDto, unlock_condition::ImmutableAccountAddressUnlockCondition, FoundryId, + SimpleTokenScheme, TokenId, }, protocol::protocol_parameters, rand::{ @@ -785,12 +787,10 @@ mod tests { #[test] fn to_from_dto() { let protocol_parameters = protocol_parameters(); - let output = rand_foundry_output(protocol_parameters.token_supply()); - let dto = OutputDto::Foundry((&output).into()); - let output_unver = Output::try_from(dto.clone()).unwrap(); - assert_eq!(&output, output_unver.as_foundry()); - let output_ver = Output::try_from(dto).unwrap(); - assert_eq!(&output, output_ver.as_foundry()); + let foundry_output = rand_foundry_output(protocol_parameters.token_supply()); + let dto = FoundryOutputDto::from(&foundry_output); + let output = Output::Foundry(FoundryOutput::try_from(dto).unwrap()); + assert_eq!(&foundry_output, output.as_foundry()); let foundry_id = FoundryId::build(&rand_account_address(), 0, SimpleTokenScheme::KIND); diff --git a/sdk/src/types/block/output/mod.rs b/sdk/src/types/block/output/mod.rs index 7249ba2393..7c6520f248 100644 --- a/sdk/src/types/block/output/mod.rs +++ b/sdk/src/types/block/output/mod.rs @@ -111,6 +111,7 @@ impl OutputWithMetadata { /// A generic output that can represent different types defining the deposit of funds. #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, From, Packable)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize), serde(untagged))] #[packable(unpack_error = Error)] #[packable(unpack_visitor = ProtocolParameters)] #[packable(tag_type = u8, with_error = Error::InvalidOutputKind)] @@ -434,140 +435,3 @@ pub trait MinimumOutputAmount: StorageScore { self.storage_score(params) * params.storage_cost() } } - -#[cfg(feature = "serde")] -pub mod dto { - use alloc::format; - - use serde::{Deserialize, Serialize, Serializer}; - use serde_json::Value; - - use super::*; - pub use super::{ - account::dto::AccountOutputDto, anchor::dto::AnchorOutputDto, basic::dto::BasicOutputDto, - delegation::dto::DelegationOutputDto, foundry::dto::FoundryOutputDto, nft::dto::NftOutputDto, - }; - - /// Describes all the different output types. - #[derive(Clone, Debug, Eq, PartialEq, From)] - pub enum OutputDto { - Basic(BasicOutputDto), - Account(AccountOutputDto), - Anchor(AnchorOutputDto), - Foundry(FoundryOutputDto), - Nft(NftOutputDto), - Delegation(DelegationOutputDto), - } - - impl From<&Output> for OutputDto { - fn from(value: &Output) -> Self { - match value { - Output::Basic(o) => Self::Basic(o.into()), - Output::Account(o) => Self::Account(o.into()), - Output::Anchor(o) => Self::Anchor(o.into()), - Output::Foundry(o) => Self::Foundry(o.into()), - Output::Nft(o) => Self::Nft(o.into()), - Output::Delegation(o) => Self::Delegation(o.into()), - } - } - } - - impl TryFrom for Output { - type Error = Error; - - fn try_from(dto: OutputDto) -> Result { - Ok(match dto { - OutputDto::Basic(o) => Self::Basic(BasicOutput::try_from(o)?), - OutputDto::Account(o) => Self::Account(AccountOutput::try_from(o)?), - OutputDto::Anchor(o) => Self::Anchor(AnchorOutput::try_from(o)?), - OutputDto::Foundry(o) => Self::Foundry(FoundryOutput::try_from(o)?), - OutputDto::Nft(o) => Self::Nft(NftOutput::try_from(o)?), - OutputDto::Delegation(o) => Self::Delegation(DelegationOutput::try_from(o)?), - }) - } - } - - impl<'de> Deserialize<'de> for OutputDto { - fn deserialize>(d: D) -> Result { - let value = Value::deserialize(d)?; - Ok( - match value - .get("type") - .and_then(Value::as_u64) - .ok_or_else(|| serde::de::Error::custom("invalid output type"))? as u8 - { - BasicOutput::KIND => Self::Basic( - BasicOutputDto::deserialize(value) - .map_err(|e| serde::de::Error::custom(format!("cannot deserialize basic output: {e}")))?, - ), - AccountOutput::KIND => Self::Account( - AccountOutputDto::deserialize(value) - .map_err(|e| serde::de::Error::custom(format!("cannot deserialize account output: {e}")))?, - ), - AnchorOutput::KIND => Self::Anchor( - AnchorOutputDto::deserialize(value) - .map_err(|e| serde::de::Error::custom(format!("cannot deserialize anchor output: {e}")))?, - ), - FoundryOutput::KIND => Self::Foundry( - FoundryOutputDto::deserialize(value) - .map_err(|e| serde::de::Error::custom(format!("cannot deserialize foundry output: {e}")))?, - ), - NftOutput::KIND => Self::Nft( - NftOutputDto::deserialize(value) - .map_err(|e| serde::de::Error::custom(format!("cannot deserialize NFT output: {e}")))?, - ), - DelegationOutput::KIND => { - Self::Delegation(DelegationOutputDto::deserialize(value).map_err(|e| { - serde::de::Error::custom(format!("cannot deserialize delegation output: {e}")) - })?) - } - _ => return Err(serde::de::Error::custom("invalid output type")), - }, - ) - } - } - - impl Serialize for OutputDto { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - #[derive(Serialize)] - #[serde(untagged)] - enum OutputDto_<'a> { - T0(&'a BasicOutputDto), - T1(&'a AccountOutputDto), - T2(&'a AnchorOutputDto), - T3(&'a FoundryOutputDto), - T4(&'a NftOutputDto), - T5(&'a DelegationOutputDto), - } - #[derive(Serialize)] - struct TypedOutput<'a> { - #[serde(flatten)] - output: OutputDto_<'a>, - } - let output = match self { - Self::Basic(o) => TypedOutput { - output: OutputDto_::T0(o), - }, - Self::Account(o) => TypedOutput { - output: OutputDto_::T1(o), - }, - Self::Anchor(o) => TypedOutput { - output: OutputDto_::T2(o), - }, - Self::Foundry(o) => TypedOutput { - output: OutputDto_::T3(o), - }, - Self::Nft(o) => TypedOutput { - output: OutputDto_::T4(o), - }, - Self::Delegation(o) => TypedOutput { - output: OutputDto_::T5(o), - }, - }; - output.serialize(serializer) - } - } -} diff --git a/sdk/src/types/block/output/nft.rs b/sdk/src/types/block/output/nft.rs index 29760875f8..d4f9dd2919 100644 --- a/sdk/src/types/block/output/nft.rs +++ b/sdk/src/types/block/output/nft.rs @@ -578,7 +578,7 @@ pub(crate) mod dto { #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] - pub struct NftOutputDto { + pub(crate) struct NftOutputDto { #[serde(rename = "type")] pub kind: u8, #[serde(with = "string")] @@ -659,6 +659,8 @@ pub(crate) mod dto { builder.finish() } } + + crate::impl_serde_typed_dto!(NftOutput, NftOutputDto, "nft output"); } #[cfg(test)] @@ -667,7 +669,7 @@ mod tests { use super::*; use crate::types::block::{ - output::dto::OutputDto, + output::nft::dto::NftOutputDto, protocol::protocol_parameters, rand::output::{ feature::rand_allowed_features, rand_nft_output, unlock_condition::rand_address_unlock_condition, @@ -677,23 +679,21 @@ mod tests { #[test] fn to_from_dto() { let protocol_parameters = protocol_parameters(); - let output = rand_nft_output(protocol_parameters.token_supply()); - let dto = OutputDto::Nft((&output).into()); - let output_unver = Output::try_from(dto.clone()).unwrap(); - assert_eq!(&output, output_unver.as_nft()); - let output_ver = Output::try_from(dto).unwrap(); - assert_eq!(&output, output_ver.as_nft()); + let nft_output = rand_nft_output(protocol_parameters.token_supply()); + let dto = NftOutputDto::from(&nft_output); + let output = Output::Nft(NftOutput::try_from(dto).unwrap()); + assert_eq!(&nft_output, output.as_nft()); let output_split = NftOutput::try_from_dtos( - OutputBuilderAmount::Amount(output.amount()), - output.mana(), - output.nft_id(), - output.unlock_conditions().iter().map(Into::into).collect(), - Some(output.features().to_vec()), - Some(output.immutable_features().to_vec()), + OutputBuilderAmount::Amount(nft_output.amount()), + nft_output.mana(), + nft_output.nft_id(), + nft_output.unlock_conditions().iter().map(Into::into).collect(), + Some(nft_output.features().to_vec()), + Some(nft_output.immutable_features().to_vec()), ) .unwrap(); - assert_eq!(output, output_split); + assert_eq!(nft_output, output_split); let test_split_dto = |builder: NftOutputBuilder| { let output_split = NftOutput::try_from_dtos( diff --git a/sdk/src/types/block/payload/signed_transaction/transaction.rs b/sdk/src/types/block/payload/signed_transaction/transaction.rs index ff5c713c5b..c566601431 100644 --- a/sdk/src/types/block/payload/signed_transaction/transaction.rs +++ b/sdk/src/types/block/payload/signed_transaction/transaction.rs @@ -536,7 +536,7 @@ pub(crate) mod dto { use super::*; use crate::types::{ - block::{mana::ManaAllotmentDto, output::dto::OutputDto, payload::dto::PayloadDto, Error}, + block::{mana::ManaAllotmentDto, payload::dto::PayloadDto, Error}, TryFromDto, }; @@ -554,7 +554,7 @@ pub(crate) mod dto { pub capabilities: TransactionCapabilities, #[serde(default, skip_serializing_if = "Option::is_none")] pub payload: Option, - pub outputs: Vec, + pub outputs: Vec, } impl From<&Transaction> for TransactionDto { @@ -571,7 +571,7 @@ pub(crate) mod dto { Some(_) => unimplemented!(), None => None, }, - outputs: value.outputs().iter().map(Into::into).collect(), + outputs: value.outputs().to_vec(), } } } @@ -592,11 +592,7 @@ pub(crate) mod dto { .into_iter() .map(|o| ManaAllotment::try_from_dto_with_params_inner(o, params)) .collect::, Error>>()?; - let outputs = dto - .outputs - .into_iter() - .map(Output::try_from) - .collect::, Error>>()?; + let outputs = dto.outputs; let mut builder = Self::builder(network_id) .with_creation_slot(dto.creation_slot) diff --git a/sdk/src/wallet/core/mod.rs b/sdk/src/wallet/core/mod.rs index 68c6843a45..158784e362 100644 --- a/sdk/src/wallet/core/mod.rs +++ b/sdk/src/wallet/core/mod.rs @@ -33,10 +33,7 @@ use crate::{ types::{ block::{ address::{Address, Bech32Address, Hrp, ImplicitAccountCreationAddress}, - output::{ - dto::FoundryOutputDto, AccountId, AnchorId, DelegationId, FoundryId, FoundryOutput, NftId, Output, - OutputId, TokenId, - }, + output::{AccountId, AnchorId, DelegationId, FoundryId, FoundryOutput, NftId, Output, OutputId, TokenId}, payload::signed_transaction::TransactionId, protocol::ProtocolParameters, }, @@ -576,7 +573,7 @@ pub struct WalletDataDto { pub pending_transactions: HashSet, pub incoming_transactions: HashMap, #[serde(default)] - pub native_token_foundries: HashMap, + pub native_token_foundries: HashMap, } impl TryFromDto for WalletData { @@ -613,11 +610,7 @@ impl TryFromDto for WalletData { .map(|(id, o)| Ok((id, TransactionWithMetadata::try_from_dto_with_params_inner(o, params)?))) .collect::>()?, inaccessible_incoming_transactions: Default::default(), - native_token_foundries: dto - .native_token_foundries - .into_iter() - .map(|(id, o)| Ok((id, FoundryOutput::try_from(o)?))) - .collect::>()?, + native_token_foundries: dto.native_token_foundries, }) } } @@ -650,11 +643,7 @@ impl From<&WalletData> for WalletDataDto { .iter() .map(|(id, transaction)| (*id, TransactionWithMetadataDto::from(transaction))) .collect(), - native_token_foundries: value - .native_token_foundries - .iter() - .map(|(id, foundry)| (*id, FoundryOutputDto::from(foundry))) - .collect(), + native_token_foundries: value.native_token_foundries.clone(), } } } diff --git a/sdk/src/wallet/operations/transaction/mod.rs b/sdk/src/wallet/operations/transaction/mod.rs index 5bf828b771..82221ec46d 100644 --- a/sdk/src/wallet/operations/transaction/mod.rs +++ b/sdk/src/wallet/operations/transaction/mod.rs @@ -20,10 +20,7 @@ use crate::{ }, types::{ api::core::OutputWithMetadataResponse, - block::{ - output::{dto::OutputDto, Output}, - payload::signed_transaction::SignedTransactionPayload, - }, + block::{output::Output, payload::signed_transaction::SignedTransactionPayload}, }, wallet::{ types::{InclusionState, TransactionWithMetadata}, @@ -164,7 +161,7 @@ where .into_iter() .map(|input| OutputWithMetadataResponse { metadata: input.output_metadata, - output: OutputDto::from(&input.output), + output: input.output, }) .collect(); diff --git a/sdk/src/wallet/types/mod.rs b/sdk/src/wallet/types/mod.rs index f50f4b8615..14d901501f 100644 --- a/sdk/src/wallet/types/mod.rs +++ b/sdk/src/wallet/types/mod.rs @@ -22,7 +22,7 @@ use crate::{ api::core::OutputWithMetadataResponse, block::{ address::Address, - output::{dto::OutputDto, Output, OutputId, OutputMetadata}, + output::{Output, OutputId, OutputMetadata}, payload::signed_transaction::{dto::SignedTransactionPayloadDto, SignedTransactionPayload, TransactionId}, protocol::ProtocolParameters, slot::SlotIndex, @@ -94,7 +94,7 @@ pub struct OutputDataDto { /// The metadata of the output pub metadata: OutputMetadata, /// The actual Output - pub output: OutputDto, + pub output: Output, /// If an output is spent pub is_spent: bool, /// Associated account address. @@ -113,7 +113,7 @@ impl From<&OutputData> for OutputDataDto { Self { output_id: value.output_id, metadata: value.metadata, - output: OutputDto::from(&value.output), + output: value.output.clone(), is_spent: value.is_spent, address: value.address.clone(), network_id: value.network_id.to_string(), @@ -130,7 +130,7 @@ impl TryFrom for OutputData { Ok(Self { output_id: dto.output_id, metadata: dto.metadata, - output: Output::try_from(dto.output)?, + output: dto.output, is_spent: dto.is_spent, address: dto.address, network_id: dto