cosmwasm-common-library 3.0.0

Cosmwasm common library
Documentation
use crate::bigdecimal::BigDecimal;
use core::fmt::{Display, Formatter};
use core::str::FromStr;
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{StdError, StdResult, Uint128, Uint256};
use std::iter::Sum;
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};

#[cw_serde]
#[derive(Copy, Default, Ord, PartialOrd, Eq)]
pub struct BigInteger(pub Uint256);

impl BigInteger {
    pub const MAX: Self = Self(Uint256::MAX);
    pub const MIN: Self = Self(Uint256::MIN);

    pub const fn new(value: u128) -> Self {
        Self(Uint256::new(value))
    }

    pub fn scale_down(&self, decimals: u32) -> BigDecimal {
        BigDecimal::from(*self, decimals)
    }

    pub fn scale_up(&self, decimals: u32) -> Self {
        Self(self.0 * Uint256::from(10u64).pow(decimals))
    }

    pub fn to_uint128(&self) -> StdResult<Uint128> {
        Ok(Uint128::try_from(self.0)?)
    }

    pub fn to_uint256(&self) -> Uint256 {
        self.0
    }

    pub fn create_with_scale(value: u128, decimals: u32) -> Self {
        Self::from(value).scale_up(decimals)
    }

    pub fn is_zero(&self) -> bool {
        self.0.is_zero()
    }

    pub fn zero() -> Self {
        Self(Uint256::zero())
    }

    pub fn one() -> Self {
        Self(Uint256::one())
    }

    pub fn saturating_sub(&self, rhs: Self) -> Self {
        Self(self.0.saturating_sub(rhs.0))
    }

    pub fn checked_sub(&self, rhs: Self) -> StdResult<Self> {
        Ok(Self(self.0.checked_sub(rhs.0)?))
    }

    pub fn pow(&self, exp: u32) -> Self {
        Self(self.0.pow(exp))
    }

    pub fn from_be_bytes(bytes: [u8; 32]) -> Self {
        Self(Uint256::from_be_bytes(bytes))
    }

    pub fn from_le_bytes(bytes: [u8; 32]) -> Self {
        Self(Uint256::from_le_bytes(bytes))
    }

    pub fn to_be_bytes(&self) -> [u8; 32] {
        self.0.to_be_bytes()
    }

    pub fn to_le_bytes(&self) -> [u8; 32] {
        self.0.to_le_bytes()
    }

    pub fn multiply_ratio<A: Into<Uint256>, B: Into<Uint256>>(
        &self,
        numerator: A,
        denominator: B,
    ) -> BigInteger {
        let multiplier = BigDecimal::from_ratio(numerator, denominator);
        BigInteger::from(*self * multiplier)
    }
}

impl From<BigInteger> for String {
    fn from(value: BigInteger) -> Self {
        Self::from(value.0)
    }
}

impl FromStr for BigInteger {
    type Err = StdError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(BigInteger(Uint256::from_str(s)?))
    }
}

impl From<BigDecimal> for BigInteger {
    fn from(value: BigDecimal) -> Self {
        Self(value.0.to_uint_floor())
    }
}

impl From<Uint256> for BigInteger {
    fn from(value: Uint256) -> Self {
        Self(value)
    }
}

impl From<u128> for BigInteger {
    fn from(value: u128) -> Self {
        Self(Uint256::new(value))
    }
}

impl From<Uint128> for BigInteger {
    fn from(value: Uint128) -> Self {
        Self::from(value.u128())
    }
}

impl From<BigInteger> for Uint256 {
    fn from(value: BigInteger) -> Self {
        value.0
    }
}

impl From<u64> for BigInteger {
    fn from(value: u64) -> Self {
        Self(Uint256::from(value))
    }
}

impl From<u32> for BigInteger {
    fn from(value: u32) -> Self {
        Self(Uint256::from(value))
    }
}

impl From<u16> for BigInteger {
    fn from(value: u16) -> Self {
        Self(Uint256::from(value))
    }
}

impl From<u8> for BigInteger {
    fn from(value: u8) -> Self {
        Self(Uint256::from(value))
    }
}

impl Sub<BigInteger> for BigInteger {
    type Output = BigInteger;

