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/block_builder/mod.rs b/sdk/src/client/api/block_builder/mod.rs index 9c87e324b9..9222463327 100644 --- a/sdk/src/client/api/block_builder/mod.rs +++ b/sdk/src/client/api/block_builder/mod.rs @@ -8,7 +8,7 @@ pub use self::transaction::verify_semantic; use crate::{ client::{ClientInner, Result}, types::block::{ - core::{basic::MaxBurnedManaAmount, BlockHeader, UnsignedBlock}, + core::{BlockHeader, UnsignedBlock}, output::AccountId, payload::Payload, BlockBody, @@ -39,7 +39,7 @@ impl ClientInner { protocol_params.version(), protocol_params.network_id(), issuing_time, - issuance.commitment.id(), + issuance.latest_commitment.id(), issuance.latest_finalized_slot, issuer_id, ), @@ -47,7 +47,7 @@ impl ClientInner { issuance.strong_parents()?, ( protocol_params.work_score_parameters, - issuance.commitment.reference_mana_cost(), + issuance.latest_commitment.reference_mana_cost(), ), ) .with_weak_parents(issuance.weak_parents()?) diff --git a/sdk/src/client/api/high_level.rs b/sdk/src/client/api/high_level.rs index 460667c9c8..55a67e4194 100644 --- a/sdk/src/client/api/high_level.rs +++ b/sdk/src/client/api/high_level.rs @@ -77,10 +77,7 @@ impl Client { .flatten() .map(|output_with_meta| { Ok(( - UtxoInput::new( - output_with_meta.metadata().transaction_id().to_owned(), - output_with_meta.metadata().output_index(), - ), + UtxoInput::from(*output_with_meta.metadata().output_id()), output_with_meta.output().amount(), )) }) 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..907f0891a3 100644 --- a/sdk/src/types/api/core.rs +++ b/sdk/src/types/api/core.rs @@ -14,7 +14,8 @@ use crate::{ types::block::{ address::Bech32Address, core::Parents, - output::{dto::OutputDto, OutputId, OutputMetadata, OutputWithMetadata}, + output::{Output, OutputId, OutputMetadata, OutputWithMetadata}, + payload::signed_transaction::TransactionId, protocol::{ProtocolParameters, ProtocolParametersHash}, semantic::TransactionFailureReason, slot::{EpochIndex, SlotCommitment, SlotCommitmentId, SlotIndex}, @@ -173,6 +174,31 @@ pub struct BaseTokenResponse { pub decimals: u32, } +/// Information of a validator. +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ValidatorResponse { + /// Account address of the validator. + address: Bech32Address, + /// The epoch index until which the validator registered to stake. + staking_end_epoch: EpochIndex, + /// The total stake of the pool, including delegators. + #[serde(with = "string")] + pool_stake: u64, + /// The stake of a validator. + #[serde(with = "string")] + validator_stake: u64, + /// The fixed cost of the validator, which it receives as part of its Mana rewards. + #[serde(with = "string")] + fixed_cost: u64, + /// Shows whether the validator was active recently. + active: bool, + /// The latest protocol version the validator supported. + latest_supported_protocol_version: u8, + /// The protocol hash of the latest supported protocol of the validator. + latest_supported_protocol_hash: ProtocolParametersHash, +} + /// Response of GET /api/core/v3/blocks/validators. /// A paginated list of all registered validators ready for the next epoch and indicates if they were active recently /// (are eligible for committee selection). @@ -195,10 +221,10 @@ pub struct ValidatorsResponse { #[serde(rename_all = "camelCase")] pub struct ManaRewardsResponse { /// The starting epoch index for which the mana rewards are returned. - pub epoch_start: EpochIndex, + pub start_epoch: EpochIndex, /// The ending epoch index for which the mana rewards are returned, the decay is applied up to this point /// included. - pub epoch_end: EpochIndex, + pub end_epoch: EpochIndex, /// The amount of totally available rewards the requested output may claim. #[serde(with = "string")] pub rewards: u64, @@ -238,31 +264,6 @@ pub struct CommitteeMember { pub fixed_cost: u64, } -/// Information of a validator. -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ValidatorResponse { - /// Account address of the validator. - address: Bech32Address, - /// The epoch index until which the validator registered to stake. - staking_epoch_end: EpochIndex, - /// The total stake of the pool, including delegators. - #[serde(with = "string")] - pool_stake: u64, - /// The stake of a validator. - #[serde(with = "string")] - validator_stake: u64, - /// The fixed cost of the validator, which it receives as part of its Mana rewards. - #[serde(with = "string")] - fixed_cost: u64, - /// Shows whether validator was active recently. - active: bool, - /// The latest protocol version the validator supported. - latest_supported_protocol_version: u8, - // The protocol hash of the latest supported protocol of the validator. - latest_supported_protocol_hash: ProtocolParametersHash, -} - /// Response of GET /api/core/v3/blocks/issuance /// Information that is ideal for attaching a block in the network. #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] @@ -278,8 +279,8 @@ pub struct IssuanceBlockHeaderResponse { pub shallow_like_parents: BTreeSet, /// The slot index of the latest finalized slot. pub latest_finalized_slot: SlotIndex, - /// The most recent slot commitment. - pub commitment: SlotCommitment, + /// The latest slot commitment. + pub latest_commitment: SlotCommitment, } impl IssuanceBlockHeaderResponse { @@ -389,6 +390,16 @@ pub enum BlockFailureReason { Invalid = 255, } +// Response of a GET transaction metadata REST API call. +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TransactionMetadataResponse { + pub transaction_id: TransactionId, + pub transaction_state: TransactionState, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub transaction_failure_reason: Option, +} + /// Response of GET /api/core/v3/blocks/{blockId}/metadata. /// Returns the metadata of a block. #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] @@ -397,11 +408,9 @@ pub struct BlockMetadataResponse { pub block_id: BlockId, pub block_state: BlockState, #[serde(default, skip_serializing_if = "Option::is_none")] - pub transaction_state: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] pub block_failure_reason: Option, #[serde(default, skip_serializing_if = "Option::is_none")] - pub transaction_failure_reason: Option, + pub transaction_metadata: Option, } /// Response of GET /api/core/v3/blocks/{blockId}/full. @@ -418,14 +427,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/metadata.rs b/sdk/src/types/block/output/metadata.rs index 300b32da8c..f518a2403d 100644 --- a/sdk/src/types/block/output/metadata.rs +++ b/sdk/src/types/block/output/metadata.rs @@ -2,94 +2,150 @@ // SPDX-License-Identifier: Apache-2.0 use crate::types::block::{ - output::OutputId, payload::signed_transaction::TransactionId, slot::SlotCommitmentId, BlockId, + output::OutputId, + payload::signed_transaction::TransactionId, + slot::{SlotCommitmentId, SlotIndex}, + BlockId, }; +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +#[cfg_attr( + feature = "serde", + derive(serde::Serialize, serde::Deserialize), + serde(rename_all = "camelCase") +)] +pub struct OutputInclusionMetadata { + // Slot in which the output was included. + slot: SlotIndex, + // Transaction ID that created the output. + transaction_id: TransactionId, + // Commitment ID that includes the creation of the output. + #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "Option::is_none"))] + commitment_id: Option, +} + +impl OutputInclusionMetadata { + pub fn new(slot: SlotIndex, transaction_id: TransactionId, commitment_id: Option) -> Self { + Self { + slot, + transaction_id, + commitment_id, + } + } + + pub fn slot(&self) -> SlotIndex { + self.slot + } + + pub fn transaction_id(&self) -> &TransactionId { + &self.transaction_id + } + + pub fn commitment_id(&self) -> Option<&SlotCommitmentId> { + self.commitment_id.as_ref() + } +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +#[cfg_attr( + feature = "serde", + derive(serde::Serialize, serde::Deserialize), + serde(rename_all = "camelCase") +)] +pub struct OutputConsumptionMetadata { + // Slot in which the output was spent. + slot: SlotIndex, + // Transaction ID that spent the output. + transaction_id: TransactionId, + // Commitment ID that includes the spending of the output. + #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "Option::is_none"))] + commitment_id: Option, +} + +impl OutputConsumptionMetadata { + pub fn new(slot: SlotIndex, transaction_id: TransactionId, commitment_id: Option) -> Self { + Self { + slot, + transaction_id, + commitment_id, + } + } + + pub fn slot(&self) -> SlotIndex { + self.slot + } + + pub fn transaction_id(&self) -> &TransactionId { + &self.transaction_id + } + + pub fn commitment_id(&self) -> Option<&SlotCommitmentId> { + self.commitment_id.as_ref() + } +} + /// Metadata of an [`Output`](crate::types::block::output::Output). #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +#[cfg_attr( + feature = "serde", + derive(serde::Serialize, serde::Deserialize), + serde(rename_all = "camelCase") +)] pub struct OutputMetadata { - /// The ID of the block in which the output was included. - block_id: BlockId, /// The ID of the output. output_id: OutputId, - /// Whether the output is spent or not. - is_spent: bool, - // Commitment ID that includes the spent output. - commitment_id_spent: Option, - // Transaction ID that spent the output. - transaction_id_spent: Option, - /// Commitment ID that includes the output. - included_commitment_id: Option, + /// The ID of the block in which the output was included. + block_id: BlockId, + // Metadata of the output if it is included in the ledger. + included: OutputInclusionMetadata, + // Metadata of the output if it is marked as spent in the ledger. + #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "Option::is_none"))] + spent: Option, /// Latest commitment ID of the node. latest_commitment_id: SlotCommitmentId, } impl OutputMetadata { /// Creates a new [`OutputMetadata`]. - #[allow(clippy::too_many_arguments)] pub fn new( - block_id: BlockId, output_id: OutputId, - is_spent: bool, - commitment_id_spent: Option, - transaction_id_spent: Option, - included_commitment_id: Option, + block_id: BlockId, + included: OutputInclusionMetadata, + spent: Option, latest_commitment_id: SlotCommitmentId, ) -> Self { Self { block_id, output_id, - is_spent, - commitment_id_spent, - transaction_id_spent, - included_commitment_id, + included, + spent, latest_commitment_id, } } - /// Returns the block ID of the [`OutputMetadata`]. - pub fn block_id(&self) -> &BlockId { - &self.block_id - } - /// Returns the output ID of the [`OutputMetadata`]. pub fn output_id(&self) -> &OutputId { &self.output_id } - /// Returns the transaction ID of the [`OutputMetadata`]. - pub fn transaction_id(&self) -> &TransactionId { - self.output_id.transaction_id() - } - - /// Returns the output index of the [`OutputMetadata`]. - pub fn output_index(&self) -> u16 { - self.output_id.index() - } - - /// Returns whether the output is spent or not. - pub fn is_spent(&self) -> bool { - self.is_spent - } - - /// Sets whether the output is spent or not. - pub fn set_spent(&mut self, spent: bool) { - self.is_spent = spent; + /// Returns the block ID of the [`OutputMetadata`]. + pub fn block_id(&self) -> &BlockId { + &self.block_id } - /// Returns the commitment ID spent of the [`OutputMetadata`]. - pub fn commitment_id_spent(&self) -> Option<&SlotCommitmentId> { - self.commitment_id_spent.as_ref() + /// Returns the inclusion metadata of the [`OutputMetadata`]. + pub fn included(&self) -> &OutputInclusionMetadata { + &self.included } - /// Returns the transaction ID spent of the [`OutputMetadata`]. - pub fn transaction_id_spent(&self) -> Option<&TransactionId> { - self.transaction_id_spent.as_ref() + /// Returns the consumption metadata of the [`OutputMetadata`]. + pub fn spent(&self) -> Option<&OutputConsumptionMetadata> { + self.spent.as_ref() } - /// Returns the included commitment ID of the [`OutputMetadata`]. - pub fn included_commitment_id(&self) -> Option<&SlotCommitmentId> { - self.included_commitment_id.as_ref() + /// Returns whether the [`OutputMetadata`] is spent or not. + pub fn is_spent(&self) -> bool { + self.spent.is_some() } /// Returns the latest commitment ID of the [`OutputMetadata`]. @@ -97,70 +153,3 @@ impl OutputMetadata { &self.latest_commitment_id } } - -#[cfg(feature = "serde")] -mod dto { - use serde::{Deserialize, Serialize}; - - use super::*; - - #[derive(Serialize, Deserialize)] - #[serde(rename_all = "camelCase")] - struct OutputMetadataDto { - block_id: BlockId, - transaction_id: TransactionId, - output_index: u16, - is_spent: bool, - #[serde(default, skip_serializing_if = "Option::is_none")] - commitment_id_spent: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - transaction_id_spent: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - included_commitment_id: Option, - latest_commitment_id: SlotCommitmentId, - } - - impl From for OutputMetadata { - fn from(value: OutputMetadataDto) -> Self { - Self { - block_id: value.block_id, - output_id: OutputId::new(value.transaction_id, value.output_index), - is_spent: value.is_spent, - commitment_id_spent: value.commitment_id_spent, - transaction_id_spent: value.transaction_id_spent, - included_commitment_id: value.included_commitment_id, - latest_commitment_id: value.latest_commitment_id, - } - } - } - - impl From<&OutputMetadata> for OutputMetadataDto { - fn from(value: &OutputMetadata) -> Self { - Self { - block_id: value.block_id, - transaction_id: *value.transaction_id(), - output_index: value.output_index(), - is_spent: value.is_spent, - commitment_id_spent: value.commitment_id_spent, - transaction_id_spent: value.transaction_id_spent, - included_commitment_id: value.included_commitment_id, - latest_commitment_id: value.latest_commitment_id, - } - } - } - - impl<'de> Deserialize<'de> for OutputMetadata { - fn deserialize>(d: D) -> Result { - Ok(OutputMetadataDto::deserialize(d)?.into()) - } - } - - impl Serialize for OutputMetadata { - fn serialize(&self, s: S) -> Result - where - S: serde::Serializer, - { - OutputMetadataDto::from(self).serialize(s) - } - } -} diff --git a/sdk/src/types/block/output/mod.rs b/sdk/src/types/block/output/mod.rs index 7249ba2393..b90a3fda69 100644 --- a/sdk/src/types/block/output/mod.rs +++ b/sdk/src/types/block/output/mod.rs @@ -37,7 +37,7 @@ pub use self::{ delegation::{DelegationId, DelegationOutput, DelegationOutputBuilder}, feature::{Feature, Features}, foundry::{FoundryId, FoundryOutput, FoundryOutputBuilder}, - metadata::OutputMetadata, + metadata::{OutputConsumptionMetadata, OutputInclusionMetadata, OutputMetadata}, native_token::{NativeToken, NativeTokens, NativeTokensBuilder, TokenId}, nft::{NftId, NftOutput, NftOutputBuilder}, output_id::OutputId, @@ -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/types/block/rand/output/metadata.rs b/sdk/src/types/block/rand/output/metadata.rs index 0a5223a41f..6ea90fc86b 100644 --- a/sdk/src/types/block/rand/output/metadata.rs +++ b/sdk/src/types/block/rand/output/metadata.rs @@ -2,22 +2,46 @@ // SPDX-License-Identifier: Apache-2.0 use crate::types::block::{ - output::OutputMetadata, + output::{OutputConsumptionMetadata, OutputId, OutputInclusionMetadata, OutputMetadata}, rand::{ - block::rand_block_id, bool::rand_bool, option::rand_option, output::rand_output_id, - slot::rand_slot_commitment_id, transaction::rand_transaction_id, + block::rand_block_id, + option::rand_option, + output::rand_output_id, + slot::{rand_slot_commitment_id, rand_slot_index}, + transaction::rand_transaction_id, }, }; -/// Generates a random [`OutputMetadata`]. -pub fn rand_output_metadata() -> OutputMetadata { - OutputMetadata::new( - rand_block_id(), - rand_output_id(), - rand_bool(), +/// Generates a random [`OutputInclusionMetadata`]. +pub fn rand_output_inclusion_metadata() -> OutputInclusionMetadata { + OutputInclusionMetadata::new( + rand_slot_index(), + rand_transaction_id(), rand_option(rand_slot_commitment_id()), - rand_option(rand_transaction_id()), + ) +} + +/// Generates a random [`OutputConsumptionMetadata`]. +pub fn rand_output_consumption_metadata() -> OutputConsumptionMetadata { + OutputConsumptionMetadata::new( + rand_slot_index(), + rand_transaction_id(), rand_option(rand_slot_commitment_id()), + ) +} + +/// Generates a random [`OutputMetadata`] with a specific [`OutputId`]. +pub fn rand_output_metadata_with_id(output_id: OutputId) -> OutputMetadata { + OutputMetadata::new( + output_id, + rand_block_id(), + rand_output_inclusion_metadata(), + rand_option(rand_output_consumption_metadata()), rand_slot_commitment_id(), ) } + +/// Generates a random [`OutputMetadata`]. +pub fn rand_output_metadata() -> OutputMetadata { + rand_output_metadata_with_id(rand_output_id()) +} diff --git a/sdk/src/types/block/rand/output/mod.rs b/sdk/src/types/block/rand/output/mod.rs index f84fad6133..818ca556ed 100644 --- a/sdk/src/types/block/rand/output/mod.rs +++ b/sdk/src/types/block/rand/output/mod.rs @@ -12,7 +12,10 @@ pub mod unlock_condition; use primitive_types::U256; -pub use self::{metadata::rand_output_metadata, native_token::rand_native_token}; +pub use self::{ + metadata::{rand_output_metadata, rand_output_metadata_with_id}, + native_token::rand_native_token, +}; use crate::types::block::{ output::{ unlock_condition::ImmutableAccountAddressUnlockCondition, AccountId, AccountOutput, AnchorId, AnchorOutput, 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/reissue.rs b/sdk/src/wallet/operations/reissue.rs index ec1c120f36..7bad812224 100644 --- a/sdk/src/wallet/operations/reissue.rs +++ b/sdk/src/wallet/operations/reissue.rs @@ -88,7 +88,7 @@ where let mut failed = false; for (index, block_id) in block_ids.clone().iter().enumerate() { let block_metadata = self.client().get_block_metadata(block_id).await?; - if let Some(transaction_state) = block_metadata.transaction_state { + if let Some(transaction_state) = block_metadata.transaction_metadata.map(|m| m.transaction_state) { match transaction_state { // TODO: find out what to do with TransactionState::Confirmed TransactionState::Finalized => return Ok(*block_id), diff --git a/sdk/src/wallet/operations/syncing/outputs.rs b/sdk/src/wallet/operations/syncing/outputs.rs index bc048e8350..0e18fc8c9c 100644 --- a/sdk/src/wallet/operations/syncing/outputs.rs +++ b/sdk/src/wallet/operations/syncing/outputs.rs @@ -45,7 +45,7 @@ where // transactions separated, then this check wouldn't be required) let remainder = wallet_data .transactions - .get(output_with_meta.metadata().transaction_id()) + .get(output_with_meta.metadata().output_id().transaction_id()) .map_or(false, |tx| !tx.incoming); let chain = wallet_data.bip_path.map(|bip_path| { diff --git a/sdk/src/wallet/operations/syncing/transactions.rs b/sdk/src/wallet/operations/syncing/transactions.rs index f7aa640ce4..890e78e041 100644 --- a/sdk/src/wallet/operations/syncing/transactions.rs +++ b/sdk/src/wallet/operations/syncing/transactions.rs @@ -101,7 +101,7 @@ where if let Some(block_id) = transaction.block_id { match self.client().get_block_metadata(&block_id).await { Ok(metadata) => { - if let Some(tx_state) = metadata.transaction_state { + if let Some(tx_state) = metadata.transaction_metadata.map(|m| m.transaction_state) { match tx_state { // TODO: Separate TransactionState::Finalized? TransactionState::Finalized | TransactionState::Confirmed => { 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 diff --git a/sdk/src/wallet/update.rs b/sdk/src/wallet/update.rs index 820dd663eb..c10d07f2da 100644 --- a/sdk/src/wallet/update.rs +++ b/sdk/src/wallet/update.rs @@ -69,7 +69,8 @@ where wallet_data.unspent_outputs.remove(&output_id); // Update spent data fields if let Some(output_data) = wallet_data.outputs.get_mut(&output_id) { - output_data.metadata.set_spent(true); + // TODO https://github.com/iotaledger/iota-sdk/issues/1718 + // output_data.metadata.set_spent(true); output_data.is_spent = true; #[cfg(feature = "events")] { diff --git a/sdk/tests/client/input_signing_data.rs b/sdk/tests/client/input_signing_data.rs index 491cf180f5..89c057a191 100644 --- a/sdk/tests/client/input_signing_data.rs +++ b/sdk/tests/client/input_signing_data.rs @@ -1,8 +1,6 @@ // Copyright 2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -use std::str::FromStr; - use crypto::keys::bip44::Bip44; use iota_sdk::{ client::{ @@ -11,10 +9,8 @@ use iota_sdk::{ }, types::block::{ address::Address, - output::{unlock_condition::AddressUnlockCondition, BasicOutput, OutputId, OutputMetadata}, - payload::signed_transaction::TransactionId, - slot::SlotCommitmentId, - BlockId, + output::{unlock_condition::AddressUnlockCondition, BasicOutput}, + rand::output::rand_output_metadata, }, }; use pretty_assertions::assert_eq; @@ -32,30 +28,7 @@ fn input_signing_data_conversion() { let input_signing_data = InputSigningData { output, - output_metadata: OutputMetadata::new( - BlockId::from_str("0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda00000000").unwrap(), - OutputId::from_str("0xbce525324af12eda02bf7927e92cea3a8e8322d0f41966271443e6c3b245a440000000000000") - .unwrap(), - false, - Some( - SlotCommitmentId::from_str( - "0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda4f9567d8", - ) - .unwrap(), - ), - Some( - TransactionId::from_str("0x24a1f46bdb6b2bf38f1c59f73cdd4ae5b418804bb231d76d06fbf246498d588300000000") - .unwrap(), - ), - Some( - SlotCommitmentId::from_str( - "0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda4f9567d8", - ) - .unwrap(), - ), - SlotCommitmentId::from_str("0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda4f9567d8") - .unwrap(), - ), + output_metadata: rand_output_metadata(), chain: Some(bip44_chain), }; @@ -65,45 +38,10 @@ fn input_signing_data_conversion() { let restored_input_signing_data = InputSigningData::try_from(input_signing_data_dto.clone()).unwrap(); assert_eq!(input_signing_data, restored_input_signing_data); - let input_signing_data_dto_json = serde_json::json!({ - "output": { - "type": 0, - "amount": "1000000", - "mana": "0", - "unlockConditions": [ - { - "type": 0, - "address": { - "type": 0, - "pubKeyHash": "0x7ffec9e1233204d9c6dce6812b1539ee96af691ca2e4d9065daa85907d33e5d3" - } - } - ] - }, - "outputMetadata": { - "blockId": "0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda00000000", - "transactionId": "0xbce525324af12eda02bf7927e92cea3a8e8322d0f41966271443e6c3b245a44000000000", - "outputIndex": 0, - "isSpent": false, - "commitmentIdSpent": "0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda4f9567d8", - "transactionIdSpent": "0x24a1f46bdb6b2bf38f1c59f73cdd4ae5b418804bb231d76d06fbf246498d588300000000", - "includedCommitmentId": "0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda4f9567d8", - "latestCommitmentId": "0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda4f9567d8"}, - "chain": { - "coinType": 4219, - "account": 0, - "change": 0, - "addressIndex": 0 - } - } - ); - assert_eq!( - serde_json::to_value(&input_signing_data_dto).unwrap(), - input_signing_data_dto_json - ); + let input_signing_data_dto_json = serde_json::to_string(&input_signing_data_dto).unwrap(); let restored_input_signing_data_dto = - serde_json::from_value::(input_signing_data_dto_json).unwrap(); + serde_json::from_str::(&input_signing_data_dto_json).unwrap(); assert_eq!(restored_input_signing_data_dto.chain.as_ref(), Some(&bip44_chain)); let restored_input_signing_data = InputSigningData::try_from(restored_input_signing_data_dto).unwrap(); diff --git a/sdk/tests/client/mod.rs b/sdk/tests/client/mod.rs index 854d8a836a..6e5be5e3ca 100644 --- a/sdk/tests/client/mod.rs +++ b/sdk/tests/client/mod.rs @@ -29,9 +29,9 @@ use iota_sdk::{ StorageDepositReturnUnlockCondition, TimelockUnlockCondition, UnlockCondition, }, AccountId, AccountOutputBuilder, BasicOutputBuilder, FoundryOutputBuilder, NativeToken, NftId, - NftOutputBuilder, Output, OutputId, OutputMetadata, SimpleTokenScheme, TokenId, TokenScheme, + NftOutputBuilder, Output, OutputId, SimpleTokenScheme, TokenId, TokenScheme, }, - rand::{block::rand_block_id, slot::rand_slot_commitment_id, transaction::rand_transaction_id}, + rand::{output::rand_output_metadata_with_id, transaction::rand_transaction_id}, }, }; @@ -239,15 +239,7 @@ fn build_inputs<'a>(outputs: impl IntoIterator>) -> Vec