diff --git a/cast/src/lib.rs b/cast/src/lib.rs index aee5b1d4..a5634e03 100644 --- a/cast/src/lib.rs +++ b/cast/src/lib.rs @@ -3,7 +3,10 @@ //! TODO use chrono::NaiveDateTime; use ethers_core::{ - abi::{Abi, AbiParser, Token}, + abi::{ + token::{LenientTokenizer, Tokenizer}, + Abi, AbiParser, Token, + }, types::{Chain, *}, utils::{self, keccak256}, }; @@ -786,6 +789,35 @@ impl SimpleCast { Ok(format!("0x{}{}", "0".repeat(64 - num_hex.len()), num_hex)) } + /// Converts an eth amount into a specified unit + /// + /// ``` + /// use cast::SimpleCast as Cast; + /// + /// fn main() -> eyre::Result<()> { + /// assert_eq!(Cast::to_unit("1 wei".to_string(), "wei".to_string())?, "1"); + /// assert_eq!(Cast::to_unit("1".to_string(), "wei".to_string())?, "1"); + /// assert_eq!(Cast::to_unit("1ether".to_string(), "wei".to_string())?, "1000000000000000000"); + /// assert_eq!(Cast::to_unit("100 gwei".to_string(), "gwei".to_string())?, "100"); + /// + /// Ok(()) + /// } + /// ``` + pub fn to_unit(value: String, unit: String) -> Result { + let value = U256::from(LenientTokenizer::tokenize_uint(&value)?); + + Ok(match &unit[..] { + "ether" => ethers_core::utils::format_units(value, 18)? + .trim_end_matches(".000000000000000000") + .to_string(), + "gwei" | "nano" | "nanoether" => ethers_core::utils::format_units(value, 9)? + .trim_end_matches(".000000000") + .to_string(), + "wei" => ethers_core::utils::format_units(value, 0)?.trim_end_matches(".0").to_string(), + _ => return Err(eyre::eyre!("invalid unit")), + }) + } + /// Converts an eth amount into wei /// /// ``` diff --git a/cli/src/cast.rs b/cli/src/cast.rs index 1cc5f699..0777ec83 100644 --- a/cli/src/cast.rs +++ b/cli/src/cast.rs @@ -107,6 +107,10 @@ async fn main() -> eyre::Result<()> { let val = unwrap_or_stdin(value)?; println!("{}", SimpleCast::to_uint256(&val)?); } + Subcommands::ToUnit { value, unit } => { + let val = unwrap_or_stdin(value)?; + println!("{}", SimpleCast::to_unit(val, unit.unwrap_or_else(|| String::from("wei")))?); + } Subcommands::ToWei { value, unit } => { let val = unwrap_or_stdin(value)?; println!( diff --git a/cli/src/opts/cast.rs b/cli/src/opts/cast.rs index ccd5b0c7..e87f8385 100644 --- a/cli/src/opts/cast.rs +++ b/cli/src/opts/cast.rs @@ -54,11 +54,23 @@ pub enum Subcommands { #[clap(name = "--to-uint256")] #[clap(about = "convert a number into uint256 hex string with 0x prefix")] ToUint256 { value: Option }, + #[clap(name = "--to-unit")] + #[clap( + about = r#"convert an ETH amount into a specified unit: ether, gwei or wei (default: wei). + Usage: + - 1ether wei | converts 1 ether to wei + - "1 ether" wei | converts 1 ether to wei + - 1ether | converts 1 ether to wei + - 1 gwei | converts 1 wei to gwei + - 1gwei ether | converts 1 gwei to ether + "# + )] + ToUnit { value: Option, unit: Option }, #[clap(name = "--to-wei")] - #[clap(about = "convert an ETH amount into wei")] + #[clap(about = "convert an ETH amount into wei. Consider using --to-unit.")] ToWei { value: Option, unit: Option }, #[clap(name = "--from-wei")] - #[clap(about = "convert wei into an ETH amount")] + #[clap(about = "convert wei into an ETH amount. Consider using --to-unit.")] FromWei { value: Option, unit: Option }, #[clap(name = "block")] #[clap(