From 5679a42abbab05b597c431acbc49aac3aaf45706 Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Sat, 18 Dec 2021 20:24:23 -0800 Subject: [PATCH] feat(cast): add tx command (#260) This commit ports the `seth tx` command to `cast`. It follows the implementation of `cast block` and includes the feature to print a specific field in the transaction as well as printing the result in JSON. ``` $ cast tx --rpc-url [field] ``` The flag `-j`/`--json` is used to print the result as JSON. --- cast/README.md | 4 ++-- cast/src/lib.rs | 42 +++++++++++++++++++++++++++++++++++++++++- cli/src/cast.rs | 4 ++++ cli/src/opts/cast.rs | 10 ++++++++++ 4 files changed, 57 insertions(+), 3 deletions(-) diff --git a/cast/README.md b/cast/README.md index 72636dba43a7..b57cfeeb6994 100644 --- a/cast/README.md +++ b/cast/README.md @@ -35,7 +35,7 @@ - [x] `calldata` - [x] `chain` - [x] `chain-id` -- [ ] `code` +- [x] `code` - [ ] `debug` - [ ] `estimate` - [ ] `etherscan-source` @@ -56,4 +56,4 @@ - [x] `send` (partial) - [ ] `sign` - [x] `storage` -- [ ] `tx` +- [x] `tx` diff --git a/cast/src/lib.rs b/cast/src/lib.rs index 099e5d46aa87..1488d93b2540 100644 --- a/cast/src/lib.rs +++ b/cast/src/lib.rs @@ -44,7 +44,7 @@ where /// Makes a read-only call to the specified address /// /// ```no_run - /// + /// /// use cast::Cast; /// use ethers_core::types::Address; /// use ethers_providers::{Provider, Http}; @@ -308,6 +308,46 @@ where ) -> Result { Ok(format!("{}", self.provider.get_code(who, block).await?)) } + + /// ```no_run + /// use cast::Cast; + /// use ethers_providers::{Provider, Http}; + /// use std::convert::TryFrom; + /// + /// # async fn foo() -> eyre::Result<()> { + /// let provider = Provider::::try_from("http://localhost:8545")?; + /// let cast = Cast::new(provider); + /// let tx_hash = "0xf8d1713ea15a81482958fb7ddf884baee8d3bcc478c5f2f604e008dc788ee4fc"; + /// let tx = cast.transaction(tx_hash.to_string(), None, false).await?; + /// println!("{}", tx); + /// # Ok(()) + /// # } + /// ``` + pub async fn transaction( + &self, + tx_hash: String, + field: Option, + to_json: bool, + ) -> Result { + let transaction_result = self + .provider + .get_transaction(H256::from_str(&tx_hash)?) + .await? + .ok_or_else(|| eyre::eyre!("transaction {:?} not found", tx_hash))?; + + let transaction = if let Some(ref field) = field { + serde_json::to_value(&transaction_result)? + .get(field) + .cloned() + .ok_or_else(|| eyre::eyre!("field {} not found", field))? + } else { + serde_json::to_value(&transaction_result)? + }; + + let transaction = + if to_json { serde_json::to_string(&transaction)? } else { to_table(transaction) }; + Ok(transaction) + } } pub struct SimpleCast; diff --git a/cli/src/cast.rs b/cli/src/cast.rs index cc83cbaa2159..393e434b76aa 100644 --- a/cli/src/cast.rs +++ b/cli/src/cast.rs @@ -124,6 +124,10 @@ async fn main() -> eyre::Result<()> { Subcommands::Namehash { name } => { println!("{}", SimpleCast::namehash(&name)?); } + Subcommands::Tx { rpc_url, hash, field, to_json } => { + let provider = Provider::try_from(rpc_url)?; + println!("{}", Cast::new(&provider).transaction(hash, field, to_json).await?) + } Subcommands::SendTx { eth, to, sig, cast_async, args } => { let provider = Provider::try_from(eth.rpc_url.as_str())?; let chain_id = Cast::new(&provider).chain_id().await?; diff --git a/cli/src/opts/cast.rs b/cli/src/opts/cast.rs index 1a7d0d314f8e..0e4b3d9b5f73 100644 --- a/cli/src/opts/cast.rs +++ b/cli/src/opts/cast.rs @@ -107,6 +107,16 @@ pub enum Subcommands { #[structopt(name = "namehash")] #[structopt(about = "returns ENS namehash of provided name")] Namehash { name: String }, + #[structopt(name = "tx")] + #[structopt(about = "Show information about the transaction ")] + Tx { + hash: String, + field: Option, + #[structopt(long = "--json", short = "-j")] + to_json: bool, + #[structopt(long, env = "ETH_RPC_URL")] + rpc_url: String, + }, #[structopt(name = "send")] #[structopt(about = "Publish a transaction signed by to call with ")] SendTx {