ethers_core/utils/
units.rs

1use super::ConversionError;
2use std::{fmt, str::FromStr};
3
4/// Common Ethereum unit types.
5#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
6pub enum Units {
7    /// Wei is equivalent to 1 wei.
8    Wei,
9    /// Kwei is equivalent to 1e3 wei.
10    Kwei,
11    /// Mwei is equivalent to 1e6 wei.
12    Mwei,
13    /// Gwei is equivalent to 1e9 wei.
14    Gwei,
15    /// Twei is equivalent to 1e12 wei.
16    Twei,
17    /// Pwei is equivalent to 1e15 wei.
18    Pwei,
19    /// Ether is equivalent to 1e18 wei.
20    Ether,
21    /// Other less frequent unit sizes, equivalent to 1e{0} wei.
22    Other(u32),
23}
24
25impl fmt::Display for Units {
26    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27        f.pad(self.as_num().to_string().as_str())
28    }
29}
30
31impl TryFrom<u32> for Units {
32    type Error = ConversionError;
33
34    fn try_from(value: u32) -> Result<Self, Self::Error> {
35        Ok(Units::Other(value))
36    }
37}
38
39impl TryFrom<i32> for Units {
40    type Error = ConversionError;
41
42    fn try_from(value: i32) -> Result<Self, Self::Error> {
43        Ok(Units::Other(value as u32))
44    }
45}
46
47impl TryFrom<usize> for Units {
48    type Error = ConversionError;
49
50    fn try_from(value: usize) -> Result<Self, Self::Error> {
51        Ok(Units::Other(value as u32))
52    }
53}
54
55impl TryFrom<String> for Units {
56    type Error = ConversionError;
57
58    fn try_from(value: String) -> Result<Self, Self::Error> {
59        Self::from_str(&value)
60    }
61}
62
63impl<'a> TryFrom<&'a String> for Units {
64    type Error = ConversionError;
65
66    fn try_from(value: &'a String) -> Result<Self, Self::Error> {
67        Self::from_str(value)
68    }
69}
70
71impl TryFrom<&str> for Units {
72    type Error = ConversionError;
73
74    fn try_from(value: &str) -> Result<Self, Self::Error> {
75        Self::from_str(value)
76    }
77}
78
79impl FromStr for Units {
80    type Err = ConversionError;
81
82    fn from_str(s: &str) -> Result<Self, Self::Err> {
83        Ok(match s.to_lowercase().as_str() {
84            "eth" | "ether" => Units::Ether,
85            "pwei" | "milli" | "milliether" | "finney" => Units::Pwei,
86            "twei" | "micro" | "microether" | "szabo" => Units::Twei,
87            "gwei" | "nano" | "nanoether" | "shannon" => Units::Gwei,
88            "mwei" | "pico" | "picoether" | "lovelace" => Units::Mwei,
89            "kwei" | "femto" | "femtoether" | "babbage" => Units::Kwei,
90            "wei" => Units::Wei,
91            _ => return Err(ConversionError::UnrecognizedUnits(s.to_string())),
92        })
93    }
94}
95
96impl From<Units> for u32 {
97    fn from(units: Units) -> Self {
98        units.as_num()
99    }
100}
101
102impl From<Units> for i32 {
103    fn from(units: Units) -> Self {
104        units.as_num() as i32
105    }
106}
107
108impl From<Units> for usize {
109    fn from(units: Units) -> Self {
110        units.as_num() as usize
111    }
112}
113
114impl Units {
115    pub fn as_num(&self) -> u32 {
116        match self {
117            Units::Wei => 0,
118            Units::Kwei => 3,
119            Units::Mwei => 6,
120            Units::Gwei => 9,
121            Units::Twei => 12,
122            Units::Pwei => 15,
123            Units::Ether => 18,
124            Units::Other(inner) => *inner,
125        }
126    }
127}
128
129#[cfg(test)]
130mod tests {
131    use super::*;
132    use Units::*;
133
134    #[test]
135    fn test_units() {
136        assert_eq!(Wei.as_num(), 0);
137        assert_eq!(Kwei.as_num(), 3);
138        assert_eq!(Mwei.as_num(), 6);
139        assert_eq!(Gwei.as_num(), 9);
140        assert_eq!(Twei.as_num(), 12);
141        assert_eq!(Pwei.as_num(), 15);
142        assert_eq!(Ether.as_num(), 18);
143        assert_eq!(Other(10).as_num(), 10);
144        assert_eq!(Other(20).as_num(), 20);
145    }
146
147    #[test]
148    fn test_into() {
149        assert_eq!(Units::try_from("wei").unwrap(), Wei);
150        assert_eq!(Units::try_from("kwei").unwrap(), Kwei);
151        assert_eq!(Units::try_from("mwei").unwrap(), Mwei);
152        assert_eq!(Units::try_from("gwei").unwrap(), Gwei);
153        assert_eq!(Units::try_from("twei").unwrap(), Twei);
154        assert_eq!(Units::try_from("pwei").unwrap(), Pwei);
155        assert_eq!(Units::try_from("ether").unwrap(), Ether);
156
157        assert_eq!(Units::try_from("wei".to_string()).unwrap(), Wei);
158        assert_eq!(Units::try_from("kwei".to_string()).unwrap(), Kwei);
159        assert_eq!(Units::try_from("mwei".to_string()).unwrap(), Mwei);
160        assert_eq!(Units::try_from("gwei".to_string()).unwrap(), Gwei);
161        assert_eq!(Units::try_from("twei".to_string()).unwrap(), Twei);
162        assert_eq!(Units::try_from("pwei".to_string()).unwrap(), Pwei);
163        assert_eq!(Units::try_from("ether".to_string()).unwrap(), Ether);
164
165        assert_eq!(Units::try_from(&"wei".to_string()).unwrap(), Wei);
166        assert_eq!(Units::try_from(&"kwei".to_string()).unwrap(), Kwei);
167        assert_eq!(Units::try_from(&"mwei".to_string()).unwrap(), Mwei);
168        assert_eq!(Units::try_from(&"gwei".to_string()).unwrap(), Gwei);
169        assert_eq!(Units::try_from(&"twei".to_string()).unwrap(), Twei);
170        assert_eq!(Units::try_from(&"pwei".to_string()).unwrap(), Pwei);
171        assert_eq!(Units::try_from(&"ether".to_string()).unwrap(), Ether);
172    }
173}