monetary/
amount.rs

1use std::marker::PhantomData;
2
3use cosmwasm_std::{Decimal, DivideByZeroError, OverflowError, Uint128};
4
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6#[cfg_attr(feature = "serde", serde(transparent))]
7#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
8#[derive(Clone, Debug, PartialEq, Eq, Copy)]
9pub struct AmountU128<T>(
10    pub(crate) Uint128,
11    #[cfg_attr(feature = "serde", serde(skip))] PhantomData<T>,
12);
13
14impl<T> AmountU128<T> {
15    #[inline]
16    pub const fn new(amount: Uint128) -> Self {
17        AmountU128(amount, PhantomData)
18    }
19
20    #[inline]
21    pub const fn u128(&self) -> u128 {
22        self.0.u128()
23    }
24
25    #[inline]
26    pub const fn uint128(&self) -> Uint128 {
27        self.0
28    }
29
30    #[inline]
31    pub const fn zero() -> Self {
32        Self::new(Uint128::zero())
33    }
34
35    #[must_use]
36    #[inline]
37    pub const fn is_zero(&self) -> bool {
38        self.0.is_zero()
39    }
40
41    pub fn checked_add(self, other: Self) -> Result<Self, OverflowError> {
42        Ok(Self::new(self.0.checked_add(other.0)?))
43    }
44
45    pub fn checked_sub(self, other: Self) -> Result<Self, OverflowError> {
46        Ok(Self::new(self.0.checked_sub(other.0)?))
47    }
48
49    pub fn checked_mul(self, other: Self) -> Result<Self, OverflowError> {
50        Ok(Self::new(self.0.checked_mul(other.0)?))
51    }
52
53    pub fn checked_div(self, other: Self) -> Result<Self, DivideByZeroError> {
54        Ok(Self::new(self.0.checked_div(other.0)?))
55    }
56
57    #[must_use = "this returns the result of the operation, without modifying the original"]
58    pub fn saturating_add(self, other: Self) -> Self {
59        Self::new(self.0.saturating_add(other.0))
60    }
61
62    #[must_use = "this returns the result of the operation, without modifying the original"]
63    pub fn saturating_sub(self, other: Self) -> Self {
64        Self::new(self.0.saturating_sub(other.0))
65    }
66
67    #[must_use = "this returns the result of the operation, without modifying the original"]
68    pub fn saturating_mul(self, other: Self) -> Self {
69        Self::new(self.0.saturating_mul(other.0))
70    }
71
72    #[must_use = "this returns the result of the operation, without modifying the original"]
73    pub const fn abs_diff(self, other: Self) -> Self {
74        Self::new(self.0.abs_diff(other.0))
75    }
76
77    pub fn dec_mul_floor(self, dec: Decimal) -> Self {
78        Self::new(self.0.mul_floor(dec))
79    }
80
81    pub fn dec_mul_ceil(self, dec: Decimal) -> Self {
82        Self::new(self.0.mul_ceil(dec))
83    }
84
85    pub fn dec_div_floor(self, dec: Decimal) -> Result<Self, DivideByZeroError> {
86        Ok(Self::new(self.0.div_floor(dec)))
87    }
88
89    pub fn dec_div_ceil(self, dec: Decimal) -> Result<Self, DivideByZeroError> {
90        Ok(Self::new(self.0.div_ceil(dec)))
91    }
92}
93
94impl<T> std::ops::Add for AmountU128<T> {
95    type Output = Self;
96
97    fn add(self, rhs: Self) -> Self::Output {
98        Self::new(self.0 + rhs.0)
99    }
100}
101
102impl<T> std::ops::Sub for AmountU128<T> {
103    type Output = Self;
104
105    fn sub(self, rhs: Self) -> Self::Output {
106        Self::new(self.0 - rhs.0)
107    }
108}
109
110impl<T> std::ops::Mul for AmountU128<T> {
111    type Output = Self;
112
113    fn mul(self, rhs: Self) -> Self::Output {
114        Self::new(self.0 * rhs.0)
115    }
116}
117
118impl<T> std::ops::Div for AmountU128<T> {
119    type Output = Self;
120
121    fn div(self, rhs: Self) -> Self::Output {
122        Self::new(self.0 / rhs.0)
123    }
124}
125
126impl<T> std::ops::AddAssign for AmountU128<T> {
127    fn add_assign(&mut self, rhs: Self) {
128        self.0 += rhs.0;
129    }
130}
131
132impl<T> std::ops::SubAssign for AmountU128<T> {
133    fn sub_assign(&mut self, rhs: Self) {
134        self.0 -= rhs.0;
135    }
136}
137
138impl<T> std::ops::MulAssign for AmountU128<T> {
139    fn mul_assign(&mut self, rhs: Self) {
140        self.0 *= rhs.0;
141    }
142}
143
144impl<T> std::ops::DivAssign for AmountU128<T> {
145    fn div_assign(&mut self, rhs: Self) {
146        self.0 /= rhs.0;
147    }
148}
149
150impl<T> std::fmt::Display for AmountU128<T> {
151    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
152        write!(f, "{}", self.0)
153    }
154}
155
156impl<T> From<AmountU128<T>> for String {
157    fn from(val: AmountU128<T>) -> Self {
158        val.0.to_string()
159    }
160}
161
162impl<T: PartialEq> PartialOrd for AmountU128<T> {
163    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
164        Some(self.0.cmp(&other.0))
165    }
166}
167
168impl<T: Eq> Ord for AmountU128<T> {
169    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
170        self.0.cmp(&other.0)
171    }
172}
173
174impl<T: Default> Default for AmountU128<T> {
175    fn default() -> Self {
176        Self::new(Uint128::default())
177    }
178}
179
180#[cfg(test)]
181mod test {
182    use monetary_macros::denom;
183
184    use crate::AmountU128;
185
186    #[denom]
187    pub struct Denom;
188
189    #[test]
190    fn serialization() {
191        let a = AmountU128::<Denom>::new(12345u128.into());
192        let serialized = serde_json_wasm::to_string(&a).unwrap();
193        assert_eq!(serialized, r#""12345""#);
194
195        let b: AmountU128<Denom> = serde_json_wasm::from_str(&serialized).unwrap();
196        assert_eq!(a, b);
197    }
198}