use alloy::primitives::U256;
#[cfg(not(feature = "high-precision"))]
use std::str::FromStr;
#[cfg(feature = "high-precision")]
use rust_decimal::Decimal;
#[cfg(not(feature = "high-precision"))]
pub fn eth_to_wei(eth_amount: f64) -> U256 {
let wei_str = format!("{:.0}", eth_amount * 1e18);
U256::from_str(&wei_str).unwrap_or(U256::ZERO)
}
#[cfg(feature = "high-precision")]
pub fn eth_to_wei(eth_amount: Decimal) -> U256 {
use rust_decimal::prelude::*;
let wei_amount = eth_amount * Decimal::from_str("1000000000000000000").unwrap();
let wei_str = wei_amount.to_string();
let integer_part = wei_str.split('.').next().unwrap_or("0");
U256::from_str(integer_part).unwrap_or(U256::ZERO)
}
#[cfg(not(feature = "high-precision"))]
pub fn wei_to_eth(wei_amount: U256) -> f64 {
let wei_str = wei_amount.to_string();
wei_str.parse::<f64>().unwrap_or(0.0) / 1e18
}
#[cfg(feature = "high-precision")]
pub fn wei_to_eth(wei_amount: U256) -> Decimal {
use rust_decimal::prelude::*;
let wei_str = wei_amount.to_string();
let wei_decimal = Decimal::from_str(&wei_str).unwrap_or(Decimal::ZERO);
let divisor = Decimal::from_str("1000000000000000000").unwrap();
wei_decimal / divisor
}
#[cfg(not(feature = "high-precision"))]
pub fn gwei_to_wei(gwei_amount: f64) -> U256 {
let wei_str = format!("{:.0}", gwei_amount * 1e9);
U256::from_str(&wei_str).unwrap_or(U256::ZERO)
}
#[cfg(feature = "high-precision")]
pub fn gwei_to_wei(gwei_amount: Decimal) -> U256 {
use rust_decimal::prelude::*;
let wei_amount = gwei_amount * Decimal::from_str("1000000000").unwrap();
let wei_str = wei_amount.to_string();
let integer_part = wei_str.split('.').next().unwrap_or("0");
U256::from_str(integer_part).unwrap_or(U256::ZERO)
}
#[cfg(not(feature = "high-precision"))]
pub fn wei_to_gwei(wei_amount: U256) -> f64 {
let wei_str = wei_amount.to_string();
wei_str.parse::<f64>().unwrap_or(0.0) / 1e9
}
#[cfg(feature = "high-precision")]
pub fn wei_to_gwei(wei_amount: U256) -> Decimal {
use rust_decimal::prelude::*;
let wei_str = wei_amount.to_string();
let wei_decimal = Decimal::from_str(&wei_str).unwrap_or(Decimal::ZERO);
let divisor = Decimal::from_str("1000000000").unwrap();
wei_decimal / divisor
}
#[cfg(not(feature = "high-precision"))]
pub fn token_to_smallest_unit(amount: f64, decimals: u8) -> U256 {
let multiplier = 10_f64.powi(decimals as i32);
let smallest_unit_str = format!("{:.0}", amount * multiplier);
U256::from_str(&smallest_unit_str).unwrap_or(U256::ZERO)
}
#[cfg(feature = "high-precision")]
pub fn token_to_smallest_unit(amount: Decimal, decimals: u8) -> U256 {
use rust_decimal::prelude::*;
let multiplier = Decimal::from(10_u64.pow(decimals as u32));
let smallest_unit = amount * multiplier;
let smallest_unit_str = smallest_unit.to_string();
let integer_part = smallest_unit_str.split('.').next().unwrap_or("0");
U256::from_str(integer_part).unwrap_or(U256::ZERO)
}
#[cfg(not(feature = "high-precision"))]
pub fn smallest_unit_to_token(amount: U256, decimals: u8) -> f64 {
let divisor = 10_f64.powi(decimals as i32);
let amount_str = amount.to_string();
amount_str.parse::<f64>().unwrap_or(0.0) / divisor
}
#[cfg(feature = "high-precision")]
pub fn smallest_unit_to_token(amount: U256, decimals: u8) -> Decimal {
use rust_decimal::prelude::*;
let amount_str = amount.to_string();
let amount_decimal = Decimal::from_str(&amount_str).unwrap_or(Decimal::ZERO);
let divisor = Decimal::from(10_u64.pow(decimals as u32));
amount_decimal / divisor
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_eth_to_wei_basic() {
let result = eth_to_wei(1.0);
assert_eq!(result, U256::from_str("1000000000000000000").unwrap());
}
#[test]
fn test_eth_to_wei_with_high_precision() {
let result = eth_to_wei(0.123456789012345678);
assert_eq!(result, U256::from_str("123456789012345678").unwrap());
}
#[test]
fn test_eth_to_wei_very_large_value() {
let result = eth_to_wei(1_000_000.0);
assert_eq!(result, U256::from_str("1000000000000000000000000").unwrap());
}
#[test]
fn test_eth_to_wei_zero() {
let result = eth_to_wei(0.0);
assert_eq!(result, U256::ZERO);
}
#[test]
fn test_gwei_to_wei_basic() {
let result = gwei_to_wei(1.0);
assert_eq!(result, U256::from_str("1000000000").unwrap());
}
#[test]
fn test_gwei_to_wei_with_precision() {
let result = gwei_to_wei(1.5);
assert_eq!(result, U256::from_str("1500000000").unwrap());
}
#[test]
fn test_gwei_to_wei_large_value() {
let result = gwei_to_wei(1_000_000.0);
assert_eq!(result, U256::from_str("1000000000000000").unwrap());
}
#[test]
fn test_token_to_smallest_unit_18_decimals() {
let result = token_to_smallest_unit(1.0, 18);
assert_eq!(result, U256::from_str("1000000000000000000").unwrap());
}
#[test]
fn test_token_to_smallest_unit_6_decimals() {
let result = token_to_smallest_unit(1.0, 6);
assert_eq!(result, U256::from_str("1000000").unwrap());
}
#[test]
fn test_token_to_smallest_unit_with_precision() {
let result = token_to_smallest_unit(1.23456, 8);
assert_eq!(result, U256::from_str("123456000").unwrap());
}
#[test]
fn test_token_to_smallest_unit_very_large() {
let result = token_to_smallest_unit(1_000_000_000.0, 18);
assert_eq!(
result,
U256::from_str("1000000000000000000000000000").unwrap()
);
}
#[test]
fn test_wei_to_eth() {
let wei = U256::from_str("1000000000000000000").unwrap();
let result = wei_to_eth(wei);
assert!((result - 1.0).abs() < 1e-10);
}
#[test]
fn test_wei_to_gwei() {
let wei = U256::from_str("1000000000").unwrap();
let result = wei_to_gwei(wei);
assert!((result - 1.0).abs() < 1e-10);
}
#[test]
fn test_smallest_unit_to_token() {
let amount = U256::from_str("1000000000000000000").unwrap();
let result = smallest_unit_to_token(amount, 18);
assert!((result - 1.0).abs() < 1e-10);
}
#[test]
fn test_conversion_roundtrip() {
let original = 123.456789;
let wei = eth_to_wei(original);
let back = wei_to_eth(wei);
assert!((back - original).abs() < 1e-6); }
}