From 4afe330048945c55a265d3b20d9467c706f70ab4 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Fri, 2 Aug 2024 09:29:01 -0400 Subject: [PATCH] feat: add published events to if-write --- FULL_HELP_DOCS.md | 8 ++-- .../src/commands/contract/invoke.rs | 39 ++++++++++++------- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 30aa9f9cb..8eda3d4b7 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -480,7 +480,7 @@ stellar contract invoke ... -- --help ###### **Options:** * `--id ` — Contract ID to invoke -* `--is-view` — View the result simulating and do not sign and submit transaction. Deprecated use `--send=no` +* `--is-view` — View the result simulating and do not sign and submit transaction. Ieprecated use `--send=no` * `--rpc-url ` — RPC server endpoint * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config @@ -501,11 +501,11 @@ stellar contract invoke ... -- --help Possible values: - `if-write`: - Send the transaction to the network if there are ledger writes or events published, otherwise output the simulation result and do not send to the network + Only send transaction if there are ledger writes or published events, otherwise return simulation result - `no`: - Do not send the transaction to the network, and output the simulation result + Do not send transaction, return simulation result - `yes`: - Send the transaction to the network, and output the transaction result + Always send transaction diff --git a/cmd/soroban-cli/src/commands/contract/invoke.rs b/cmd/soroban-cli/src/commands/contract/invoke.rs index ccb8bf315..79f0bfcba 100644 --- a/cmd/soroban-cli/src/commands/contract/invoke.rs +++ b/cmd/soroban-cli/src/commands/contract/invoke.rs @@ -12,11 +12,12 @@ use heck::ToKebabCase; use soroban_env_host::{ xdr::{ - self, AccountEntry, AccountEntryExt, AccountId, Hash, HostFunction, InvokeContractArgs, - InvokeHostFunctionOp, LedgerEntryData, Limits, Memo, MuxedAccount, Operation, - OperationBody, Preconditions, PublicKey, ScAddress, ScSpecEntry, ScSpecFunctionV0, - ScSpecTypeDef, ScVal, ScVec, SequenceNumber, String32, StringM, Thresholds, Transaction, - TransactionExt, Uint256, VecM, WriteXdr, + self, AccountEntry, AccountEntryExt, AccountId, ContractEvent, ContractEventType, + DiagnosticEvent, Hash, HostFunction, InvokeContractArgs, InvokeHostFunctionOp, + LedgerEntryData, Limits, Memo, MuxedAccount, Operation, OperationBody, Preconditions, + PublicKey, ScAddress, ScSpecEntry, ScSpecFunctionV0, ScSpecTypeDef, ScVal, ScVec, + SequenceNumber, String32, StringM, Thresholds, Transaction, TransactionExt, Uint256, VecM, + WriteXdr, }, HostError, }; @@ -45,7 +46,7 @@ pub struct Cmd { // For testing only #[arg(skip)] pub wasm: Option, - /// View the result simulating and do not sign and submit transaction. Deprecated use `--send=no` + /// View the result simulating and do not sign and submit transaction. Ieprecated use `--send=no` #[arg(long, env = "STELLAR_INVOKE_VIEW")] pub is_view: bool, /// Function name as subcommand, then arguments for that function as `--arg-name value` @@ -558,7 +559,7 @@ Note: The only types which aren't JSON are Bytes and BytesN, which are raw bytes #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, ValueEnum, Default)] pub enum Send { - /// Only send transaction if there are ledger writes, otherwise return simulation result + /// Only send transaction if there are ledger writes or published events, otherwise return simulation result #[default] IfWrite, /// Do not send transaction, return simulation result @@ -570,14 +571,26 @@ pub enum Send { impl Send { pub fn should_send(self, sim_res: &SimulateTransactionResponse) -> Result { Ok(match self { - Send::IfWrite => !sim_res - .transaction_data()? - .resources - .footprint - .read_write - .is_empty(), + Send::IfWrite => has_write(sim_res)? || has_published_event(sim_res)?, Send::No => false, Send::Yes => true, }) } } + +fn has_write(sim_res: &SimulateTransactionResponse) -> Result { + Ok(!sim_res + .transaction_data()? + .resources + .footprint + .read_write + .is_empty()) +} +fn has_published_event(sim_res: &SimulateTransactionResponse) -> Result { + Ok(!sim_res.events()?.iter().any( + |DiagnosticEvent { + event: ContractEvent { type_, .. }, + .. + }| matches!(type_, ContractEventType::Contract), + )) +}