From 1a7a1b057da9d60370c6c19b0853db1512706334 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Sat, 23 Jul 2022 01:02:36 +0100 Subject: [PATCH] cosmrs: `Coin` type changes (#235) - Implemented `serde` traits for `Denom` - Changed internal `Coin` representation - Getter for `Decimal`'s internal value - Removed unused `Decimal` --- cosmrs/src/base.rs | 33 +++++++++++++++++++++--- cosmrs/src/decimal.rs | 59 ------------------------------------------- cosmrs/src/lib.rs | 2 -- cosmrs/src/tx.rs | 2 +- cosmrs/src/tx/fee.rs | 3 ++- 5 files changed, 33 insertions(+), 66 deletions(-) delete mode 100644 cosmrs/src/decimal.rs diff --git a/cosmrs/src/base.rs b/cosmrs/src/base.rs index 74f262fd..17c45d70 100644 --- a/cosmrs/src/base.rs +++ b/cosmrs/src/base.rs @@ -1,6 +1,6 @@ //! Base functionality. -use crate::{proto, Decimal, Error, ErrorReport, Result}; +use crate::{proto, Error, ErrorReport, Result}; use eyre::WrapErr; use serde::{de, de::Error as _, ser, Deserialize, Serialize}; use std::{fmt, str::FromStr}; @@ -128,13 +128,17 @@ impl Serialize for AccountId { } /// Coin defines a token with a denomination and an amount. -#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct Coin { /// Denomination pub denom: Denom, /// Amount - pub amount: Decimal, + // represent coin amount as an u128, which theoretically supports lower maximum value than + // cosmos-sdk's `Int` that has a maximum value of 2^256 - 1. (https://github.com/cosmos/cosmos-sdk/blob/v0.45.4/types/int.go#L72-L74=) + // But I would argue this is sufficient for the current realistic use cases and is less cumbersome to use than the `Decimal` + // (which should have been used for a `DecCoin`) + pub amount: u128, } impl TryFrom for Coin { @@ -171,6 +175,15 @@ impl From<&Coin> for proto::cosmos::base::v1beta1::Coin { } } +impl fmt::Display for Coin { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // Follow the same formatting without the space between amount and denom as + // Cosmwasm in their Coin, which is furthermore consistent with the cosmos-sdk: + // https://github.com/cosmos/cosmos-sdk/blob/v0.42.4/types/coin.go#L643-L645 + write!(f, "{}{}", self.amount, self.denom) + } +} + /// Denomination. #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct Denom(String); @@ -202,6 +215,20 @@ impl FromStr for Denom { } } +impl<'de> Deserialize<'de> for Denom { + fn deserialize>(deserializer: D) -> Result { + String::deserialize(deserializer)? + .parse() + .map_err(D::Error::custom) + } +} + +impl Serialize for Denom { + fn serialize(&self, serializer: S) -> Result { + self.0.serialize(serializer) + } +} + #[cfg(test)] mod tests { use super::{AccountId, Denom}; diff --git a/cosmrs/src/decimal.rs b/cosmrs/src/decimal.rs deleted file mode 100644 index b0db69e4..00000000 --- a/cosmrs/src/decimal.rs +++ /dev/null @@ -1,59 +0,0 @@ -//! Decimal type with equivalent semantics to the [Cosmos `sdk.Dec`][1] type. -//! -//! [1]: https://pkg.go.dev/github.com/cosmos/cosmos-sdk/types#Dec - -use crate::{ErrorReport, Result}; -use std::{ - fmt, - ops::{Add, AddAssign}, - str::FromStr, -}; - -/// Decimal type which follows Cosmos [Cosmos `sdk.Dec`][1] conventions. -/// -/// [1]: https://pkg.go.dev/github.com/cosmos/cosmos-sdk/types#Dec -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] -pub struct Decimal(u64); - -impl FromStr for Decimal { - type Err = ErrorReport; - - fn from_str(s: &str) -> Result { - Ok(s.parse().map(Self)?) - } -} - -impl fmt::Display for Decimal { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -impl Add for Decimal { - type Output = Decimal; - - #[inline] - fn add(self, rhs: Decimal) -> Decimal { - Decimal(self.0 + rhs.0) - } -} - -impl AddAssign for Decimal { - #[inline] - fn add_assign(&mut self, rhs: Decimal) { - self.0 += rhs.0; - } -} - -macro_rules! impl_from_primitive_int_for_decimal { - ($($int:ty),+) => { - $(impl From<$int> for Decimal { - fn from(num: $int) -> Decimal { - #[allow(trivial_numeric_casts)] - Decimal(num.into()) - } - })+ - }; -} - -impl_from_primitive_int_for_decimal!(u8, u16, u32, u64); diff --git a/cosmrs/src/lib.rs b/cosmrs/src/lib.rs index e88d9ef8..d434d6d3 100644 --- a/cosmrs/src/lib.rs +++ b/cosmrs/src/lib.rs @@ -34,13 +34,11 @@ pub mod cosmwasm; pub mod dev; mod base; -mod decimal; mod error; mod prost_ext; pub use crate::{ base::{AccountId, Coin, Denom}, - decimal::Decimal, error::{Error, Result}, tx::Tx, }; diff --git a/cosmrs/src/tx.rs b/cosmrs/src/tx.rs index 8124d2b3..baa87af9 100644 --- a/cosmrs/src/tx.rs +++ b/cosmrs/src/tx.rs @@ -47,7 +47,7 @@ //! // We'll be doing a simple send transaction. //! // First we'll create a "Coin" amount to be sent, in this case 1 million uatoms. //! let amount = Coin { -//! amount: 1_000_000u64.into(), +//! amount: 1_000_000u128, //! denom: "uatom".parse()?, //! }; //! diff --git a/cosmrs/src/tx/fee.rs b/cosmrs/src/tx/fee.rs index 394a78ee..d6d1c620 100644 --- a/cosmrs/src/tx/fee.rs +++ b/cosmrs/src/tx/fee.rs @@ -2,13 +2,14 @@ use super::Gas; use crate::{prost_ext::ParseOptional, proto, AccountId, Coin, ErrorReport, Result}; +use serde::{Deserialize, Serialize}; /// Fee includes the amount of coins paid in fees and the maximum gas to be /// used by the transaction. /// /// The ratio yields an effective “gasprice”, which must be above some minimum /// to be accepted into the mempool. -#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, PartialOrd, Ord, Serialize)] pub struct Fee { /// Amount of coins to be paid as a fee. pub amount: Vec,