From c994b7dcb249d0b8dd8e47073f92453657662cae Mon Sep 17 00:00:00 2001 From: kien6034 Date: Wed, 23 Oct 2024 10:26:17 +0700 Subject: [PATCH 1/7] feat: base func for parseunints and formatuints --- crates/cast/bin/args.rs | 20 ++++++++++++++++++++ crates/cast/bin/main.rs | 8 ++++++++ crates/cast/src/lib.rs | 12 ++++++++++++ 3 files changed, 40 insertions(+) diff --git a/crates/cast/bin/args.rs b/crates/cast/bin/args.rs index fdb6a113354a..fb8c4e39fe28 100644 --- a/crates/cast/bin/args.rs +++ b/crates/cast/bin/args.rs @@ -230,6 +230,26 @@ pub enum CastSubcommand { unit: String, }, + /// Convert a number into a uint. + #[command(visible_aliases = &["--parse-uints", "pu"])] + ParseUints { + /// The value to convert. + value: Option, + + /// The unit to convert to. + unit: u8, + }, + + /// Format a number into a unit. + #[command(visible_aliases = &["--format-units", "fu"])] + FormatUnits { + /// The value to format. + value: Option, + + /// The unit to format to. + unit: u8, + }, + /// Convert an ETH amount to wei. /// /// Consider using --to-unit. diff --git a/crates/cast/bin/main.rs b/crates/cast/bin/main.rs index 607f4439188a..6895650c726e 100644 --- a/crates/cast/bin/main.rs +++ b/crates/cast/bin/main.rs @@ -121,6 +121,14 @@ async fn main_args(args: CastArgs) -> Result<()> { let value = stdin::unwrap_line(value)?; println!("{}", SimpleCast::to_unit(&value, &unit)?); } + CastSubcommand::ParseUints { value, unit } => { + let value = stdin::unwrap_line(value)?; + println!("{}", SimpleCast::parse_units(&value, unit)?); + } + CastSubcommand::FormatUnits { value, unit } => { + let value = stdin::unwrap_line(value)?; + println!("{}", SimpleCast::format_units(&value, unit)?); + } CastSubcommand::FromWei { value, unit } => { let value = stdin::unwrap_line(value)?; println!("{}", SimpleCast::from_wei(&value, &unit)?); diff --git a/crates/cast/src/lib.rs b/crates/cast/src/lib.rs index 69f86268b3d0..773218ba2ca1 100644 --- a/crates/cast/src/lib.rs +++ b/crates/cast/src/lib.rs @@ -1364,6 +1364,18 @@ impl SimpleCast { Ok(formatted) } + pub fn parse_units(value: &str, unit: u8) -> Result { + let unit = Unit::new(unit).ok_or_else(|| eyre::eyre!("invalid unit"))?; + + Ok(ParseUnits::parse_units(value, unit)?.to_string()) + } + + pub fn format_units(value: &str, unit: u8) -> Result { + let value = NumberWithBase::parse_int(value, None)?.number(); + let unit = Unit::new(unit).ok_or_else(|| eyre::eyre!("invalid unit"))?; + Ok(ParseUnits::U256(value).format_units(unit)) + } + /// Converts wei into an eth amount /// /// # Example From 1a2599ab3b3f5b97d6e235f576b0a70a3a29c99f Mon Sep 17 00:00:00 2001 From: kien6034 Date: Wed, 23 Oct 2024 10:42:32 +0700 Subject: [PATCH 2/7] test: update doc and tests --- crates/cast/bin/args.rs | 14 ++++++++++++-- crates/cast/src/lib.rs | 42 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/crates/cast/bin/args.rs b/crates/cast/bin/args.rs index fb8c4e39fe28..6ca23d4191ee 100644 --- a/crates/cast/bin/args.rs +++ b/crates/cast/bin/args.rs @@ -230,7 +230,12 @@ pub enum CastSubcommand { unit: String, }, - /// Convert a number into a uint. + /// Convert a number into a uint with arbitrary decimals. + /// + /// Examples: + /// - 1.0 6 (for USDC, result: 1000000) + /// - 2.5 12 (for 12 decimals token, result: 2500000000000) + /// - 1.23 3 (for 3 decimals token, result: 1230) #[command(visible_aliases = &["--parse-uints", "pu"])] ParseUints { /// The value to convert. @@ -240,7 +245,12 @@ pub enum CastSubcommand { unit: u8, }, - /// Format a number into a unit. + /// Format a number from smallest unit to decimal with arbitrary decimals. + /// + /// Examples: + /// - 1000000 6 (for USDC, result: 1.0) + /// - 2500000000000 12 (for 12 decimals, result: 2.5) + /// - 1230 3 (for 3 decimals, result: 1.23) #[command(visible_aliases = &["--format-units", "fu"])] FormatUnits { /// The value to format. diff --git a/crates/cast/src/lib.rs b/crates/cast/src/lib.rs index 773218ba2ca1..6b225754f754 100644 --- a/crates/cast/src/lib.rs +++ b/crates/cast/src/lib.rs @@ -1364,16 +1364,56 @@ impl SimpleCast { Ok(formatted) } + /// Convert a number into a uint with arbitrary decimals. + /// + /// # Example + /// + /// ``` + /// use cast::SimpleCast as Cast; + /// + /// # fn main() -> eyre::Result<()> { + /// assert_eq!(Cast::parse_units("1.0", 6)?, "1000000"); // USDC (6 decimals) + /// assert_eq!(Cast::parse_units("2.5", 6)?, "2500000"); + /// assert_eq!(Cast::parse_units("1.0", 12)?, "1000000000000"); // 12 decimals + /// assert_eq!(Cast::parse_units("1.23", 3)?, "1230"); // 3 decimals + /// # Ok(()) + /// # } + /// ``` pub fn parse_units(value: &str, unit: u8) -> Result { let unit = Unit::new(unit).ok_or_else(|| eyre::eyre!("invalid unit"))?; Ok(ParseUnits::parse_units(value, unit)?.to_string()) } + /// Format a number from smallest unit to decimal with arbitrary decimals. + /// + /// # Example + /// + /// ``` + /// use cast::SimpleCast as Cast; + /// + /// # fn main() -> eyre::Result<()> { + /// assert_eq!(Cast::format_units("1000000", 6)?, "1"); // USDC (6 decimals) + /// assert_eq!(Cast::format_units("2500000", 6)?, "2.500000"); + /// assert_eq!(Cast::format_units("1000000000000", 12)?, "1"); // 12 decimals + /// assert_eq!(Cast::format_units("1230", 3)?, "1.230"); // 3 decimals + /// # Ok(()) + /// # } + /// ``` pub fn format_units(value: &str, unit: u8) -> Result { let value = NumberWithBase::parse_int(value, None)?.number(); let unit = Unit::new(unit).ok_or_else(|| eyre::eyre!("invalid unit"))?; - Ok(ParseUnits::U256(value).format_units(unit)) + let mut formatted = ParseUnits::U256(value).format_units(unit); + + // Trim empty fractional part. + if let Some(dot) = formatted.find('.') { + let fractional = &formatted[dot + 1..]; + if fractional.chars().all(|c: char| c == '0') { + formatted = formatted[..dot].to_string(); + } + } + + Ok(formatted) } /// Converts wei into an eth amount From 1ccb70e454b1e0a15b06b0c460159df49ce6313d Mon Sep 17 00:00:00 2001 From: kien6034 Date: Wed, 23 Oct 2024 23:43:20 +0700 Subject: [PATCH 3/7] fix: function alias --- crates/cast/bin/args.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/cast/bin/args.rs b/crates/cast/bin/args.rs index 6ca23d4191ee..3d63acf238fa 100644 --- a/crates/cast/bin/args.rs +++ b/crates/cast/bin/args.rs @@ -236,12 +236,13 @@ pub enum CastSubcommand { /// - 1.0 6 (for USDC, result: 1000000) /// - 2.5 12 (for 12 decimals token, result: 2500000000000) /// - 1.23 3 (for 3 decimals token, result: 1230) - #[command(visible_aliases = &["--parse-uints", "pu"])] + #[command(visible_aliases = &["--parse-uints", "pun"])] ParseUints { /// The value to convert. value: Option, /// The unit to convert to. + #[arg(default_value = "18")] unit: u8, }, @@ -251,12 +252,13 @@ pub enum CastSubcommand { /// - 1000000 6 (for USDC, result: 1.0) /// - 2500000000000 12 (for 12 decimals, result: 2.5) /// - 1230 3 (for 3 decimals, result: 1.23) - #[command(visible_aliases = &["--format-units", "fu"])] + #[command(visible_aliases = &["--format-units", "fun"])] FormatUnits { /// The value to format. value: Option, /// The unit to format to. + #[arg(default_value = "18")] unit: u8, }, From b128ce0265aed012ccb96d6467285c853a616d30 Mon Sep 17 00:00:00 2001 From: kien6034 Date: Thu, 24 Oct 2024 00:42:43 +0700 Subject: [PATCH 4/7] test: cast test --- crates/cast/bin/args.rs | 6 +++--- crates/cast/bin/main.rs | 2 +- crates/cast/tests/cli/main.rs | 36 +++++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/crates/cast/bin/args.rs b/crates/cast/bin/args.rs index 3d63acf238fa..7f421ed442b6 100644 --- a/crates/cast/bin/args.rs +++ b/crates/cast/bin/args.rs @@ -230,14 +230,14 @@ pub enum CastSubcommand { unit: String, }, - /// Convert a number into a uint with arbitrary decimals. + /// Convert a number from decimal to smallest unit with arbitrary decimals. /// /// Examples: /// - 1.0 6 (for USDC, result: 1000000) /// - 2.5 12 (for 12 decimals token, result: 2500000000000) /// - 1.23 3 (for 3 decimals token, result: 1230) - #[command(visible_aliases = &["--parse-uints", "pun"])] - ParseUints { + #[command(visible_aliases = &["--parse-units", "pun"])] + ParseUnits { /// The value to convert. value: Option, diff --git a/crates/cast/bin/main.rs b/crates/cast/bin/main.rs index 6895650c726e..0a8fce61a208 100644 --- a/crates/cast/bin/main.rs +++ b/crates/cast/bin/main.rs @@ -121,7 +121,7 @@ async fn main_args(args: CastArgs) -> Result<()> { let value = stdin::unwrap_line(value)?; println!("{}", SimpleCast::to_unit(&value, &unit)?); } - CastSubcommand::ParseUints { value, unit } => { + CastSubcommand::ParseUnits { value, unit } => { let value = stdin::unwrap_line(value)?; println!("{}", SimpleCast::parse_units(&value, unit)?); } diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index 5487dc9f374b..478836fc773a 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -1375,3 +1375,39 @@ casttest!(hash_message, |_prj, cmd| { "#]]); }); + +casttest!(parse_uints, |_prj, cmd| { + cmd.args(["parse-units", "1.5", "6"]).assert_success().stdout_eq(str![[r#" +1500000 + +"#]]); + + cmd.cast_fuse().args(["pun", "1.23", "18"]).assert_success().stdout_eq(str![[r#" +1230000000000000000 + +"#]]); + + cmd.cast_fuse().args(["--parse-units", "1.23", "3"]).assert_success().stdout_eq(str![[r#" +1230 + +"#]]); +}); + +casttest!(format_units, |_prj, cmd| { + cmd.args(["format-units", "1000000", "6"]).assert_success().stdout_eq(str![[r#" +1 + +"#]]); + + cmd.cast_fuse().args(["--format-units", "2500000", "6"]).assert_success().stdout_eq(str![[ + r#" +2.500000 + +"# + ]]); + + cmd.cast_fuse().args(["fun", "1230", "3"]).assert_success().stdout_eq(str![[r#" +1.230 + +"#]]); +}); From 9aea6f31222701c7fa1ad3970e3c3a31fbd5237e Mon Sep 17 00:00:00 2001 From: kien6034 Date: Thu, 24 Oct 2024 16:42:57 +0700 Subject: [PATCH 5/7] refacctor: helper fucnction --- crates/cast/src/lib.rs | 21 +++++++-------------- crates/cast/tests/cli/main.rs | 2 +- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/crates/cast/src/lib.rs b/crates/cast/src/lib.rs index 56ceafe1be85..3ebb894509b1 100644 --- a/crates/cast/src/lib.rs +++ b/crates/cast/src/lib.rs @@ -1351,17 +1351,7 @@ impl SimpleCast { .wrap_err("Could not convert to uint")? .0; let unit = unit.parse().wrap_err("could not parse units")?; - let mut formatted = ParseUnits::U256(value).format_units(unit); - - // Trim empty fractional part. - if let Some(dot) = formatted.find('.') { - let fractional = &formatted[dot + 1..]; - if fractional.chars().all(|c: char| c == '0') { - formatted = formatted[..dot].to_string(); - } - } - - Ok(formatted) + Ok(Self::format_unit_as_string(value, unit)) } /// Convert a number into a uint with arbitrary decimals. @@ -1403,8 +1393,12 @@ impl SimpleCast { pub fn format_units(value: &str, unit: u8) -> Result { let value = NumberWithBase::parse_int(value, None)?.number(); let unit = Unit::new(unit).ok_or_else(|| eyre::eyre!("invalid unit"))?; - let mut formatted = ParseUnits::U256(value).format_units(unit); + Ok(Self::format_unit_as_string(value, unit)) + } + // Helper function to format units as a string + fn format_unit_as_string(value: U256, unit: Unit) -> String { + let mut formatted = ParseUnits::U256(value).format_units(unit); // Trim empty fractional part. if let Some(dot) = formatted.find('.') { let fractional = &formatted[dot + 1..]; @@ -1412,8 +1406,7 @@ impl SimpleCast { formatted = formatted[..dot].to_string(); } } - - Ok(formatted) + formatted } /// Converts wei into an eth amount diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index b066701c26bf..c88e1cd3a236 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -1405,7 +1405,7 @@ casttest!(parse_uints, |_prj, cmd| { "#]]); }); -casttest!(format_units, |_prj, cmd| { +casttest!(parse_units, |_prj, cmd| { cmd.args(["format-units", "1000000", "6"]).assert_success().stdout_eq(str![[r#" 1 From 7e4030cc79c1a89a8a0766755f6283ca738022c0 Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Thu, 24 Oct 2024 13:09:38 +0300 Subject: [PATCH 6/7] Update crates/cast/tests/cli/main.rs --- crates/cast/tests/cli/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index c88e1cd3a236..304ded3a4118 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -1388,7 +1388,7 @@ casttest!(hash_message, |_prj, cmd| { "#]]); }); -casttest!(parse_uints, |_prj, cmd| { +casttest!(parse_units, |_prj, cmd| { cmd.args(["parse-units", "1.5", "6"]).assert_success().stdout_eq(str![[r#" 1500000 From 026cc41fe4d329e022b7143702fc47eef4efc518 Mon Sep 17 00:00:00 2001 From: kien6034 Date: Thu, 24 Oct 2024 17:19:29 +0700 Subject: [PATCH 7/7] revert: format uints function cattest func name --- crates/cast/tests/cli/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index 304ded3a4118..d6023509ac76 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -1405,7 +1405,7 @@ casttest!(parse_units, |_prj, cmd| { "#]]); }); -casttest!(parse_units, |_prj, cmd| { +casttest!(format_units, |_prj, cmd| { cmd.args(["format-units", "1000000", "6"]).assert_success().stdout_eq(str![[r#" 1