1use std::ops::Deref;
2
3use crate::error::WalletKitError;
4use ruint::aliases::U256;
5use serde::{Deserialize, Serialize};
6
7#[allow(clippy::module_name_repetitions)]
16#[derive(Debug, PartialEq, Eq, Clone, Copy, uniffi::Object)]
17pub struct U256Wrapper(pub U256);
18
19#[uniffi::export]
20impl U256Wrapper {
21 #[must_use]
23 pub fn to_hex_string(&self) -> String {
24 format!("{:#066x}", self.0)
25 }
26
27 #[must_use]
29 pub fn to_decimal_string(&self) -> String {
30 self.0.to_string()
31 }
32
33 #[uniffi::constructor]
38 pub fn try_from_hex_string(hex_string: &str) -> Result<Self, WalletKitError> {
39 let hex_string = hex_string.trim().trim_start_matches("0x");
40
41 let number = U256::from_str_radix(hex_string, 16)
42 .map_err(|_| WalletKitError::InvalidNumber)?;
43
44 Ok(Self(number))
45 }
46
47 #[must_use]
51 #[uniffi::constructor]
52 pub fn from_u64(value: u64) -> Self {
53 Self(U256::from(value))
54 }
55
56 #[must_use]
60 #[uniffi::constructor]
61 pub fn from_u32(value: u32) -> Self {
62 Self(U256::from(value))
63 }
64
65 #[uniffi::constructor]
73 pub fn from_limbs(limbs: Vec<u64>) -> Result<Self, WalletKitError> {
74 let limbs = limbs
75 .try_into()
76 .map_err(|_| WalletKitError::InvalidNumber)?;
77
78 Ok(Self(U256::from_limbs(limbs)))
79 }
80
81 #[must_use]
85 pub fn into_limbs(self) -> Vec<u64> {
86 self.0.into_limbs().to_vec()
87 }
88}
89
90impl From<U256Wrapper> for U256 {
91 fn from(val: U256Wrapper) -> Self {
92 val.0
93 }
94}
95
96impl From<U256> for U256Wrapper {
97 fn from(val: U256) -> Self {
98 Self(val)
99 }
100}
101
102impl std::fmt::Display for U256Wrapper {
103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104 write!(f, "{}", self.to_hex_string())
105 }
106}
107
108impl Deref for U256Wrapper {
109 type Target = U256;
110
111 fn deref(&self) -> &Self::Target {
112 &self.0
113 }
114}
115
116impl Serialize for U256Wrapper {
117 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
118 where
119 S: serde::Serializer,
120 {
121 serializer.serialize_str(&self.to_hex_string())
122 }
123}
124
125impl<'de> Deserialize<'de> for U256Wrapper {
126 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
127 where
128 D: serde::Deserializer<'de>,
129 {
130 let s = String::deserialize(deserializer)?;
131 Self::try_from_hex_string(&s).map_err(serde::de::Error::custom)
132 }
133}
134
135#[cfg(test)]
136mod tests {
137 #![allow(clippy::unreadable_literal)]
138
139 use super::*;
140 use ruint::uint;
141
142 #[test]
143 fn test_to_hex_string_for_u256() {
144 assert_eq!(
145 U256Wrapper(U256::from(1)).to_hex_string(),
146 "0x0000000000000000000000000000000000000000000000000000000000000001"
147 );
148 assert_eq!(
149 U256Wrapper(U256::from(42)).to_hex_string(),
150 "0x000000000000000000000000000000000000000000000000000000000000002a"
151 );
152
153 assert_eq!(
154 U256Wrapper(uint!(999999_U256)).to_hex_string(),
155 "0x00000000000000000000000000000000000000000000000000000000000f423f"
156 );
157
158 assert_eq!(
159 U256Wrapper(uint!(
160 80084422859880547211683076133703299733277748156566366325829078699459944778998_U256
161 ))
162 .to_hex_string(),
163 "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6"
164 );
165
166 assert_eq!(
167 U256Wrapper(uint!(
168 0x036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0_U256
169 ))
170 .to_hex_string(),
171 "0x036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0"
172 );
173 }
174
175 #[test]
176 fn test_from_hex_string_for_u256() {
177 assert_eq!(
178 U256Wrapper::try_from_hex_string(
179 "0x0000000000000000000000000000000000000000000000000000000000000001"
180 )
181 .unwrap(),
182 U256Wrapper(U256::from(1))
183 );
184 assert_eq!(
185 U256Wrapper::try_from_hex_string(
186 "0x000000000000000000000000000000000000000000000000000000000000002a"
187 )
188 .unwrap(),
189 U256Wrapper(U256::from(42))
190 );
191
192 assert_eq!(
193 U256Wrapper::try_from_hex_string(
194 "0x00000000000000000000000000000000000000000000000000000000000f423f"
195 )
196 .unwrap(),
197 U256Wrapper(uint!(999999_U256))
198 );
199
200 assert_eq!(
201 U256Wrapper::try_from_hex_string("0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6").unwrap(),
202 U256Wrapper(uint!(
203 80084422859880547211683076133703299733277748156566366325829078699459944778998_U256
204 ))
205 );
206
207 assert_eq!(
208 U256Wrapper::try_from_hex_string(
209 "0x036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0"
210 )
211 .unwrap()
212 .0,
213 uint!(
214 0x036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0_U256
215 )
216 );
217 }
218
219 #[test]
220 fn test_invalid_hex_string() {
221 assert!(U256Wrapper::try_from_hex_string("0xZZZZ").is_err());
222 assert!(U256Wrapper::try_from_hex_string("1g").is_err());
223 assert!(U256Wrapper::try_from_hex_string("not a hex string").is_err());
224 }
225
226 #[test]
227 fn test_json_serializing() {
228 let number = U256Wrapper(uint!(
229 0x036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0_U256
230 ));
231
232 let json = serde_json::to_string(&number).unwrap();
233 assert_eq!(
234 json,
235 "\"0x036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0\""
236 );
237 }
238
239 #[test]
240 fn test_from_u64() {
241 assert_eq!(U256Wrapper::from_u64(1).0, uint!(1_U256));
242 assert_eq!(U256Wrapper::from_u64(42).0, uint!(42_U256));
243 assert_eq!(U256Wrapper::from_u64(999_999).0, uint!(999_999_U256));
244
245 assert_eq!(
246 U256Wrapper::from_u64(2).to_hex_string(),
247 "0x0000000000000000000000000000000000000000000000000000000000000002"
248 );
249 assert_eq!(
250 U256Wrapper::from_u64(u64::MAX).to_hex_string(),
251 "0x000000000000000000000000000000000000000000000000ffffffffffffffff"
252 );
253 }
254
255 #[test]
256 fn test_from_u32() {
257 assert_eq!(U256Wrapper::from_u32(1).0, U256::from(1));
258 assert_eq!(U256Wrapper::from_u32(42).0, U256::from(42));
259 assert_eq!(U256Wrapper::from_u32(999999).0, U256::from(999999));
260 }
261
262 #[test]
263 fn test_from_limbs() {
264 assert_eq!(
265 U256Wrapper::from_limbs(vec![1, 0, 0, 0]).unwrap().0,
266 U256::from(1)
267 );
268
269 assert_eq!(
270 U256Wrapper::from_limbs(vec![0, 0, 0, 2161727821137838080])
271 .unwrap()
272 .to_hex_string(),
273 "0x1e00000000000000000000000000000000000000000000000000000000000000"
274 );
275
276 assert_eq!(
277 U256Wrapper::from_limbs(vec![1, 0, 0, 2161727821137838080])
278 .unwrap()
279 .to_hex_string(),
280 "0x1e00000000000000000000000000000000000000000000000000000000000001"
281 );
282 }
283
284 #[test]
285 fn test_from_limbs_invalid_length() {
286 assert!(U256Wrapper::from_limbs(vec![1, 0, 0]).is_err()); assert!(U256Wrapper::from_limbs(vec![1, 0, 0, 0, 5]).is_err());
288 assert!(U256Wrapper::from_limbs(vec![1, 0, 0, 0, 0]).is_err());
289 }
290}