Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Sui]: Adds support for remaining commands/call_args/input_args in raw json #4252

Merged
merged 5 commits into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions rust/chains/tw_sui/src/transaction/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use move_core_types::identifier::Identifier;
use move_core_types::language_storage::TypeTag;
use serde::{Deserialize, Serialize};

// Taken from here: https://github.com/MystenLabs/sui/blob/93f02057bb55eca407f04f551e6514f123005b65/crates/sui-types/src/transaction.rs#L660
/// A single command in a programmable transaction.
#[derive(Debug, Deserialize, Serialize)]
pub enum Command {
Expand All @@ -30,6 +31,14 @@ pub enum Command {
/// Given n-values of the same type, it constructs a vector. For non objects or an empty vector,
/// the type tag must be specified.
MakeMoveVec(Option<TypeTag>, Vec<Argument>),
/// Upgrades a Move package
/// Takes (in order):
/// 1. A vector of serialized modules for the package.
/// 2. A vector of object ids for the transitive dependencies of the new package.
/// 3. The object ID of the package being upgraded.
/// 4. An argument holding the `UpgradeTicket` that must have been produced from an earlier command in the same
/// programmable transaction.
Upgrade(Vec<Vec<u8>>, Vec<ObjectID>, ObjectID, Argument),
}

impl Command {
Expand Down
216 changes: 206 additions & 10 deletions rust/chains/tw_sui/src/transaction/raw_types.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
use move_core_types::identifier::Identifier;
use move_core_types::language_storage::TypeTag;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use tw_coin_entry::error::prelude::SigningError;
use tw_coin_entry::error::prelude::*;
use tw_coin_entry::error::prelude::{SigningError, SigningErrorType, SigningResult};
use tw_memory::Data;
use tw_misc::serde::as_string;

use crate::address::SuiAddress;

use super::sui_types::TransactionExpiration;
use super::{
command::Argument,
sui_types::{ObjectArg, ObjectID, SequenceNumber},
command::{Argument, Command},
sui_types::{CallArg, ObjectArg, ObjectDigest, ObjectID, ObjectRef, SequenceNumber},
};

#[derive(Debug, Deserialize, Serialize)]
Expand All @@ -21,6 +24,18 @@ pub struct PaymentConfig {
pub digest: String,
}

impl TryFrom<PaymentConfig> for ObjectRef {
type Error = SigningError;

fn try_from(config: PaymentConfig) -> Result<Self, Self::Error> {
Ok((
ObjectID::from_str(&config.object_id)?,
SequenceNumber(config.version),
ObjectDigest::from_str(&config.digest)?,
))
}
}

#[derive(Debug, Deserialize, Serialize)]
pub struct GasConfig {
#[serde(with = "as_string")]
Expand All @@ -32,20 +47,42 @@ pub struct GasConfig {

#[derive(Debug, Deserialize, Serialize)]
pub enum InputObjectArg {
#[serde(rename_all = "camelCase")]
ImmOrOwned {
object_id: String,
#[serde(with = "as_string")]
version: u64,
digest: String,
},
#[serde(rename_all = "camelCase")]
Shared {
mutable: bool,
#[serde(with = "as_string")]
initial_shared_version: u64,
object_id: String,
},
#[serde(rename_all = "camelCase")]
Receiving {
digest: String,
version: u64,
object_id: String,
},
}

impl TryFrom<InputObjectArg> for ObjectArg {
type Error = SigningError;

fn try_from(arg: InputObjectArg) -> Result<Self, Self::Error> {
match arg {
InputObjectArg::ImmOrOwned {
object_id,
version,
digest,
} => Ok(ObjectArg::ImmOrOwnedObject((
ObjectID::from_str(&object_id)?,
SequenceNumber(version),
ObjectDigest::from_str(&digest)?,
))),
InputObjectArg::Shared {
mutable,
initial_shared_version,
Expand All @@ -55,6 +92,15 @@ impl TryFrom<InputObjectArg> for ObjectArg {
initial_shared_version: SequenceNumber(initial_shared_version),
mutable,
}),
InputObjectArg::Receiving {
digest,
version,
object_id,
} => Ok(ObjectArg::Receiving((
ObjectID::from_str(&object_id)?,
SequenceNumber(version),
ObjectDigest::from_str(&digest)?,
))),
}
}
}
Expand All @@ -65,6 +111,17 @@ pub enum InputArg {
Object(InputObjectArg),
}

impl TryFrom<InputArg> for CallArg {
type Error = SigningError;

fn try_from(arg: InputArg) -> Result<Self, Self::Error> {
match arg {
InputArg::Pure(data) => Ok(CallArg::Pure(data)),
InputArg::Object(object) => Ok(CallArg::Object(object.try_into()?)),
}
}
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Input {
Expand All @@ -79,8 +136,17 @@ pub struct Input {
#[serde(tag = "kind")]
pub enum TransactionArg {
GasCoin,
Input { index: u16 },
Result { index: u16 },
Input {
index: u16,
},
Result {
index: u16,
},
#[serde(rename_all = "camelCase")]
NestedResult {
index: u16,
result_index: u16,
},
}

impl From<TransactionArg> for Argument {
Expand All @@ -89,6 +155,10 @@ impl From<TransactionArg> for Argument {
TransactionArg::GasCoin => Argument::GasCoin,
TransactionArg::Input { index } => Argument::Input(index),
TransactionArg::Result { index } => Argument::Result(index),
TransactionArg::NestedResult {
index,
result_index,
} => Argument::NestedResult(index, result_index),
}
}
}
Expand All @@ -105,10 +175,6 @@ impl From<TypeTagWrapper> for TypeTag {
#[derive(Debug, Deserialize, Serialize)]
#[serde(tag = "kind")]
pub enum Transaction {
SplitCoins {
coin: TransactionArg,
amounts: Vec<TransactionArg>,
},
#[serde(rename_all = "camelCase")]
MoveCall {
target: String,
Expand All @@ -119,14 +185,144 @@ pub enum Transaction {
objects: Vec<TransactionArg>,
address: TransactionArg,
},
SplitCoins {
coin: TransactionArg,
amounts: Vec<TransactionArg>,
},
MergeCoins {
destination: TransactionArg,
sources: Vec<TransactionArg>,
},
Publish {
modules: Vec<Data>,
dependencies: Vec<String>,
},
#[serde(rename_all = "camelCase")]
MakeMoveVec {
type_tag: Option<TypeTagWrapper>,
arguments: Vec<TransactionArg>,
},
#[serde(rename_all = "camelCase")]
Upgrade {
modules: Vec<Data>,
dependencies: Vec<String>,
package_id: String,
ticket: TransactionArg,
},
}

impl TryFrom<Transaction> for Command {
type Error = SigningError;

fn try_from(transaction: Transaction) -> Result<Self, Self::Error> {
match transaction {
Transaction::MoveCall {
target,
type_arguments,
arguments,
} => {
let parts: Vec<&str> = target.split("::").collect();
if parts.len() != 3 {
return SigningError::err(SigningErrorType::Error_invalid_params)
.context("Invalid target format for MoveCall command");
}
let package = ObjectID::from_str(parts[0]).context("Failed to parse package ID")?;
let module = Identifier::from_str(parts[1])
.tw_err(|_| SigningErrorType::Error_invalid_params)
.context("Failed to parse module")?;
let function = Identifier::from_str(parts[2])
.tw_err(|_| SigningErrorType::Error_invalid_params)
.context("Failed to parse function")?;
Ok(Command::move_call(
package,
module,
function,
type_arguments.into_iter().map(|tag| tag.into()).collect(),
arguments
.into_iter()
.map(|argument| argument.into())
.collect(),
))
},
Transaction::TransferObjects { objects, address } => Ok(Command::TransferObjects(
objects.into_iter().map(|object| object.into()).collect(),
address.into(),
)),
Transaction::SplitCoins { coin, amounts } => Ok(Command::SplitCoins(
coin.into(),
amounts.into_iter().map(|amount| amount.into()).collect(),
)),
Transaction::MergeCoins {
destination,
sources,
} => Ok(Command::MergeCoins(
destination.into(),
sources.into_iter().map(|source| source.into()).collect(),
)),
Transaction::Publish {
modules,
dependencies,
} => Ok(Command::Publish(
modules,
dependencies
.into_iter()
.map(|dependency| {
ObjectID::from_str(&dependency).context("Failed to parse object ID")
})
.collect::<SigningResult<Vec<_>>>()?,
)),
Transaction::MakeMoveVec {
type_tag,
arguments,
} => Ok(Command::MakeMoveVec(
type_tag.map(|tag| tag.into()),
arguments
.into_iter()
.map(|argument| argument.into())
.collect(),
)),
Transaction::Upgrade {
modules,
dependencies,
package_id,
ticket,
} => Ok(Command::Upgrade(
modules,
dependencies
.into_iter()
.map(|dependency| {
ObjectID::from_str(&dependency).context("Failed to parse object ID")
})
.collect::<SigningResult<Vec<_>>>()?,
ObjectID::from_str(&package_id).context("Failed to parse object ID")?,
ticket.into(),
)),
}
}
}

// Taken from here: https://github.com/MystenLabs/ts-sdks/blob/68e1b649c125f031b72ff7816d1ff653ef47cb53/packages/typescript/src/transactions/data/v1.ts#L271
#[derive(Debug, Deserialize, Serialize)]
pub enum Expiration {
None(bool),
Epoch(u64),
}

impl From<Expiration> for TransactionExpiration {
fn from(expiration: Expiration) -> Self {
match expiration {
Expiration::None(_) => TransactionExpiration::None,
Expiration::Epoch(epoch) => TransactionExpiration::Epoch(epoch),
}
}
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RawTransaction {
pub version: u8,
pub sender: SuiAddress,
pub expiration: Option<u64>,
pub expiration: Option<Expiration>,
pub gas_config: GasConfig,
pub inputs: Vec<Input>,
pub transactions: Vec<Transaction>,
Expand Down
4 changes: 4 additions & 0 deletions rust/chains/tw_sui/src/transaction/sui_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ impl CallArg {
pub const SUI_SYSTEM_MUT: Self = Self::Object(ObjectArg::SUI_SYSTEM_MUT);
}

// Taken from here: https://github.com/MystenLabs/sui/blob/93f02057bb55eca407f04f551e6514f123005b65/crates/sui-types/src/transaction.rs#L107
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub enum ObjectArg {
// A Move object, either immutable, or owned mutable.
Expand All @@ -72,6 +73,8 @@ pub enum ObjectArg {
initial_shared_version: SequenceNumber,
mutable: bool,
},
// A Move object that can be received in this transaction.
Receiving(ObjectRef),
}

impl ObjectArg {
Expand All @@ -84,6 +87,7 @@ impl ObjectArg {
pub fn id(&self) -> ObjectID {
match self {
ObjectArg::ImmOrOwnedObject((id, _, _)) | ObjectArg::SharedObject { id, .. } => *id,
ObjectArg::Receiving((id, _, _)) => *id,
}
}
}
Expand Down
Loading
Loading