diff --git a/Cargo.lock b/Cargo.lock index 0588e0451a2..0e7cef84098 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6176,6 +6176,7 @@ version = "0.0.0" dependencies = [ "anyhow", "bcs", + "clap", "colored", "enum_dispatch", "fastcrypto", diff --git a/crates/iota-json-rpc-types/Cargo.toml b/crates/iota-json-rpc-types/Cargo.toml index 96baec66d2e..f62c781580f 100644 --- a/crates/iota-json-rpc-types/Cargo.toml +++ b/crates/iota-json-rpc-types/Cargo.toml @@ -23,6 +23,8 @@ serde_json.workspace = true serde_with.workspace = true tabled.workspace = true tracing.workspace = true +clap = { version = "4.0", features = ["derive"] } + move-binary-format.workspace = true move-bytecode-utils.workspace = true diff --git a/crates/iota-json-rpc-types/src/iota_transaction.rs b/crates/iota-json-rpc-types/src/iota_transaction.rs index 9a40e65bcb4..9dd842da38a 100644 --- a/crates/iota-json-rpc-types/src/iota_transaction.rs +++ b/crates/iota-json-rpc-types/src/iota_transaction.rs @@ -49,6 +49,7 @@ use tabled::{ builder::Builder as TableBuilder, settings::{style::HorizontalLine, Panel as TablePanel, Style as TableStyle}, }; +use clap::Parser; use crate::{ balance_changes::BalanceChange, iota_transaction::GenericSignature::Signature, @@ -96,20 +97,34 @@ pub type TransactionBlocksPage = Page bool { self == &Self::default() } + + pub fn from_cli(mut self, opts: Vec) -> Self { + if opts.contains(&"input".to_string()) { + self.show_input = true; + } + if opts.contains(&"effects".to_string()) { + self.show_effects = true; + } + if opts.contains(&"events".to_string()) { + self.show_events = true; + } + if opts.contains(&"object_changes".to_string()) { + self.show_object_changes = true; + } + if opts.contains(&"balance_changes".to_string()) { + self.show_balance_changes = true; + } + self + } } #[serde_as] diff --git a/crates/iota-sdk/src/wallet_context.rs b/crates/iota-sdk/src/wallet_context.rs index 35eb62ed9f9..b3a724e30b1 100644 --- a/crates/iota-sdk/src/wallet_context.rs +++ b/crates/iota-sdk/src/wallet_context.rs @@ -299,9 +299,10 @@ impl WalletContext { pub async fn execute_transaction_must_succeed( &self, tx: Transaction, + opts: Vec, ) -> IotaTransactionBlockResponse { tracing::debug!("Executing transaction: {:?}", tx); - let response = self.execute_transaction_may_fail(tx).await.unwrap(); + let response = self.execute_transaction_may_fail(tx, Vec::new()).await.unwrap(); assert!( response.status_ok().unwrap(), "Transaction failed: {:?}", @@ -317,18 +318,14 @@ impl WalletContext { pub async fn execute_transaction_may_fail( &self, tx: Transaction, + opts: Vec, ) -> anyhow::Result { let client = self.get_client().await?; Ok(client .quorum_driver_api() .execute_transaction_block( tx, - IotaTransactionBlockResponseOptions::new() - .with_effects() - .with_input() - .with_events() - .with_object_changes() - .with_balance_changes(), + IotaTransactionBlockResponseOptions::new().from_cli(opts), Some(iota_types::quorum_driver_types::ExecuteTransactionRequestType::WaitForLocalExecution), ) .await?) diff --git a/crates/iota-test-transaction-builder/src/lib.rs b/crates/iota-test-transaction-builder/src/lib.rs index 45efb327b8a..a44a8bdbdb3 100644 --- a/crates/iota-test-transaction-builder/src/lib.rs +++ b/crates/iota-test-transaction-builder/src/lib.rs @@ -528,7 +528,7 @@ pub async fn publish_package(context: &WalletContext, path: PathBuf) -> ObjectRe .publish(path) .build(), ); - let resp = context.execute_transaction_must_succeed(txn).await; + let resp = context.execute_transaction_must_succeed(txn, Vec::new()).await; get_new_package_obj_from_response(&resp).unwrap() } @@ -542,7 +542,7 @@ pub async fn publish_basics_package(context: &WalletContext) -> ObjectRef { .publish_examples("basics") .build(), ); - let resp = context.execute_transaction_must_succeed(txn).await; + let resp = context.execute_transaction_must_succeed(txn, Vec::new()).await; get_new_package_obj_from_response(&resp).unwrap() } @@ -560,7 +560,7 @@ pub async fn publish_basics_package_and_make_counter( .build(), ); let resp = context - .execute_transaction_must_succeed(counter_creation_txn) + .execute_transaction_must_succeed(counter_creation_txn, Vec::new()) .await; let counter_ref = resp .effects @@ -599,7 +599,7 @@ pub async fn increment_counter( .call_counter_increment(package_id, counter_id, initial_shared_version) .build(), ); - context.execute_transaction_must_succeed(txn).await + context.execute_transaction_must_succeed(txn, Vec::new()).await } /// Executes a transaction to publish the `nfts` package and returns the package @@ -615,7 +615,7 @@ pub async fn publish_nfts_package( .publish_examples("nfts") .build(), ); - let resp = context.execute_transaction_must_succeed(txn).await; + let resp = context.execute_transaction_must_succeed(txn, Vec::new()).await; let package_id = get_new_package_obj_from_response(&resp).unwrap().0; (package_id, gas_id, resp.digest) } @@ -635,7 +635,7 @@ pub async fn create_devnet_nft( .call_nft_create(package_id) .build(), ); - let resp = context.execute_transaction_must_succeed(txn).await; + let resp = context.execute_transaction_must_succeed(txn, Vec::new()).await; let object_id = resp .effects @@ -668,5 +668,5 @@ pub async fn delete_devnet_nft( .call_nft_delete(package_id, nft_to_delete) .build(), ); - context.execute_transaction_must_succeed(txn).await + context.execute_transaction_must_succeed(txn, Vec::new()).await } diff --git a/crates/iota/src/client_commands.rs b/crates/iota/src/client_commands.rs index 0a461867f68..912e30a4592 100644 --- a/crates/iota/src/client_commands.rs +++ b/crates/iota/src/client_commands.rs @@ -85,7 +85,7 @@ mod profiler_tests; #[macro_export] macro_rules! serialize_or_execute { - ($tx_data:expr, $serialize_unsigned:expr, $serialize_signed:expr, $context:expr, $result_variant:ident) => {{ + ($tx_data:expr, $serialize_unsigned:expr, $serialize_signed:expr, $context:expr, $result_variant:ident, $opts:expr) => {{ assert!( !$serialize_unsigned || !$serialize_signed, "Cannot specify both --serialize-unsigned-transaction and --serialize-signed-transaction" @@ -107,7 +107,7 @@ macro_rules! serialize_or_execute { IotaClientCommandResult::SerializedSignedTransaction(sender_signed_data) } else { let transaction = Transaction::new(sender_signed_data); - let response = $context.execute_transaction_may_fail(transaction).await?; + let response = $context.execute_transaction_may_fail(transaction, $opts).await?; let effects = response.effects.as_ref().ok_or_else(|| { anyhow!("Effects from IotaTransactionBlockResult should not be empty") })?; @@ -178,7 +178,6 @@ pub enum IotaClientCommands { #[clap(long, num_args(1..))] args: Vec, /// ID of the gas object for gas payment, in 20 bytes Hex string - #[clap(long)] /// If not provided, a gas object with at least gas_budget value will be /// selected #[clap(long)] @@ -208,6 +207,12 @@ pub enum IotaClientCommands { /// `. #[clap(long, required = false)] serialize_signed_transaction: bool, + + /// Select which fields of the response to display. + /// If not provided, all fields are displayed. + /// The fields are: input, effects, events, object_changes, balance_changes. + #[clap(long, required = false)] + emit: Vec, }, /// Query the chain identifier from the rpc endpoint. @@ -1099,7 +1104,8 @@ impl IotaClientCommands { serialize_unsigned_transaction, serialize_signed_transaction, context, - Upgrade + Upgrade, + Vec::new() ) } IotaClientCommands::Publish { @@ -1155,7 +1161,8 @@ impl IotaClientCommands { serialize_unsigned_transaction, serialize_signed_transaction, context, - Publish + Publish, + Vec::new() ) } @@ -1266,6 +1273,7 @@ impl IotaClientCommands { args, serialize_unsigned_transaction, serialize_signed_transaction, + emit } => { let tx_data = construct_move_call_transaction( package, &module, &function, type_args, gas, gas_budget, gas_price, args, @@ -1277,7 +1285,8 @@ impl IotaClientCommands { serialize_unsigned_transaction, serialize_signed_transaction, context, - Call + Call, + emit ) } @@ -1301,7 +1310,8 @@ impl IotaClientCommands { serialize_unsigned_transaction, serialize_signed_transaction, context, - Transfer + Transfer, + Vec::new() ) } @@ -1325,7 +1335,8 @@ impl IotaClientCommands { serialize_unsigned_transaction, serialize_signed_transaction, context, - TransferIota + TransferIota, + Vec::new() ) } @@ -1370,7 +1381,8 @@ impl IotaClientCommands { serialize_unsigned_transaction, serialize_signed_transaction, context, - Pay + Pay, + Vec::new() ) } @@ -1414,7 +1426,8 @@ impl IotaClientCommands { serialize_unsigned_transaction, serialize_signed_transaction, context, - PayIota + PayIota, + Vec::new() ) } @@ -1442,7 +1455,8 @@ impl IotaClientCommands { serialize_unsigned_transaction, serialize_signed_transaction, context, - PayAllIota + PayAllIota, + Vec::new() ) } @@ -1582,7 +1596,8 @@ impl IotaClientCommands { serialize_unsigned_transaction, serialize_signed_transaction, context, - SplitCoin + SplitCoin, + Vec::new() ) } IotaClientCommands::MergeCoin { @@ -1604,7 +1619,8 @@ impl IotaClientCommands { serialize_unsigned_transaction, serialize_signed_transaction, context, - MergeCoin + MergeCoin, + Vec::new() ) } IotaClientCommands::Switch { address, env } => { @@ -1660,7 +1676,7 @@ impl IotaClientCommands { } let transaction = Transaction::from_generic_sig_data(data, sigs); - let response = context.execute_transaction_may_fail(transaction).await?; + let response = context.execute_transaction_may_fail(transaction, Vec::new()).await?; IotaClientCommandResult::ExecuteSignedTx(response) } IotaClientCommands::ExecuteCombinedSignedTx { signed_tx_bytes } => { @@ -1671,7 +1687,7 @@ impl IotaClientCommands { .map_err(|_| anyhow!("Invalid Base64 encoding"))? ).map_err(|_| anyhow!("Failed to parse SenderSignedData bytes, check if it matches the output of iota client commands with --serialize-signed-transaction"))?; let transaction = Envelope::::new(data); - let response = context.execute_transaction_may_fail(transaction).await?; + let response = context.execute_transaction_may_fail(transaction, Vec::new()).await?; IotaClientCommandResult::ExecuteSignedTx(response) } IotaClientCommands::NewEnv { alias, rpc, ws } => { diff --git a/crates/iota/src/client_ptb/ptb.rs b/crates/iota/src/client_ptb/ptb.rs index f039a5e6b54..00aaa9232ab 100644 --- a/crates/iota/src/client_ptb/ptb.rs +++ b/crates/iota/src/client_ptb/ptb.rs @@ -168,12 +168,12 @@ impl PTB { ); if program_metadata.serialize_unsigned_set { - serialize_or_execute!(tx_data, true, false, context, PTB).print(true); + serialize_or_execute!(tx_data, true, false, context, PTB, Vec::new()).print(true); return Ok(()); } if program_metadata.serialize_signed_set { - serialize_or_execute!(tx_data, false, true, context, PTB).print(true); + serialize_or_execute!(tx_data, false, true, context, PTB, Vec::new()).print(true); return Ok(()); } diff --git a/crates/iota/tests/cli_tests.rs b/crates/iota/tests/cli_tests.rs index c24ab755557..58ea7b3914d 100644 --- a/crates/iota/tests/cli_tests.rs +++ b/crates/iota/tests/cli_tests.rs @@ -313,6 +313,7 @@ async fn test_ptb_publish_and_complex_arg_resolution() -> Result<(), anyhow::Err args: vec![], serialize_unsigned_transaction: false, serialize_signed_transaction: false, + emit: Vec::new(), } .execute(context) .await?; @@ -660,6 +661,7 @@ async fn test_move_call_args_linter_command() -> Result<(), anyhow::Error> { gas_price: None, serialize_unsigned_transaction: false, serialize_signed_transaction: false, + emit: Vec::new(), } .execute(context) .await?; @@ -700,6 +702,7 @@ async fn test_move_call_args_linter_command() -> Result<(), anyhow::Error> { gas_price: None, serialize_unsigned_transaction: false, serialize_signed_transaction: false, + emit: Vec::new(), } .execute(context) .await; @@ -727,6 +730,7 @@ async fn test_move_call_args_linter_command() -> Result<(), anyhow::Error> { gas_price: None, serialize_unsigned_transaction: false, serialize_signed_transaction: false, + emit: Vec::new(), } .execute(context) .await; @@ -751,6 +755,7 @@ async fn test_move_call_args_linter_command() -> Result<(), anyhow::Error> { gas_price: Some(1), serialize_unsigned_transaction: false, serialize_signed_transaction: false, + emit: Vec::new(), } .execute(context) .await; @@ -784,6 +789,7 @@ async fn test_move_call_args_linter_command() -> Result<(), anyhow::Error> { gas_price: None, serialize_unsigned_transaction: false, serialize_signed_transaction: false, + emit: Vec::new(), } .execute(context) .await?; @@ -805,6 +811,7 @@ async fn test_move_call_args_linter_command() -> Result<(), anyhow::Error> { gas_price: Some(12345), serialize_unsigned_transaction: false, serialize_signed_transaction: false, + emit: Vec::new(), } .execute(context) .await?; @@ -962,6 +969,7 @@ async fn test_delete_shared_object() -> Result<(), anyhow::Error> { args: vec![], serialize_unsigned_transaction: false, serialize_signed_transaction: false, + emit: Vec::new(), } .execute(context) .await?; @@ -985,6 +993,7 @@ async fn test_delete_shared_object() -> Result<(), anyhow::Error> { args: vec![IotaJsonValue::from_str(&shared_id.to_string()).unwrap()], serialize_unsigned_transaction: false, serialize_signed_transaction: false, + emit: Vec::new(), } .execute(context) .await?; @@ -1071,6 +1080,7 @@ async fn test_receive_argument() -> Result<(), anyhow::Error> { args: vec![], serialize_unsigned_transaction: false, serialize_signed_transaction: false, + emit: Vec::new(), } .execute(context) .await?; @@ -1113,6 +1123,7 @@ async fn test_receive_argument() -> Result<(), anyhow::Error> { ], serialize_unsigned_transaction: false, serialize_signed_transaction: false, + emit: Vec::new(), } .execute(context) .await?; @@ -1199,6 +1210,7 @@ async fn test_receive_argument_by_immut_ref() -> Result<(), anyhow::Error> { args: vec![], serialize_unsigned_transaction: false, serialize_signed_transaction: false, + emit: Vec::new(), } .execute(context) .await?; @@ -1241,6 +1253,7 @@ async fn test_receive_argument_by_immut_ref() -> Result<(), anyhow::Error> { ], serialize_unsigned_transaction: false, serialize_signed_transaction: false, + emit: Vec::new(), } .execute(context) .await?; @@ -1327,6 +1340,7 @@ async fn test_receive_argument_by_mut_ref() -> Result<(), anyhow::Error> { args: vec![], serialize_unsigned_transaction: false, serialize_signed_transaction: false, + emit: Vec::new(), } .execute(context) .await?; @@ -1369,6 +1383,7 @@ async fn test_receive_argument_by_mut_ref() -> Result<(), anyhow::Error> { ], serialize_unsigned_transaction: false, serialize_signed_transaction: false, + emit: Vec::new(), } .execute(context) .await?; diff --git a/crates/test-cluster/src/lib.rs b/crates/test-cluster/src/lib.rs index 10905559749..10769019214 100644 --- a/crates/test-cluster/src/lib.rs +++ b/crates/test-cluster/src/lib.rs @@ -562,7 +562,7 @@ impl TestCluster { /// ExecutionStatus::Success. This function is recommended for /// transaction execution since it most resembles the production path. pub async fn execute_transaction(&self, tx: Transaction) -> IotaTransactionBlockResponse { - self.wallet.execute_transaction_must_succeed(tx).await + self.wallet.execute_transaction_must_succeed(tx, Vec::new()).await } /// Different from `execute_transaction` which returns RPC effects types, @@ -582,7 +582,7 @@ impl TestCluster { let results = self .submit_transaction_to_validators(tx.clone(), &self.get_validator_pubkeys()) .await?; - self.wallet.execute_transaction_may_fail(tx).await.unwrap(); + self.wallet.execute_transaction_may_fail(tx, Vec::new()).await.unwrap(); Ok(results) } @@ -677,7 +677,7 @@ impl TestCluster { .transfer_iota(amount, funding_address) .build(), ); - context.execute_transaction_must_succeed(tx).await; + context.execute_transaction_must_succeed(tx, Vec::new()).await; context .get_one_gas_object_owned_by_address(funding_address)