using System; using System.Numerics; namespace Nethereum.Util { public class UnitConversion { public enum EthUnit { Wei, Kwei, Ada, Femtoether, Mwei, Babbage, Picoether, Gwei, Shannon, Nanoether, Nano, Szabo, Microether, Micro, Finney, Milliether, Milli, Ether, Kether, Grand, Einstein, Mether, Gether, Tether } private static UnitConversion _convert; public static UnitConversion Convert { get { if (_convert == null) _convert = new UnitConversion(); return _convert; } } /// /// Converts from wei to a unit, NOTE: When the total number of digits is bigger than 29 they will be rounded the less /// significant digits /// public decimal FromWei(BigInteger value, BigInteger toUnit) { return FromWei(value, GetEthUnitValueLength(toUnit)); } /// /// Converts from wei to a unit, NOTE: When the total number of digits is bigger than 29 they will be rounded the less /// significant digits /// public decimal FromWei(BigInteger value, EthUnit toUnit = EthUnit.Ether) { return FromWei(value, GetEthUnitValue(toUnit)); } /// /// Converts from wei to a unit, NOTE: When the total number of digits is bigger than 29 they will be rounded the less /// significant digits /// public decimal FromWei(BigInteger value, int decimalPlacesToUnit) { return (decimal) new BigDecimal(value, decimalPlacesToUnit * -1); } public BigDecimal FromWeiToBigDecimal(BigInteger value, int decimalPlacesToUnit) { return new BigDecimal(value, decimalPlacesToUnit * -1); } public BigDecimal FromWeiToBigDecimal(BigInteger value, EthUnit toUnit = EthUnit.Ether) { return FromWeiToBigDecimal(value, GetEthUnitValue(toUnit)); } public BigDecimal FromWeiToBigDecimal(BigInteger value, BigInteger toUnit) { return FromWeiToBigDecimal(value, GetEthUnitValueLength(toUnit)); } private int GetEthUnitValueLength(BigInteger unitValue) { return unitValue.ToStringInvariant().Length - 1; } public BigInteger GetEthUnitValue(EthUnit ethUnit) { switch (ethUnit) { case EthUnit.Wei: return BigIntegerExtensions.ParseInvariant("1"); case EthUnit.Kwei: return BigIntegerExtensions.ParseInvariant("1000"); case EthUnit.Babbage: return BigIntegerExtensions.ParseInvariant("1000"); case EthUnit.Femtoether: return BigIntegerExtensions.ParseInvariant("1000"); case EthUnit.Mwei: return BigIntegerExtensions.ParseInvariant("1000000"); case EthUnit.Picoether: return BigIntegerExtensions.ParseInvariant("1000000"); case EthUnit.Gwei: return BigIntegerExtensions.ParseInvariant("1000000000"); case EthUnit.Shannon: return BigIntegerExtensions.ParseInvariant("1000000000"); case EthUnit.Nanoether: return BigIntegerExtensions.ParseInvariant("1000000000"); case EthUnit.Nano: return BigIntegerExtensions.ParseInvariant("1000000000"); case EthUnit.Szabo: return BigIntegerExtensions.ParseInvariant("1000000000000"); case EthUnit.Microether: return BigIntegerExtensions.ParseInvariant("1000000000000"); case EthUnit.Micro: return BigIntegerExtensions.ParseInvariant("1000000000000"); case EthUnit.Finney: return BigIntegerExtensions.ParseInvariant("1000000000000000"); case EthUnit.Milliether: return BigIntegerExtensions.ParseInvariant("1000000000000000"); case EthUnit.Milli: return BigIntegerExtensions.ParseInvariant("1000000000000000"); case EthUnit.Ether: return BigIntegerExtensions.ParseInvariant("1000000000000000000"); case EthUnit.Kether: return BigIntegerExtensions.ParseInvariant("1000000000000000000000"); case EthUnit.Grand: return BigIntegerExtensions.ParseInvariant("1000000000000000000000"); case EthUnit.Einstein: return BigIntegerExtensions.ParseInvariant("1000000000000000000000"); case EthUnit.Mether: return BigIntegerExtensions.ParseInvariant("1000000000000000000000000"); case EthUnit.Gether: return BigIntegerExtensions.ParseInvariant("1000000000000000000000000000"); case EthUnit.Tether: return BigIntegerExtensions.ParseInvariant("1000000000000000000000000000000"); } throw new NotImplementedException(); } public bool TryValidateUnitValue(BigInteger ethUnit) { if (ethUnit.ToStringInvariant().Trim('0') == "1") return true; throw new Exception("Invalid unit value, it should be a power of 10 "); } public BigInteger ToWeiFromUnit(decimal amount, BigInteger fromUnit) { return ToWeiFromUnit((BigDecimal) amount, fromUnit); } public BigInteger ToWeiFromUnit(BigDecimal amount, BigInteger fromUnit) { TryValidateUnitValue(fromUnit); var bigDecimalFromUnit = new BigDecimal(fromUnit, 0); var conversion = amount * bigDecimalFromUnit; return conversion.Floor().Mantissa; } public BigInteger ToWei(BigDecimal amount, EthUnit fromUnit = EthUnit.Ether) { return ToWeiFromUnit(amount, GetEthUnitValue(fromUnit)); } public BigInteger ToWei(BigDecimal amount, int decimalPlacesFromUnit) { if (decimalPlacesFromUnit == 0) ToWei(amount, 1); return ToWeiFromUnit(amount, BigInteger.Pow(10, decimalPlacesFromUnit)); } public BigInteger ToWei(decimal amount, int decimalPlacesFromUnit) { if (decimalPlacesFromUnit == 0) ToWei(amount, 1); return ToWeiFromUnit(amount, BigInteger.Pow(10, decimalPlacesFromUnit)); } public BigInteger ToWei(decimal amount, EthUnit fromUnit = EthUnit.Ether) { return ToWeiFromUnit(amount, GetEthUnitValue(fromUnit)); } public BigInteger ToWei(BigInteger value, EthUnit fromUnit = EthUnit.Ether) { return value * GetEthUnitValue(fromUnit); } public BigInteger ToWei(int value, EthUnit fromUnit = EthUnit.Ether) { return ToWei(new BigInteger(value), fromUnit); } public BigInteger ToWei(double value, EthUnit fromUnit = EthUnit.Ether) { return ToWei(System.Convert.ToDecimal(value), fromUnit); } public BigInteger ToWei(float value, EthUnit fromUnit = EthUnit.Ether) { return ToWei(System.Convert.ToDecimal(value), fromUnit); } public BigInteger ToWei(long value, EthUnit fromUnit = EthUnit.Ether) { return ToWei(new BigInteger(value), fromUnit); } public BigInteger ToWei(string value, EthUnit fromUnit = EthUnit.Ether) { return ToWei(decimal.Parse(value), fromUnit); } private BigInteger CalculateNumberOfDecimalPlaces(double value, int maxNumberOfDecimals, int currentNumberOfDecimals = 0) { return CalculateNumberOfDecimalPlaces(System.Convert.ToDecimal(value), maxNumberOfDecimals, currentNumberOfDecimals); } private BigInteger CalculateNumberOfDecimalPlaces(float value, int maxNumberOfDecimals, int currentNumberOfDecimals = 0) { return CalculateNumberOfDecimalPlaces(System.Convert.ToDecimal(value), maxNumberOfDecimals, currentNumberOfDecimals); } private int CalculateNumberOfDecimalPlaces(decimal value, int maxNumberOfDecimals, int currentNumberOfDecimals = 0) { if (currentNumberOfDecimals == 0) { if (value.ToStringInvariant() == Math.Round(value).ToStringInvariant()) return 0; currentNumberOfDecimals = 1; } if (currentNumberOfDecimals == maxNumberOfDecimals) return maxNumberOfDecimals; var multiplied = value * (decimal) BigInteger.Pow(10, currentNumberOfDecimals); if (Math.Round(multiplied) == multiplied) return currentNumberOfDecimals; return CalculateNumberOfDecimalPlaces(value, maxNumberOfDecimals, currentNumberOfDecimals + 1); } //public BigInteger ToWei(decimal amount, BigInteger fromUnit) //{ //var maxDigits = fromUnit.ToStringInvariant().Length - 1; //var stringAmount = amount.ToStringInvariant("#.#############################", System.Globalization.CultureInfo.InvariantCulture); //if (stringAmount.IndexOf(".") == -1) //{ // return BigIntegerExtensions.ParseInvariant(stringAmount) * fromUnit; //} //stringAmount = stringAmount.TrimEnd('0'); //var decimalPosition = stringAmount.IndexOf('.'); //var decimalPlaces = decimalPosition == -1 ? 0 : stringAmount.Length - decimalPosition - 1; //if (decimalPlaces > maxDigits) //{ // return BigIntegerExtensions.ParseInvariant(stringAmount.Substring(0, decimalPosition) + stringAmount.Substring(decimalPosition + 1, maxDigits)); //} //return BigIntegerExtensions.ParseInvariant(stringAmount.Substring(0, decimalPosition) + stringAmount.Substring(decimalPosition + 1).PadRight(maxDigits, '0')); //} } }