diff --git a/crates/iota-sdk-types/src/move_package.rs b/crates/iota-sdk-types/src/move_package.rs index 4829ec24df..7c4b83f9a8 100644 --- a/crates/iota-sdk-types/src/move_package.rs +++ b/crates/iota-sdk-types/src/move_package.rs @@ -3,9 +3,10 @@ use std::collections::BTreeMap; +#[cfg(feature = "hash")] +use crate::hash::Hasher; use crate::{ Digest, ExecutionError, Identifier, ObjectId, - hash::Hasher, version::{Version, VersionError}, }; @@ -137,7 +138,7 @@ pub struct TypeOrigin { /// The name of the data type. Either refers to an enum or a struct /// identifier. // `struct_name` alias to support backwards compatibility with the old name - #[serde(alias = "struct_name")] + #[cfg_attr(feature = "serde", serde(alias = "struct_name"))] pub datatype_name: Identifier, /// ID of the package, where the given type first appeared. pub package: ObjectId, @@ -237,6 +238,7 @@ impl MovePackage { } /// Calculate the digest of the [MovePackage]. + #[cfg(feature = "hash")] pub fn digest(&self) -> Digest { Self::compute_digest_for_modules_and_deps( self.modules.values(), @@ -249,6 +251,7 @@ impl MovePackage { /// It is important that this function is shared across both the calculation /// of the digest for the package, and the calculation of the digest /// on-chain. + #[cfg(feature = "hash")] pub fn compute_digest_for_modules_and_deps<'a>( modules: impl IntoIterator>, object_ids: impl IntoIterator, diff --git a/crates/iota-sdk-types/src/transaction/mod.rs b/crates/iota-sdk-types/src/transaction/mod.rs index ef5d1c43da..d8bcbe289e 100644 --- a/crates/iota-sdk-types/src/transaction/mod.rs +++ b/crates/iota-sdk-types/src/transaction/mod.rs @@ -1305,7 +1305,7 @@ impl SharedObjectReference { /// command-make-move-vector = %x05 make-move-vector /// command-upgrade = %x06 upgrade /// ``` -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr( feature = "schemars", derive(schemars::JsonSchema), @@ -1355,6 +1355,234 @@ impl Command { MakeMoveVector, Upgrade, ); + + pub fn move_call( + package: ObjectId, + module: Identifier, + function: Identifier, + type_arguments: Vec, + arguments: Vec, + ) -> Self { + Command::MoveCall(MoveCall { + package, + module, + function, + type_arguments, + arguments, + }) + } + + pub fn transfer_objects(objects: Vec, address: Argument) -> Self { + Command::TransferObjects(TransferObjects { objects, address }) + } + + pub fn split_coins(coin: Argument, amounts: Vec) -> Self { + Command::SplitCoins(SplitCoins { coin, amounts }) + } + + pub fn merge_coins(coin: Argument, coins_to_merge: Vec) -> Self { + Command::MergeCoins(MergeCoins { + coin, + coins_to_merge, + }) + } + + pub fn publish(modules: Vec>, dependencies: Vec) -> Self { + Command::Publish(Publish { + modules, + dependencies, + }) + } + + pub fn make_move_vector(type_: Option, elements: Vec) -> Self { + Command::MakeMoveVector(MakeMoveVector { type_, elements }) + } + + pub fn upgrade( + modules: Vec>, + dependencies: Vec, + package: ObjectId, + ticket: Argument, + ) -> Self { + Command::Upgrade(Upgrade { + modules, + dependencies, + package, + ticket, + }) + } + + pub fn non_system_packages_to_be_published(&self) -> Option<&Vec>> { + match self { + Command::Publish(cmd) => Some(&cmd.modules), + Command::Upgrade(cmd) => Some(&cmd.modules), + Command::MoveCall(_) + | Command::TransferObjects(_) + | Command::SplitCoins(_) + | Command::MergeCoins(_) + | Command::MakeMoveVector(_) => None, + } + } + + pub fn is_input_arg_used(&self, input_arg: u16) -> bool { + match self { + Command::MoveCall(c) => c.is_input_arg_used(input_arg), + Command::TransferObjects(TransferObjects { + objects: args, + address: arg, + }) + | Command::MergeCoins(MergeCoins { + coins_to_merge: args, + coin: arg, + }) + | Command::SplitCoins(SplitCoins { + amounts: args, + coin: arg, + }) => args + .iter() + .chain(iter::once(arg)) + .any(|arg| matches!(arg, Argument::Input(input) if *input == input_arg)), + Command::MakeMoveVector(MakeMoveVector { elements, .. }) => elements + .iter() + .any(|arg| matches!(arg, Argument::Input(input) if *input == input_arg)), + Command::Upgrade(Upgrade { ticket, .. }) => { + matches!(ticket, Argument::Input(input) if *input == input_arg) + } + Command::Publish(_) => false, + } + } +} + +pub fn write_sep( + f: &mut core::fmt::Formatter<'_>, + items: impl IntoIterator, + delimiters: Option<(&str, &str)>, + sep: &str, +) -> std::fmt::Result { + let mut xs = items.into_iter(); + let Some(x) = xs.next() else { + return Ok(()); + }; + if let Some((l, _)) = delimiters { + write!(f, "{l}")?; + } + write!(f, "{x}")?; + for x in xs { + write!(f, "{sep}{x}")?; + } + if let Some((_, r)) = delimiters { + write!(f, "{r}")?; + } + Ok(()) +} + +impl core::fmt::Display for MoveCall { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { + package, + module, + function, + type_arguments, + arguments, + } = self; + write!(f, "MoveCall(")?; + write!(f, "{package}::{module}::{function}")?; + if !type_arguments.is_empty() { + write_sep(f, type_arguments, Some(("<", ">")), ",")?; + } + write_sep(f, arguments, Some(("(", ")")), ",")?; + write!(f, ")") + } +} + +impl core::fmt::Display for TransferObjects { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { objects, address } = self; + + write!(f, "TransferObjects(")?; + write_sep(f, objects, Some(("[", "]")), ",")?; + write!(f, ",{address})") + } +} + +impl core::fmt::Display for SplitCoins { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { coin, amounts } = self; + + write!(f, "SplitCoins({coin},")?; + write_sep(f, amounts, Some(("[", "]")), ",")?; + write!(f, ")") + } +} + +impl core::fmt::Display for MergeCoins { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { + coin, + coins_to_merge, + } = self; + + write!(f, "MergeCoins({coin},")?; + write_sep(f, coins_to_merge, Some(("[", "]")), ",")?; + write!(f, ")") + } +} + +impl core::fmt::Display for Publish { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { dependencies, .. } = self; + + write!(f, "Publish(_,")?; + write_sep(f, dependencies, Some(("[", "]")), ",")?; + write!(f, ")") + } +} + +impl core::fmt::Display for MakeMoveVector { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { type_, elements } = self; + + write!(f, "MakeMoveVector(")?; + if let Some(ty) = type_ { + write!(f, "Some({ty})")?; + } else { + write!(f, "None")?; + } + write!(f, ",")?; + write_sep(f, elements, Some(("[", "]")), ",")?; + write!(f, ")") + } +} + +impl core::fmt::Display for Upgrade { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { + dependencies, + package, + ticket, + .. + } = self; + + write!(f, "Upgrade(_,")?; + write_sep(f, dependencies, Some(("[", "]")), ",")?; + write!(f, ", {package}")?; + write!(f, ", {ticket}")?; + write!(f, ")") + } +} + +impl core::fmt::Display for Command { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Command::MoveCall(cmd) => write!(f, "{cmd}"), + Command::TransferObjects(cmd) => write!(f, "{cmd}"), + Command::SplitCoins(cmd) => write!(f, "{cmd}"), + Command::MergeCoins(cmd) => write!(f, "{cmd}"), + Command::Publish(cmd) => write!(f, "{cmd}"), + Command::MakeMoveVector(cmd) => write!(f, "{cmd}"), + Command::Upgrade(cmd) => write!(f, "{cmd}"), + } + } } /// Command to transfer ownership of a set of objects to an address @@ -1366,7 +1594,7 @@ impl Command { /// ```text /// transfer-objects = (vector argument) argument /// ``` -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] #[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))] @@ -1387,7 +1615,7 @@ pub struct TransferObjects { /// ```text /// split-coins = argument (vector argument) /// ``` -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] #[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))] @@ -1408,7 +1636,7 @@ pub struct SplitCoins { /// ```text /// merge-coins = argument (vector argument) /// ``` -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr( feature = "serde", derive(serde::Serialize, serde::Deserialize), @@ -1436,7 +1664,7 @@ pub struct MergeCoins { /// publish = (vector bytes) ; the serialized move modules /// (vector object-id) ; the set of package dependencies /// ``` -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] #[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))] @@ -1463,7 +1691,7 @@ pub struct Publish { /// ```text /// make-move-vector = (option type-tag) (vector argument) /// ``` -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] #[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))] @@ -1491,7 +1719,7 @@ pub struct MakeMoveVector { /// object-id ; package-id of the package /// argument ; upgrade ticket /// ``` -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] #[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))] @@ -1626,7 +1854,7 @@ impl Argument { /// (vector type-tag) ; type arguments, if any /// (vector argument) ; input arguments /// ``` -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr( feature = "serde", derive(serde::Serialize, serde::Deserialize), @@ -1648,3 +1876,11 @@ pub struct MoveCall { #[cfg_attr(feature = "proptest", any(proptest::collection::size_range(0..=2).lift()))] pub arguments: Vec, } + +impl MoveCall { + fn is_input_arg_used(&self, arg: u16) -> bool { + self.arguments + .iter() + .any(|a| matches!(a, Argument::Input(inp) if *inp == arg)) + } +} diff --git a/crates/iota-sdk-types/src/transaction/serialization.rs b/crates/iota-sdk-types/src/transaction/serialization.rs index e74837a38e..7fff2ba8ae 100644 --- a/crates/iota-sdk-types/src/transaction/serialization.rs +++ b/crates/iota-sdk-types/src/transaction/serialization.rs @@ -717,6 +717,7 @@ mod command { } #[derive(serde::Serialize)] + #[serde(rename = "Command")] enum BinaryCommandRef<'a> { MoveCall(&'a MoveCall), TransferObjects(&'a TransferObjects), @@ -728,6 +729,7 @@ mod command { } #[derive(serde::Deserialize)] + #[serde(rename = "Command")] enum BinaryCommand { MoveCall(MoveCall), TransferObjects(TransferObjects),