diff --git a/examples/Cargo.lock b/examples/Cargo.lock index 74bcaebe..720c82bf 100644 --- a/examples/Cargo.lock +++ b/examples/Cargo.lock @@ -590,9 +590,12 @@ dependencies = [ "anyhow", "cosmwasm-schema", "cosmwasm-std", + "custom-and-generic", "cw-multi-test", "cw-storage-plus", "cw-utils", + "cw1", + "generic", "serde", "sylvia", ] diff --git a/examples/contracts/generic_contract/Cargo.toml b/examples/contracts/generic_contract/Cargo.toml index a34ded2b..af6f57dd 100644 --- a/examples/contracts/generic_contract/Cargo.toml +++ b/examples/contracts/generic_contract/Cargo.toml @@ -24,6 +24,9 @@ cw-storage-plus = "1.0" cw-utils = "1.0" serde = { version = "1.0", default-features = false, features = ["derive"] } sylvia = { path = "../../../sylvia" } +cw1 = { path = "../../interfaces/cw1" } +generic = { path = "../../interfaces/generic" } +custom-and-generic = { path = "../../interfaces/custom-and-generic" } [dev-dependencies] anyhow = "1.0" diff --git a/examples/contracts/generic_contract/src/bin/schema.rs b/examples/contracts/generic_contract/src/bin/schema.rs index a8828949..f84d1bb3 100644 --- a/examples/contracts/generic_contract/src/bin/schema.rs +++ b/examples/contracts/generic_contract/src/bin/schema.rs @@ -2,13 +2,12 @@ use cosmwasm_schema::write_api; #[cfg(not(tarpaulin_include))] fn main() { - use generic_contract::contract::{ - ContractExecMsg, ContractQueryMsg, ExternalMsg, InstantiateMsg, - }; + use generic_contract::contract::{ContractExecMsg, ContractQueryMsg, InstantiateMsg}; + use sylvia::types::SvCustomMsg; write_api! { - instantiate: InstantiateMsg, - execute: ContractExecMsg, - query: ContractQueryMsg, + instantiate: InstantiateMsg, + execute: ContractExecMsg, + query: ContractQueryMsg, } } diff --git a/examples/contracts/generic_contract/src/contract.rs b/examples/contracts/generic_contract/src/contract.rs index 9ef1ee4b..e253e06e 100644 --- a/examples/contracts/generic_contract/src/contract.rs +++ b/examples/contracts/generic_contract/src/contract.rs @@ -1,14 +1,11 @@ -use cosmwasm_schema::cw_serde; use cosmwasm_std::{Reply, Response, StdResult}; use serde::de::DeserializeOwned; use serde::Deserialize; -use sylvia::types::{CustomMsg, ExecCtx, InstantiateCtx, MigrateCtx, QueryCtx, ReplyCtx}; +use sylvia::types::{ + CustomMsg, ExecCtx, InstantiateCtx, MigrateCtx, QueryCtx, ReplyCtx, SvCustomMsg, +}; use sylvia::{contract, schemars}; -#[cw_serde] -pub struct ExternalMsg; -impl cosmwasm_std::CustomMsg for ExternalMsg {} - pub struct GenericContract( std::marker::PhantomData<( InstantiateParam, @@ -20,6 +17,10 @@ pub struct GenericContract as Generic: custom(msg))] +#[messages(custom_and_generic as CustomAndGeneric)] +#[sv::custom(msg=SvCustomMsg)] impl GenericContract where @@ -34,64 +35,79 @@ where } #[msg(instantiate)] - pub fn instantiate(&self, _ctx: InstantiateCtx, _msg: InstantiateParam) -> StdResult { + pub fn instantiate( + &self, + _ctx: InstantiateCtx, + _msg: InstantiateParam, + ) -> StdResult> { Ok(Response::new()) } #[msg(exec)] - pub fn execute(&self, _ctx: ExecCtx, _msg: ExecParam) -> StdResult { + pub fn contract_execute( + &self, + _ctx: ExecCtx, + _msg: ExecParam, + ) -> StdResult> { Ok(Response::new()) } #[msg(query)] - pub fn query(&self, _ctx: QueryCtx, _msg: QueryParam) -> StdResult { + pub fn contract_query( + &self, + _ctx: QueryCtx, + _msg: QueryParam, + ) -> StdResult> { Ok(Response::new()) } #[msg(migrate)] - pub fn migrate(&self, _ctx: MigrateCtx, _msg: MigrateParam) -> StdResult { + pub fn migrate( + &self, + _ctx: MigrateCtx, + _msg: MigrateParam, + ) -> StdResult> { Ok(Response::new()) } #[allow(dead_code)] #[msg(reply)] - fn reply(&self, _ctx: ReplyCtx, _reply: Reply) -> StdResult { + fn reply(&self, _ctx: ReplyCtx, _reply: Reply) -> StdResult> { Ok(Response::new()) } } #[cfg(test)] mod tests { + use super::multitest_utils::CodeId; use sylvia::multitest::App; - - use crate::contract::ExternalMsg; + use sylvia::types::SvCustomMsg; #[test] fn generic_contract() { - use super::multitest_utils::CodeId; - let app = App::default(); + let app = App::>::custom(|_, _, _| {}); let code_id: CodeId< - ExternalMsg, - ExternalMsg, - ExternalMsg, - super::ExternalMsg, - super::ExternalMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + super::SvCustomMsg, + super::SvCustomMsg, _, > = CodeId::store_code(&app); let owner = "owner"; let contract = code_id - .instantiate(ExternalMsg {}) + .instantiate(SvCustomMsg {}) .with_label("GenericContract") .with_admin(owner) .call(owner) .unwrap(); - contract.execute(ExternalMsg).call(owner).unwrap(); - contract.query(ExternalMsg).unwrap(); + contract.contract_execute(SvCustomMsg).call(owner).unwrap(); + contract.contract_query(SvCustomMsg).unwrap(); contract - .migrate(ExternalMsg) + .migrate(SvCustomMsg) .call(owner, code_id.code_id()) .unwrap(); } diff --git a/examples/contracts/generic_contract/src/custom_and_generic.rs b/examples/contracts/generic_contract/src/custom_and_generic.rs new file mode 100644 index 00000000..98926abc --- /dev/null +++ b/examples/contracts/generic_contract/src/custom_and_generic.rs @@ -0,0 +1,77 @@ +use cosmwasm_std::{CosmosMsg, Response, StdError, StdResult}; +use custom_and_generic::CustomAndGeneric; +use sylvia::contract; +use sylvia::types::{ExecCtx, QueryCtx, SvCustomMsg}; + +#[contract(module = crate::contract)] +#[messages(custom_and_generic as CustomAndGeneric)] +#[sv::custom(msg=sylvia::types::SvCustomMsg)] +impl + CustomAndGeneric + for crate::contract::GenericContract< + InstantiateParam, + ExecParam, + QueryParam, + MigrateParam, + RetType, + > +{ + type Error = StdError; + + #[msg(exec)] + fn custom_generic_execute( + &self, + _ctx: ExecCtx, + _msgs: Vec>, + ) -> StdResult> { + Ok(Response::new()) + } + + #[msg(query)] + fn custom_generic_query( + &self, + _ctx: QueryCtx, + _msg: sylvia::types::SvCustomMsg, + ) -> StdResult { + Ok(SvCustomMsg {}) + } +} + +#[cfg(test)] +mod tests { + use super::test_utils::CustomAndGeneric; + use crate::contract::multitest_utils::CodeId; + use sylvia::{multitest::App, types::SvCustomMsg}; + + #[test] + fn proxy_methods() { + let app = App::>::custom(|_, _, _| {}); + let code_id = CodeId::< + SvCustomMsg, + sylvia::types::SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + sylvia::types::SvCustomMsg, + _, + >::store_code(&app); + + let owner = "owner"; + + let contract = code_id + .instantiate(SvCustomMsg {}) + .with_label("GenericContract") + .with_admin(owner) + .call(owner) + .unwrap(); + + contract + .custom_and_generic_proxy() + .custom_generic_execute(vec![]) + .call(owner) + .unwrap(); + contract + .custom_and_generic_proxy() + .custom_generic_query(SvCustomMsg {}) + .unwrap(); + } +} diff --git a/examples/contracts/generic_contract/src/cw1.rs b/examples/contracts/generic_contract/src/cw1.rs new file mode 100644 index 00000000..48bd0870 --- /dev/null +++ b/examples/contracts/generic_contract/src/cw1.rs @@ -0,0 +1,70 @@ +use cosmwasm_std::{CosmosMsg, Response, StdError, StdResult}; +use cw1::{CanExecuteResp, Cw1}; +use sylvia::contract; +use sylvia::types::{ExecCtx, QueryCtx}; + +#[contract(module = crate::contract)] +#[messages(cw1 as Cw1)] +#[sv::custom(msg=sylvia::types::SvCustomMsg)] +impl Cw1 + for crate::contract::GenericContract< + InstantiateParam, + ExecParam, + QueryParam, + MigrateParam, + RetType, + > +{ + type Error = StdError; + + #[msg(exec)] + fn execute(&self, _ctx: ExecCtx, _msgs: Vec) -> StdResult { + Ok(Response::new()) + } + + #[msg(query)] + fn can_execute( + &self, + _ctx: QueryCtx, + _sender: String, + _msg: CosmosMsg, + ) -> StdResult { + Ok(CanExecuteResp::default()) + } +} + +#[cfg(test)] +mod tests { + use super::test_utils::Cw1; + use crate::contract::multitest_utils::CodeId; + use cosmwasm_std::{CosmosMsg, Empty}; + use sylvia::{multitest::App, types::SvCustomMsg}; + + #[test] + fn proxy_methods() { + let app = App::>::custom(|_, _, _| {}); + let code_id = CodeId::< + SvCustomMsg, + sylvia::types::SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + sylvia::types::SvCustomMsg, + _, + >::store_code(&app); + + let owner = "owner"; + + let contract = code_id + .instantiate(SvCustomMsg {}) + .with_label("GenericContract") + .with_admin(owner) + .call(owner) + .unwrap(); + + contract.cw1_proxy().execute(vec![]).call(owner).unwrap(); + contract + .cw1_proxy() + .can_execute("sender".to_owned(), CosmosMsg::Custom(Empty {})) + .unwrap(); + } +} diff --git a/examples/contracts/generic_contract/src/generic.rs b/examples/contracts/generic_contract/src/generic.rs new file mode 100644 index 00000000..aef1ac96 --- /dev/null +++ b/examples/contracts/generic_contract/src/generic.rs @@ -0,0 +1,80 @@ +use cosmwasm_std::{CosmosMsg, Response, StdError, StdResult}; +use generic::Generic; +use sylvia::contract; +use sylvia::types::{ExecCtx, QueryCtx, SvCustomMsg}; + +#[contract(module = crate::contract)] +#[messages(generic as Generic)] +#[sv::custom(msg=SvCustomMsg)] +impl + Generic + for crate::contract::GenericContract< + InstantiateParam, + ExecParam, + QueryParam, + MigrateParam, + RetType, + > +{ + type Error = StdError; + + #[msg(exec)] + fn generic_exec( + &self, + _ctx: ExecCtx, + _msgs: Vec>, + ) -> StdResult { + Ok(Response::new()) + } + + // Sylvia will fail if single type is used to match against two different generics + // It's because we have to map unique generics used as they can be used multiple times. + // If for some reason like here one type would be used in place of two generics either full + // path or some alias has to be used. + #[msg(query)] + fn generic_query( + &self, + _ctx: QueryCtx, + _msg: sylvia::types::SvCustomMsg, + ) -> StdResult { + Ok(SvCustomMsg {}) + } +} + +#[cfg(test)] +mod tests { + use super::test_utils::Generic; + use crate::contract::multitest_utils::CodeId; + use cosmwasm_std::CosmosMsg; + use sylvia::multitest::App; + use sylvia::types::SvCustomMsg; + + #[test] + fn proxy_methods() { + let app = App::>::custom(|_, _, _| {}); + let code_id: CodeId< + SvCustomMsg, + sylvia::types::SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + sylvia::types::SvCustomMsg, + _, + > = CodeId::store_code(&app); + + let owner = "owner"; + + let contract = code_id + .instantiate(SvCustomMsg {}) + .with_label("GenericContract") + .with_admin(owner) + .call(owner) + .unwrap(); + + contract + .generic_proxy() + .generic_exec(vec![CosmosMsg::Custom(SvCustomMsg {})]) + .call(owner) + .unwrap(); + contract.generic_proxy().generic_query(SvCustomMsg).unwrap(); + } +} diff --git a/examples/contracts/generic_contract/src/lib.rs b/examples/contracts/generic_contract/src/lib.rs index 2943dbb5..ea8b3738 100644 --- a/examples/contracts/generic_contract/src/lib.rs +++ b/examples/contracts/generic_contract/src/lib.rs @@ -1 +1,4 @@ pub mod contract; +pub mod custom_and_generic; +pub mod cw1; +pub mod generic;