1use std::fmt::Display;
23
24use alloy::primitives::{I256, U256};
25
26pub fn convert_i256_to_f64(amount: I256, decimals: u8) -> anyhow::Result<f64> {
32 let is_negative = amount.is_negative();
33 let abs_amount = if is_negative { -amount } else { amount };
34 let amount = convert_to_f64(abs_amount, decimals, "I256")?;
35
36 Ok(if is_negative { -amount } else { amount })
37}
38
39pub fn convert_u256_to_f64(amount: U256, decimals: u8) -> anyhow::Result<f64> {
45 convert_to_f64(amount, decimals, "U256")
46}
47
48fn convert_to_f64(amount: impl Display, decimals: u8, type_name: &str) -> anyhow::Result<f64> {
49 let amount: f64 = amount
50 .to_string()
51 .parse()
52 .map_err(|e| anyhow::anyhow!("Failed to parse {type_name} to f64: {e}"))?;
53
54 let factor = 10f64.powi(i32::from(decimals));
55 Ok(amount / factor)
56}
57
58#[cfg(test)]
59mod tests {
60 use std::str::FromStr;
61
62 use alloy::primitives::{I256, U256};
63 use rstest::rstest;
64
65 use super::*;
66
67 #[rstest]
68 fn test_convert_positive_i256_to_f64() {
69 let amount = I256::from_str("1000000").unwrap();
71 let result = convert_i256_to_f64(amount, 6).unwrap();
72 assert_eq!(result, 1.0);
73
74 let amount = I256::from_str("1000000000000000000").unwrap();
76 let result = convert_i256_to_f64(amount, 18).unwrap();
77 assert_eq!(result, 1.0);
78 }
79
80 #[rstest]
81 fn test_convert_negative_i256_to_f64() {
82 let amount = I256::from_str("-1000000").unwrap();
84 let result = convert_i256_to_f64(amount, 6).unwrap();
85 assert_eq!(result, -1.0);
86
87 let amount = I256::from_str("-2500000000000000000").unwrap();
89 let result = convert_i256_to_f64(amount, 18).unwrap();
90 assert_eq!(result, -2.5);
91 }
92
93 #[rstest]
94 fn test_convert_zero_i256_to_f64() {
95 let amount = I256::ZERO;
96 let result = convert_i256_to_f64(amount, 6).unwrap();
97 assert_eq!(result, 0.0);
98
99 let result = convert_i256_to_f64(amount, 18).unwrap();
100 assert_eq!(result, 0.0);
101 }
102
103 #[rstest]
104 fn test_convert_fractional_amounts() {
105 let amount = I256::from_str("500000").unwrap();
107 let result = convert_i256_to_f64(amount, 6).unwrap();
108 assert_eq!(result, 0.5);
109
110 let amount = I256::from_str("123456").unwrap();
112 let result = convert_i256_to_f64(amount, 6).unwrap();
113 assert_eq!(result, 0.123456);
114
115 let amount = I256::from_str("-123456").unwrap();
117 let result = convert_i256_to_f64(amount, 6).unwrap();
118 assert_eq!(result, -0.123456);
119 }
120
121 #[rstest]
122 fn test_convert_large_i256_values() {
123 let large_value = U256::from(10).pow(U256::from(30)); let amount = I256::try_from(large_value).unwrap();
126 let result = convert_i256_to_f64(amount, 18).unwrap();
127 assert_eq!(result, 1e12); let amount = I256::from_str("9007199254740991").unwrap(); let result = convert_i256_to_f64(amount, 0).unwrap();
132 assert_eq!(result, 9_007_199_254_740_991.0);
133 }
134
135 #[rstest]
136 fn test_convert_with_different_decimals() {
137 let amount = I256::from_str("1000000000").unwrap();
138
139 let result = convert_i256_to_f64(amount, 0).unwrap();
141 assert_eq!(result, 1_000_000_000.0);
142
143 let result = convert_i256_to_f64(amount, 9).unwrap();
145 assert_eq!(result, 1.0);
146
147 let result = convert_i256_to_f64(amount, 12).unwrap();
149 assert_eq!(result, 0.001);
150 }
151
152 #[rstest]
153 fn test_convert_edge_cases() {
154 let amount = I256::from_str("1").unwrap();
156 let result = convert_i256_to_f64(amount, 18).unwrap();
157 assert_eq!(result, 1e-18);
158
159 let amount = I256::from_str("100").unwrap();
161 let result = convert_i256_to_f64(amount, 6).unwrap();
162 assert_eq!(result, 0.0001);
163 }
164
165 #[rstest]
166 fn test_convert_real_world_examples() {
167 let amount = I256::from_str("1234567890").unwrap();
169 let result = convert_i256_to_f64(amount, 6).unwrap();
170 assert!((result - 1234.567890).abs() < f64::EPSILON);
171
172 let amount = I256::from_str("-5000000000000000").unwrap();
174 let result = convert_i256_to_f64(amount, 18).unwrap();
175 assert_eq!(result, -0.005);
176
177 let amount = I256::from_str("10000000000000").unwrap();
179 let result = convert_i256_to_f64(amount, 8).unwrap();
180 assert_eq!(result, 100_000.0);
181 }
182
183 #[rstest]
184 fn test_precision_boundaries() {
185 let max_safe = I256::from_str("9007199254740992").unwrap(); let result = convert_i256_to_f64(max_safe, 0).unwrap();
189 assert_eq!(result, 9_007_199_254_740_992.0);
190
191 let amount = I256::from_str("1234567890123456789").unwrap();
193 let result = convert_i256_to_f64(amount, 9).unwrap();
194 assert!((result - 1_234_567_890.123_456_7).abs() < 1.0); }
196
197 #[rstest]
199 fn test_convert_positive_u256_to_f64() {
200 let amount = U256::from_str("1000000").unwrap();
202 let result = convert_u256_to_f64(amount, 6).unwrap();
203 assert_eq!(result, 1.0);
204
205 let amount = U256::from_str("1000000000000000000").unwrap();
207 let result = convert_u256_to_f64(amount, 18).unwrap();
208 assert_eq!(result, 1.0);
209 }
210
211 #[rstest]
212 fn test_convert_zero_u256_to_f64() {
213 let amount = U256::ZERO;
214 let result = convert_u256_to_f64(amount, 6).unwrap();
215 assert_eq!(result, 0.0);
216
217 let result = convert_u256_to_f64(amount, 18).unwrap();
218 assert_eq!(result, 0.0);
219 }
220
221 #[rstest]
222 fn test_convert_fractional_u256_amounts() {
223 let amount = U256::from_str("500000").unwrap();
225 let result = convert_u256_to_f64(amount, 6).unwrap();
226 assert_eq!(result, 0.5);
227
228 let amount = U256::from_str("123456").unwrap();
230 let result = convert_u256_to_f64(amount, 6).unwrap();
231 assert_eq!(result, 0.123456);
232 }
233
234 #[rstest]
235 fn test_convert_large_u256_values() {
236 let large_value = U256::from(10).pow(U256::from(30)); let result = convert_u256_to_f64(large_value, 18).unwrap();
239 assert_eq!(result, 1e12); let amount = U256::from_str("9007199254740991").unwrap(); let result = convert_u256_to_f64(amount, 0).unwrap();
244 assert_eq!(result, 9_007_199_254_740_991.0);
245 }
246
247 #[rstest]
248 fn test_convert_u256_with_different_decimals() {
249 let amount = U256::from_str("1000000000").unwrap();
250
251 let result = convert_u256_to_f64(amount, 0).unwrap();
253 assert_eq!(result, 1_000_000_000.0);
254
255 let result = convert_u256_to_f64(amount, 9).unwrap();
257 assert_eq!(result, 1.0);
258
259 let result = convert_u256_to_f64(amount, 12).unwrap();
261 assert_eq!(result, 0.001);
262 }
263
264 #[rstest]
265 fn test_convert_u256_edge_cases() {
266 let amount = U256::from_str("1").unwrap();
268 let result = convert_u256_to_f64(amount, 18).unwrap();
269 assert_eq!(result, 1e-18);
270
271 let amount = U256::from_str("100").unwrap();
273 let result = convert_u256_to_f64(amount, 6).unwrap();
274 assert_eq!(result, 0.0001);
275 }
276
277 #[rstest]
278 fn test_convert_u256_real_world_examples() {
279 let amount = U256::from_str("1234567890").unwrap();
281 let result = convert_u256_to_f64(amount, 6).unwrap();
282 assert!((result - 1234.567890).abs() < f64::EPSILON);
283
284 let amount = U256::from_str("10000000000000").unwrap();
286 let result = convert_u256_to_f64(amount, 8).unwrap();
287 assert_eq!(result, 100_000.0);
288
289 let amount = U256::from_str("1000000000000000000000000000000").unwrap(); let result = convert_u256_to_f64(amount, 18).unwrap();
292 assert_eq!(result, 1e12);
293 }
294
295 #[rstest]
296 fn test_convert_u256_precision_boundaries() {
297 let max_safe = U256::from_str("9007199254740992").unwrap(); let result = convert_u256_to_f64(max_safe, 0).unwrap();
301 assert_eq!(result, 9_007_199_254_740_992.0);
302
303 let amount = U256::from_str("1234567890123456789").unwrap();
305 let result = convert_u256_to_f64(amount, 9).unwrap();
306 assert!((result - 1_234_567_890.123_456_7).abs() < 1.0); }
308
309 #[rstest]
310 fn test_convert_u256_vs_i256_consistency() {
311 let u256_amount = U256::from_str("1000000000000000000").unwrap();
313 let i256_amount = I256::from_str("1000000000000000000").unwrap();
314
315 let u256_result = convert_u256_to_f64(u256_amount, 18).unwrap();
316 let i256_result = convert_i256_to_f64(i256_amount, 18).unwrap();
317
318 assert_eq!(u256_result, i256_result);
319 assert_eq!(u256_result, 1.0);
320 }
321
322 #[rstest]
323 fn test_convert_u256_max_values() {
324 let large_u256 = U256::from(2).pow(U256::from(255)); let result = convert_u256_to_f64(large_u256, 0).unwrap();
327 assert!(result.is_finite());
329 assert!(result > 0.0);
330
331 let large_u256_with_decimals = U256::from(2).pow(U256::from(60)); let result = convert_u256_to_f64(large_u256_with_decimals, 18).unwrap();
334 assert!(result.is_finite());
336 assert!(result > 1.0);
337 assert!(result < 2.0); }
339}