diff --git a/sylvia/tests/generics.rs b/sylvia/tests/generics.rs index 7551600e..73f36fd4 100644 --- a/sylvia/tests/generics.rs +++ b/sylvia/tests/generics.rs @@ -13,7 +13,7 @@ pub mod cw1 { where for<'msg_de> Msg: CustomMsg + Deserialize<'msg_de>, Param: sylvia::types::CustomMsg, - for<'msg_de> QueryRet: CustomQuery + DeserializeOwned, + QueryRet: CustomQuery + DeserializeOwned, { type Error: From; @@ -29,6 +29,56 @@ pub mod cw1 { } } +pub mod whitelist { + use cosmwasm_std::{CosmosMsg, CustomMsg, CustomQuery, Response, StdError}; + + use serde::de::DeserializeOwned; + use serde::Deserialize; + use sylvia::types::{ExecCtx, QueryCtx}; + use sylvia_derive::interface; + + #[interface(module=msg)] + pub trait Whitelist + where + for<'msg_de> Msg: CustomMsg + Deserialize<'msg_de>, + for<'msg_de> QueryRet: CustomQuery + DeserializeOwned, + { + type Error: From; + + #[msg(exec)] + fn update_admins( + &self, + ctx: ExecCtx, + msgs: Vec>, + ) -> Result; + + #[msg(query)] + fn admins_list(&self, ctx: QueryCtx) -> Result; + } +} + +pub mod non_generic { + use cosmwasm_std::{CosmosMsg, Empty, Response, StdError}; + + use sylvia::types::{ExecCtx, QueryCtx}; + use sylvia_derive::interface; + + #[interface(module=msg)] + pub trait NonGeneric { + type Error: From; + + #[msg(exec)] + fn non_generic_exec( + &self, + ctx: ExecCtx, + msgs: Vec>, + ) -> Result; + + #[msg(query)] + fn non_generic_query(&self, ctx: QueryCtx) -> Result; + } +} + pub mod cw1_contract { use cosmwasm_std::{Response, StdResult}; use sylvia::types::InstantiateCtx; @@ -40,6 +90,8 @@ pub mod cw1_contract { #[contract] #[messages(crate::cw1 as Cw1)] + #[messages(crate::whitelist as Whitelist: custom(msg))] + #[messages(crate::non_generic as NonGeneric: custom(msg))] /// Required if interface returns generic `Response` #[sv::custom(msg=ExternalMsg)] impl Cw1Contract { @@ -54,6 +106,66 @@ pub mod cw1_contract { } } +pub mod impl_non_generic { + use crate::cw1_contract::Cw1Contract; + use crate::non_generic::NonGeneric; + use cosmwasm_std::{CosmosMsg, Empty, Response, StdError}; + use sylvia::types::{ExecCtx, QueryCtx}; + use sylvia_derive::contract; + + #[contract(module = crate::cw1_contract)] + #[messages(crate::non_generic as NonGeneric)] + #[sv::custom(msg=crate::ExternalMsg)] + impl NonGeneric for Cw1Contract { + type Error = StdError; + + #[msg(exec)] + fn non_generic_exec( + &self, + _ctx: ExecCtx, + _msgs: Vec>, + ) -> Result { + Ok(Response::new()) + } + + #[msg(query)] + fn non_generic_query(&self, _ctx: QueryCtx) -> Result { + Ok(Response::default()) + } + } +} + +pub mod impl_whitelist { + use cosmwasm_std::{CosmosMsg, Response, StdError}; + use sylvia::types::{ExecCtx, QueryCtx}; + use sylvia_derive::contract; + + use crate::cw1_contract::Cw1Contract; + use crate::whitelist::Whitelist; + use crate::{ExternalMsg, ExternalQuery}; + + #[contract(module = crate::cw1_contract)] + #[messages(crate::whitelist as Whitelist)] + #[sv::custom(msg=ExternalMsg)] + impl Whitelist for Cw1Contract { + type Error = StdError; + + #[msg(exec)] + fn update_admins( + &self, + _ctx: ExecCtx, + _msgs: Vec>, + ) -> Result { + Ok(Response::new()) + } + + #[msg(query)] + fn admins_list(&self, _ctx: QueryCtx) -> Result { + Ok(ExternalQuery {}) + } + } +} + pub mod impl_cw1 { use cosmwasm_std::{CosmosMsg, Response, StdError}; use sylvia::types::{ExecCtx, QueryCtx}; @@ -63,6 +175,7 @@ pub mod impl_cw1 { #[contract(module = crate::cw1_contract)] #[messages(crate::cw1 as Cw1)] + #[sv::custom(msg=ExternalMsg)] impl Cw1 for Cw1Contract { type Error = StdError; @@ -93,22 +206,38 @@ impl cosmwasm_std::CustomMsg for ExternalMsg {} #[cw_serde] pub struct ExternalQuery; impl cosmwasm_std::CustomQuery for ExternalQuery {} - #[cfg(all(test, feature = "mt"))] mod tests { use crate::cw1::{InterfaceTypes, Querier as Cw1Querier}; + use crate::cw1_contract::Cw1Contract; + use crate::impl_cw1::test_utils::Cw1; + use crate::impl_non_generic::test_utils::NonGeneric; + use crate::impl_whitelist::test_utils::Whitelist; + use crate::non_generic::Querier as NonGenericQuerier; + use crate::whitelist::Querier as WhitelistQuerier; use crate::{ExternalMsg, ExternalQuery}; use cosmwasm_std::{testing::mock_dependencies, Addr, CosmosMsg, Empty, QuerierWrapper}; + use sylvia::multitest::App; use sylvia::types::InterfaceMessages; #[test] fn construct_messages() { let contract = Addr::unchecked("contract"); + // Direct message construction + // cw1 let _ = crate::cw1::QueryMsg::<_, Empty>::some_query(ExternalMsg {}); let _ = crate::cw1::ExecMsg::execute(vec![CosmosMsg::Custom(ExternalMsg {})]); let _ = crate::cw1::ExecMsg::execute(vec![CosmosMsg::Custom(Empty {})]); + // whitelist + let _ = crate::whitelist::QueryMsg::::admins_list(); + let _ = crate::whitelist::ExecMsg::update_admins(vec![CosmosMsg::Custom(ExternalMsg {})]); + + // non_generic + let _ = crate::non_generic::QueryMsg::non_generic_query(); + let _ = crate::non_generic::ExecMsg::non_generic_exec(vec![]); + // Generic Querier let deps = mock_dependencies(); let querier: QuerierWrapper = QuerierWrapper::new(&deps.querier); @@ -120,6 +249,8 @@ mod tests { let contract_querier = crate::cw1_contract::BoundQuerier::borrowed(&contract, &querier); let _: Result = contract_querier.some_query(ExternalMsg {}); + let _: Result = contract_querier.admins_list(); + let _ = contract_querier.non_generic_query(); // Construct messages with Interface extension let _ = @@ -131,4 +262,39 @@ mod tests { CosmosMsg::Custom(ExternalMsg {}), ]); } + + #[test] + fn mt_helpers() { + let _ = Cw1Contract::new(); + let app = App::>::custom(|_, _, _| {}); + let code_id = crate::cw1_contract::multitest_utils::CodeId::store_code(&app); + + let owner = "owner"; + + let contract = code_id + .instantiate() + .with_label("Cw1Contract") + .call(owner) + .unwrap(); + + // CustomMsg generic Interface + contract.cw1_proxy().some_query(ExternalMsg {}).unwrap(); + contract.cw1_proxy().execute(vec![]).call(owner).unwrap(); + + // Non-CustomMsg generic Interface + contract.whitelist_proxy().admins_list().unwrap(); + contract + .whitelist_proxy() + .update_admins(vec![]) + .call(owner) + .unwrap(); + + // Non-CustomMsg non-generic Interface + contract.non_generic_proxy().non_generic_query().unwrap(); + contract + .non_generic_proxy() + .non_generic_exec(vec![]) + .call(owner) + .unwrap(); + } }