cosmwasm_common_library/
biginteger.rs

1use crate::bigdecimal::BigDecimal;
2use core::fmt::{Display, Formatter};
3use core::str::FromStr;
4use std::iter::Sum;
5use cosmwasm_schema::cw_serde;
6use cosmwasm_std::{StdError, StdResult, Uint128, Uint256};
7use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
8
9#[cw_serde]
10#[derive(Copy, Default, Ord, PartialOrd, Eq)]
11pub struct BigInteger(pub Uint256);
12
13impl BigInteger {
14
15    pub const MAX: Self = Self(Uint256::MAX);
16    pub const MIN: Self = Self(Uint256::MIN);
17
18    pub const fn new(value: u128) -> Self {
19        Self(Uint256::from_u128(value))
20    }
21
22    pub fn scale_down(&self, decimals: u32) -> BigDecimal {
23        BigDecimal::from(*self, decimals)
24    }
25
26    pub fn scale_up(&self, decimals: u32) -> Self {
27        Self(self.0 * Uint256::from(10u64).pow(decimals))
28    }
29
30    pub fn to_uint128(&self) -> StdResult<Uint128> {
31        Ok(Uint128::try_from(self.0)?)
32    }
33
34    pub fn to_uint256(&self) -> Uint256 {
35        self.0
36    }
37
38    pub fn create_with_scale(value: u128, decimals: u32) -> Self {
39        Self::from(value).scale_up(decimals)
40    }
41
42    pub fn is_zero(&self) -> bool {
43        self.0.is_zero()
44    }
45
46    pub fn zero() -> Self {
47        Self(Uint256::zero())
48    }
49
50    pub fn one() -> Self {
51        Self(Uint256::one())
52    }
53
54    pub fn saturating_sub(&self, rhs: Self) -> Self {
55        Self(self.0.saturating_sub(rhs.0))
56    }
57
58    pub fn checked_sub(&self, rhs: Self) -> StdResult<Self> {
59        Ok(Self(self.0.checked_sub(rhs.0)?))
60    }
61
62    pub fn pow(&self, exp: u32) -> Self {
63        Self(self.0.pow(exp))
64    }
65
66    pub fn from_be_bytes(bytes: [u8; 32]) -> Self {
67        Self(Uint256::from_be_bytes(bytes))
68    }
69
70    pub fn from_le_bytes(bytes: [u8; 32]) -> Self {
71        Self(Uint256::from_le_bytes(bytes))
72    }
73
74    pub fn to_be_bytes(&self) -> [u8; 32] {
75        self.0.to_be_bytes()
76    }
77
78    pub fn to_le_bytes(&self) -> [u8; 32] {
79        self.0.to_le_bytes()
80    }
81}
82
83impl From<BigInteger> for String {
84    fn from(value: BigInteger) -> Self {
85        Self::from(value.0)
86    }
87}
88
89impl FromStr for BigInteger {
90    type Err = StdError;
91
92    fn from_str(s: &str) -> Result<Self, Self::Err> {
93        Ok(BigInteger(Uint256::from_str(s)?))
94    }
95}
96
97impl From<BigDecimal> for BigInteger {
98    fn from(value: BigDecimal) -> Self {
99        Self(value.0.to_uint_floor())
100    }
101}
102
103impl From<u128> for BigInteger {
104    fn from(value: u128) -> Self {
105        Self(Uint256::from_u128(value))
106    }
107}
108
109impl From<Uint128> for BigInteger {
110    fn from(value: Uint128) -> Self {
111        Self::from(value.u128())
112    }
113}
114
115impl From<BigInteger> for Uint256 {
116    fn from(value: BigInteger) -> Self {
117        value.0
118    }
119}
120
121impl From<u64> for BigInteger {
122    fn from(value: u64) -> Self {
123        Self(Uint256::from(value))
124    }
125}
126
127impl From<u32> for BigInteger {
128    fn from(value: u32) -> Self {
129        Self(Uint256::from(value))
130    }
131}
132
133impl From<u16> for BigInteger {
134    fn from(value: u16) -> Self {
135        Self(Uint256::from(value))
136    }
137}
138
139impl From<u8> for BigInteger {
140    fn from(value: u8) -> Self {
141        Self(Uint256::from(value))
142    }
143}
144
145impl Sub<BigInteger> for BigInteger {
146    type Output = BigInteger;
147
148    fn sub(self, rhs: BigInteger) -> Self::Output {
149        Self(self.0 - rhs.0)
150    }
151}
152
153impl Add<BigInteger> for BigInteger {
154    type Output = BigInteger;
155
156    fn add(self, rhs: BigInteger) -> Self::Output {
157        Self(self.0 + rhs.0)
158    }
159}
160
161impl Div<BigInteger> for BigInteger {
162    type Output = BigInteger;
163
164    fn div(self, rhs: BigInteger) -> Self::Output {
165        Self(self.0 / rhs.0)
166    }
167}
168
169impl Div<BigDecimal> for BigInteger {
170    type Output = BigDecimal;
171
172    #[allow(clippy::suspicious_arithmetic_impl)]
173    fn div(self, rhs: BigDecimal) -> Self::Output {
174        BigDecimal::from(self, 0) / rhs
175    }
176}
177
178impl Mul<BigInteger> for BigInteger {
179    type Output = BigInteger;
180
181    fn mul(self, rhs: BigInteger) -> Self::Output {
182        Self(self.0 * rhs.0)
183    }
184}
185
186impl Mul<BigDecimal> for BigInteger {
187    type Output = BigDecimal;
188
189    fn mul(self, rhs: BigDecimal) -> Self::Output {
190        rhs * self
191    }
192}
193
194impl AddAssign for BigInteger {
195    fn add_assign(&mut self, rhs: Self) {
196        self.0 += rhs.0;
197    }
198}
199
200impl SubAssign for BigInteger {
201    fn sub_assign(&mut self, rhs: Self) {
202        self.0 -= rhs.0;
203    }
204}
205
206impl MulAssign for BigInteger {
207    fn mul_assign(&mut self, rhs: Self) {
208        self.0 *= rhs.0;
209    }
210}
211
212impl DivAssign for BigInteger {
213    fn div_assign(&mut self, rhs: Self) {
214        self.0 /= rhs.0;
215    }
216}
217
218impl Display for BigInteger {
219    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
220        self.0.fmt(f)
221    }
222}
223
224impl Sum for BigInteger {
225    fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
226        iter.fold(Self::zero(), Add::add)
227    }
228}
229
230impl <'a> Sum<&'a BigInteger> for BigInteger {
231    fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
232        iter.fold(Self::zero(), |a, b| a + *b)
233    }
234}
235
236#[cfg(test)]
237mod tests {
238    use crate::bigdecimal::BigDecimal;
239    use crate::biginteger::BigInteger;
240    use cosmwasm_std::{Decimal256, Uint256};
241
242    #[test]
243    fn test_scale_down() {
244        let bigint = BigInteger(Uint256::from(1000000u64));
245        let bigdecimal = bigint.scale_down(6);
246        assert_eq!(bigdecimal, BigDecimal(Decimal256::one()));
247    }
248
249    #[test]
250    fn test_div() {
251        let d = BigDecimal::from(BigInteger::from(100000000000000000000u128), 0);
252        let i = BigInteger::from(100000000000000000000u128);
253        assert_eq!(i / d, BigDecimal::one());
254    }
255
256    #[test]
257    fn test_sum() {
258        let vector: Vec<BigInteger> = vec![BigInteger::from(1u64), BigInteger::from(2u64), BigInteger::from(3u64)];
259        assert_eq!(vector.clone().into_iter().sum::<BigInteger>(), BigInteger::from(6u64));
260        assert_eq!(vector.iter().sum::<BigInteger>(), BigInteger::from(6u64));
261    }
262
263    #[test]
264    fn test_bytes() {
265        let i = BigInteger(Uint256::from(1000000u64));
266
267        assert_eq!(BigInteger::from_be_bytes(i.to_be_bytes()), i);
268    }
269}