    fn sub(self, rhs: BigInteger) -> Self::Output {
        Self(self.0 - rhs.0)
    }
}

impl Add<BigInteger> for BigInteger {
    type Output = BigInteger;

    fn add(self, rhs: BigInteger) -> Self::Output {
        Self(self.0 + rhs.0)
    }
}

impl Div<BigInteger> for BigInteger {
    type Output = BigInteger;

    fn div(self, rhs: BigInteger) -> Self::Output {
        Self(self.0 / rhs.0)
    }
}

impl Div<BigDecimal> for BigInteger {
    type Output = BigDecimal;

    #[allow(clippy::suspicious_arithmetic_impl)]
    fn div(self, rhs: BigDecimal) -> Self::Output {
        BigDecimal::from(self, 0) / rhs
    }
}

impl Mul<BigInteger> for BigInteger {
    type Output = BigInteger;

    fn mul(self, rhs: BigInteger) -> Self::Output {
        Self(self.0 * rhs.0)
    }
}

impl Mul<BigDecimal> for BigInteger {
    type Output = BigDecimal;

    fn mul(self, rhs: BigDecimal) -> Self::Output {
        rhs * self
    }
}

impl AddAssign for BigInteger {
    fn add_assign(&mut self, rhs: Self) {
        self.0 += rhs.0;
    }
}

impl SubAssign for BigInteger {
    fn sub_assign(&mut self, rhs: Self) {
        self.0 -= rhs.0;
    }
}

impl MulAssign for BigInteger {
    fn mul_assign(&mut self, rhs: Self) {
        self.0 *= rhs.0;
    }
}

impl DivAssign for BigInteger {
    fn div_assign(&mut self, rhs: Self) {
        self.0 /= rhs.0;
    }
}

impl Display for BigInteger {
    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
        self.0.fmt(f)
    }
}

impl Sum for BigInteger {
    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
        iter.fold(Self::zero(), Add::add)
    }
}

impl<'a> Sum<&'a BigInteger> for BigInteger {
    fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
        iter.fold(Self::zero(), |a, b| a + *b)
    }
}

#[cfg(test)]
mod tests {
    use crate::bigdecimal::BigDecimal;
    use crate::biginteger::BigInteger;
    use cosmwasm_std::{Decimal, Decimal256, Fraction, Uint128, Uint256};

    #[test]
    fn test_scale_down() {
        let bigint = BigInteger(Uint256::from(1000000u64));
        let bigdecimal = bigint.scale_down(6);
        assert_eq!(bigdecimal, BigDecimal(Decimal256::one()));
    }

    #[test]
    fn test_div() {
        let d = BigDecimal::from(BigInteger::from(100000000000000000000u128), 0);
        let i = BigInteger::from(100000000000000000000u128);
        assert_eq!(i / d, BigDecimal::one());

        let d = Decimal::percent(10);
        assert_eq!(
            BigInteger::from(Uint128::new(10).multiply_ratio(d.numerator(), d.denominator())),
            BigInteger::from(BigInteger::new(10) * BigDecimal::percent(10)),
        );
    }

    #[test]
    fn test_sum() {
        let vector: Vec<BigInteger> = vec![
            BigInteger::from(1u64),
            BigInteger::from(2u64),
            BigInteger::from(3u64),
        ];
        assert_eq!(
            vector.clone().into_iter().sum::<BigInteger>(),
            BigInteger::from(6u64)
        );
        assert_eq!(vector.iter().sum::<BigInteger>(), BigInteger::from(6u64));
    }

    #[test]
    fn test_bytes() {
        let i = BigInteger(Uint256::from(1000000u64));

        assert_eq!(BigInteger::from_be_bytes(i.to_be_bytes()), i);
    }

    #[test]
    fn test_multiply_ratio() {
        let a = BigInteger::new(100);

        assert_eq!(a.multiply_ratio(1u128, 2u128), BigInteger::new(50));
        assert_eq!(a.multiply_ratio(10u128, 10u128), BigInteger::new(100));
        assert_eq!(a.multiply_ratio(2u128, 1u128), BigInteger::new(200));
        assert_eq!(a.multiply_ratio(11u128, 10u128), BigInteger::new(110));
        assert_eq!(a.multiply_ratio(10u128, 11u128), BigInteger::new(90));
    }
}