diff --git a/Cargo.lock b/Cargo.lock index a9cd525..4352097 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -140,7 +140,7 @@ dependencies = [ [[package]] name = "cw-asset" -version = "1.0.0" +version = "1.0.1" dependencies = [ "astroport", "cosmwasm-std", diff --git a/Cargo.toml b/Cargo.toml index 7e8841b..87dad30 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "cw-asset" description = "Helper library for interacting with Cosmos assets (SDK coins and CW20 tokens)" -version = "1.0.0" +version = "1.0.1" authors = ["larry "] edition = "2018" license = "GPL-3.0-or-later" diff --git a/src/asset.rs b/src/asset.rs index ffcded3..ffa39aa 100644 --- a/src/asset.rs +++ b/src/asset.rs @@ -1,3 +1,4 @@ +use std::convert::TryFrom; use std::fmt; use cosmwasm_std::{ @@ -97,7 +98,7 @@ impl AssetUnchecked { /// Validate data contained in an _unchecked_ **asset** instnace, return a new _checked_ /// **asset** instance: /// * For CW20 tokens, assert the contract address is valid - /// * For SDK coins, assert that the denom is included in a given whitelist; skip if the + /// * For SDK coins, assert that the denom is included in a given whitelist; skip if the /// whitelist is not provided /// /// ```rust @@ -140,6 +141,45 @@ impl From<&Coin> for Asset { } } +impl TryFrom for Coin { + type Error = StdError; + fn try_from(asset: Asset) -> Result { + match &asset.info { + AssetInfo::Native(denom) => Ok(Coin { + denom: denom.clone(), + amount: asset.amount, + }), + AssetInfo::Cw20(_) => Err(StdError::generic_err( + format!("cannot cast asset {} into cosmwasm_std::Coin", asset.to_string()) + )), + } + } +} + +impl TryFrom<&Asset> for Coin { + type Error = StdError; + fn try_from(asset: &Asset) -> Result { + Coin::try_from(asset.clone()) + } +} + +impl std::cmp::PartialEq for Coin { + fn eq(&self, other: &Asset) -> bool { + match &other.info { + AssetInfo::Native(denom) => { + self.denom == *denom && self.amount == other.amount + } + AssetInfo::Cw20(_) => false + } + } +} + +impl std::cmp::PartialEq for Asset { + fn eq(&self, other: &Coin) -> bool { + other == self + } +} + impl Asset { /// Generate a message that sends a CW20 token to the specified recipient with a binary payload /// @@ -346,6 +386,27 @@ mod tests { ) } + #[test] + fn casting_coin() { + let uusd = Asset::native("uusd", 69u128); + let uusd_coin = Coin { + denom: String::from("uusd"), + amount: Uint128::new(69) + }; + assert_eq!(Coin::try_from(&uusd).unwrap(), uusd_coin); + assert_eq!(Coin::try_from(uusd).unwrap(), uusd_coin); + + let astro = Asset::cw20(Addr::unchecked("astro_token"), 69u128); + assert_eq!( + Coin::try_from(&astro), + Err(StdError::generic_err("cannot cast asset cw20:astro_token:69 into cosmwasm_std::Coin")) + ); + assert_eq!( + Coin::try_from(astro), + Err(StdError::generic_err("cannot cast asset cw20:astro_token:69 into cosmwasm_std::Coin")) + ); + } + #[test] fn comparing() { let uluna1 = Asset::native("uluna", 69u128); @@ -358,6 +419,27 @@ mod tests { assert_eq!(astro == astro.clone(), true); } + #[test] + fn comparing_coin() { + let uluna = Asset::native("uluna", 69u128); + let uusd_1 = Asset::native("uusd", 69u128); + let uusd_2 = Asset::native("uusd", 420u128); + let uusd_coin = Coin { + denom: String::from("uusd"), + amount: Uint128::new(69) + }; + let astro = Asset::cw20(Addr::unchecked("astro_token"), 69u128); + + assert_eq!(uluna == uusd_coin, false); + assert_eq!(uusd_coin == uluna, false); + assert_eq!(uusd_1 == uusd_coin, true); + assert_eq!(uusd_coin == uusd_1, true); + assert_eq!(uusd_2 == uusd_coin, false); + assert_eq!(uusd_coin == uusd_2, false); + assert_eq!(astro == uusd_coin, false); + assert_eq!(uusd_coin == astro, false); + } + #[test] fn displaying() { let asset = Asset::native("uusd", 69420u128);