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}