nautilus_model/defi/types/
quantity.rs1use alloy_primitives::U256;
19
20use crate::types::quantity::Quantity;
21
22impl Quantity {
23 #[must_use]
32 pub fn from_wei<U>(raw_wei: U) -> Self
33 where
34 U: Into<U256>,
35 {
36 let raw_u256: U256 = raw_wei.into();
37 let raw_u128: u128 = raw_u256
38 .try_into()
39 .expect("raw wei value exceeds unsigned 128-bit range");
40
41 Self::from_raw(raw_u128, 18)
42 }
43
44 #[must_use]
52 pub fn as_wei(&self) -> U256 {
53 if self.precision != 18 {
54 panic!(
55 "Failed to convert quantity with precision {} to wei (requires precision 18)",
56 self.precision
57 );
58 }
59
60 U256::from(self.raw)
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use rstest::rstest;
67 use rust_decimal_macros::dec;
68
69 use super::*;
70
71 #[rstest]
72 fn test_from_wei_basic() {
73 let quantity = Quantity::from_wei(U256::from(1_000_000_000_000_000_000_u128)); assert_eq!(quantity.precision, 18);
75 assert_eq!(quantity.as_decimal(), dec!(1.0));
76 }
77
78 #[rstest]
79 fn test_as_wei_basic() {
80 let quantity = Quantity::from_raw(1_000_000_000_000_000_000_u128, 18);
81 let wei = quantity.as_wei();
82 assert_eq!(wei, U256::from(1_000_000_000_000_000_000_u128));
83 }
84
85 #[rstest]
86 #[should_panic(
87 expected = "Failed to convert quantity with precision 2 to wei (requires precision 18)"
88 )]
89 fn test_as_wei_wrong_precision() {
90 let quantity = Quantity::new(1.23, 2);
91 let _ = quantity.as_wei();
92 }
93
94 #[rstest]
95 fn test_wei_round_trip() {
96 let original_wei = U256::from(1_500_000_000_000_000_000_u128); let quantity = Quantity::from_wei(original_wei);
98 let converted_wei = quantity.as_wei();
99 assert_eq!(original_wei, converted_wei);
100 assert_eq!(quantity.as_decimal(), dec!(1.5));
101 }
102
103 #[rstest]
104 fn test_from_wei_large_value() {
105 let large_wei = U256::from(1_000_000_000_000_000_000_000_u128); let quantity = Quantity::from_wei(large_wei);
108 assert_eq!(quantity.precision, 18);
109 assert_eq!(quantity.as_decimal(), dec!(1000.0));
110 }
111
112 #[rstest]
113 fn test_from_wei_small_value() {
114 let small_wei = U256::from(1_000_000_u128);
117 let quantity = Quantity::from_wei(small_wei);
118 assert_eq!(quantity.precision, 18);
119 assert_eq!(quantity.as_decimal(), dec!(0.000000000001));
120 }
121
122 #[rstest]
123 fn test_from_wei_zero() {
124 let quantity = Quantity::from_wei(U256::ZERO);
125 assert_eq!(quantity.precision, 18);
126 assert_eq!(quantity.as_decimal(), dec!(0));
127 assert_eq!(quantity.as_wei(), U256::ZERO);
128 }
129
130 #[rstest]
131 fn test_from_wei_very_large_value() {
132 let large_wei = U256::from(1_000_000_000_000_000_000_000_000_000_u128);
134 let quantity = Quantity::from_wei(large_wei);
135 assert_eq!(quantity.precision, 18);
136 assert_eq!(quantity.as_wei(), large_wei);
137 assert_eq!(quantity.as_decimal(), dec!(1000000000));
138 }
139
140 #[rstest]
141 #[should_panic(expected = "raw wei value exceeds unsigned 128-bit range")]
142 fn test_from_wei_overflow() {
143 let overflow_wei = U256::from(u128::MAX) + U256::from(1_u64);
144 let _ = Quantity::from_wei(overflow_wei);
145 }
146
147 #[rstest]
148 fn test_from_wei_various_amounts() {
149 let test_cases = vec![
151 (1_u128, dec!(0.000000000000000001)), (1000_u128, dec!(0.000000000000001)), (1_000_000_u128, dec!(0.000000000001)), (1_000_000_000_u128, dec!(0.000000001)), (1_000_000_000_000_u128, dec!(0.000001)), (1_000_000_000_000_000_u128, dec!(0.001)), (1_000_000_000_000_000_000_u128, dec!(1)), (10_000_000_000_000_000_000_u128, dec!(10)), ];
160
161 for (wei_amount, expected_decimal) in test_cases {
162 let quantity = Quantity::from_wei(U256::from(wei_amount));
163 assert_eq!(quantity.precision, 18);
164 assert_eq!(quantity.as_decimal(), expected_decimal);
165 assert_eq!(quantity.as_wei(), U256::from(wei_amount));
166 }
167 }
168
169 #[rstest]
170 fn test_as_wei_precision_validation() {
171 for precision in [2, 6, 8, 16] {
173 let quantity = Quantity::new(123.45, precision);
174 let result = std::panic::catch_unwind(|| quantity.as_wei());
175 assert!(
176 result.is_err(),
177 "as_wei() should panic for precision {precision}"
178 );
179 }
180 }
181
182 #[rstest]
183 fn test_arithmetic_operations_with_wei() {
184 let quantity1 = Quantity::from_wei(U256::from(1_000_000_000_000_000_000_u128)); let quantity2 = Quantity::from_wei(U256::from(500_000_000_000_000_000_u128)); let sum = quantity1 + quantity2;
189 assert_eq!(sum.precision, 18);
190 assert_eq!(sum.as_decimal(), dec!(1.5));
191 assert_eq!(sum.as_wei(), U256::from(1_500_000_000_000_000_000_u128));
192
193 let diff = quantity1 - quantity2;
195 assert_eq!(diff.precision, 18);
196 assert_eq!(diff.as_decimal(), dec!(0.5));
197 assert_eq!(diff.as_wei(), U256::from(500_000_000_000_000_000_u128));
198 }
199
200 #[rstest]
201 fn test_comparison_operations_with_wei() {
202 let quantity1 = Quantity::from_wei(U256::from(1_000_000_000_000_000_000_u128)); let quantity2 = Quantity::from_wei(U256::from(2_000_000_000_000_000_000_u128)); let quantity3 = Quantity::from_wei(U256::from(1_000_000_000_000_000_000_u128)); assert!(quantity1 < quantity2);
207 assert!(quantity2 > quantity1);
208 assert_eq!(quantity1, quantity3);
209 assert!(quantity1 <= quantity3);
210 assert!(quantity1 >= quantity3);
211 }
212}