From 56021f3bb62605876fb81173abb861baf6c40342 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Wo=C5=BAniak?= Date: Tue, 14 Nov 2023 15:51:40 +0100 Subject: [PATCH] fix: Allow generic return type in contract queries --- .../generic_contract/src/contract.rs | 51 ++++++++++++------- .../src/custom_and_generic.rs | 28 ++++++---- .../contracts/generic_contract/src/cw1.rs | 15 ++++-- .../contracts/generic_contract/src/generic.rs | 8 +-- .../generic_iface_on_contract/src/contract.rs | 18 ++++--- .../src/custom_and_generic.rs | 10 ++-- .../interfaces/custom-and-generic/src/lib.rs | 15 +++--- sylvia-derive/src/input.rs | 3 +- sylvia-derive/src/message.rs | 45 +++++++++++++--- sylvia/src/lib.rs | 2 +- sylvia/src/types.rs | 41 +++++++++------ 11 files changed, 159 insertions(+), 77 deletions(-) diff --git a/examples/contracts/generic_contract/src/contract.rs b/examples/contracts/generic_contract/src/contract.rs index 12f605f9..c367c280 100644 --- a/examples/contracts/generic_contract/src/contract.rs +++ b/examples/contracts/generic_contract/src/contract.rs @@ -3,7 +3,8 @@ use cw_storage_plus::Item; use serde::de::DeserializeOwned; use serde::Deserialize; use sylvia::types::{ - CustomMsg, ExecCtx, InstantiateCtx, MigrateCtx, QueryCtx, ReplyCtx, SvCustomMsg, + CustomMsg, CustomQuery, ExecCtx, InstantiateCtx, MigrateCtx, QueryCtx, ReplyCtx, SvCustomMsg, + SvCustomQuery, }; use sylvia::{contract, schemars}; @@ -16,6 +17,7 @@ pub struct GenericContract< QueryParam, MigrateParam, RetType, + CtxType, FieldType, > { _field: Item<'static, FieldType>, @@ -25,23 +27,33 @@ pub struct GenericContract< QueryParam, MigrateParam, RetType, + CtxType, )>, } -#[cfg_attr(not(feature = "library"), entry_points(generics))] +#[cfg_attr(not(feature = "library"), entry_points(generics))] #[contract] -#[messages(cw1 as Cw1: custom(msg))] -#[messages(generic as Generic: custom(msg))] -#[messages(custom_and_generic as CustomAndGeneric)] -#[sv::custom(msg=SvCustomMsg)] -impl - GenericContract +#[messages(cw1 as Cw1: custom(msg, query))] +#[messages(generic as Generic: custom(msg, query))] +#[messages(custom_and_generic as CustomAndGeneric)] +#[sv::custom(msg=SvCustomMsg, query=SvCustomQuery)] +impl + GenericContract< + InstantiateParam, + ExecParam, + QueryParam, + MigrateParam, + RetType, + CtxQuery, + FieldType, + > where for<'msg_de> InstantiateParam: CustomMsg + Deserialize<'msg_de> + 'msg_de, ExecParam: CustomMsg + DeserializeOwned + 'static, QueryParam: CustomMsg + DeserializeOwned + 'static, MigrateParam: CustomMsg + DeserializeOwned + 'static, RetType: CustomMsg + DeserializeOwned + 'static, + CtxQuery: CustomQuery + 'static, FieldType: 'static, { pub const fn new() -> Self { @@ -54,7 +66,7 @@ where #[msg(instantiate)] pub fn instantiate( &self, - _ctx: InstantiateCtx, + _ctx: InstantiateCtx, _msg: InstantiateParam, ) -> StdResult> { Ok(Response::new()) @@ -63,7 +75,7 @@ where #[msg(exec)] pub fn contract_execute( &self, - _ctx: ExecCtx, + _ctx: ExecCtx, _msg: ExecParam, ) -> StdResult> { Ok(Response::new()) @@ -72,16 +84,16 @@ where #[msg(query)] pub fn contract_query( &self, - _ctx: QueryCtx, + _ctx: QueryCtx, _msg: QueryParam, - ) -> StdResult> { - Ok(Response::new()) + ) -> StdResult { + Ok(String::default()) } #[msg(migrate)] pub fn migrate( &self, - _ctx: MigrateCtx, + _ctx: MigrateCtx, _msg: MigrateParam, ) -> StdResult> { Ok(Response::new()) @@ -89,7 +101,11 @@ where #[allow(dead_code)] #[msg(reply)] - fn reply(&self, _ctx: ReplyCtx, _reply: Reply) -> StdResult> { + fn reply( + &self, + _ctx: ReplyCtx, + _reply: Reply, + ) -> StdResult> { Ok(Response::new()) } } @@ -98,17 +114,18 @@ where mod tests { use super::sv::multitest_utils::CodeId; use sylvia::multitest::App; - use sylvia::types::SvCustomMsg; + use sylvia::types::{SvCustomMsg, SvCustomQuery}; #[test] fn generic_contract() { - let app = App::>::custom(|_, _, _| {}); + let app = App::>::custom(|_, _, _| {}); let code_id: CodeId< SvCustomMsg, SvCustomMsg, SvCustomMsg, super::SvCustomMsg, super::SvCustomMsg, + SvCustomQuery, String, _, > = CodeId::store_code(&app); diff --git a/examples/contracts/generic_contract/src/custom_and_generic.rs b/examples/contracts/generic_contract/src/custom_and_generic.rs index 2dfadcd0..6c6d067f 100644 --- a/examples/contracts/generic_contract/src/custom_and_generic.rs +++ b/examples/contracts/generic_contract/src/custom_and_generic.rs @@ -1,19 +1,25 @@ use cosmwasm_std::{CosmosMsg, Response, StdError, StdResult}; use custom_and_generic::CustomAndGeneric; use sylvia::contract; -use sylvia::types::{ExecCtx, QueryCtx, SvCustomMsg}; +use sylvia::types::{ExecCtx, QueryCtx, SvCustomMsg, SvCustomQuery}; #[contract(module = crate::contract)] #[messages(custom_and_generic as CustomAndGeneric)] -#[sv::custom(msg=sylvia::types::SvCustomMsg)] -impl - CustomAndGeneric +#[sv::custom(msg=SvCustomMsg, query=SvCustomQuery)] +impl + CustomAndGeneric< + SvCustomMsg, + SvCustomMsg, + sylvia::types::SvCustomQuery, + sylvia::types::SvCustomMsg, + > for crate::contract::GenericContract< InstantiateParam, ExecParam, QueryParam, MigrateParam, RetType, + CtxQuery, FieldType, > { @@ -22,7 +28,7 @@ impl #[msg(exec)] fn custom_generic_execute( &self, - _ctx: ExecCtx, + _ctx: ExecCtx, _msgs: Vec>, ) -> StdResult> { Ok(Response::new()) @@ -31,7 +37,7 @@ impl #[msg(query)] fn custom_generic_query( &self, - _ctx: QueryCtx, + _ctx: QueryCtx, _msg: sylvia::types::SvCustomMsg, ) -> StdResult { Ok(SvCustomMsg {}) @@ -42,17 +48,21 @@ impl mod tests { use super::sv::test_utils::CustomAndGeneric; use crate::contract::sv::multitest_utils::CodeId; - use sylvia::{multitest::App, types::SvCustomMsg}; + use sylvia::{ + multitest::App, + types::{SvCustomMsg, SvCustomQuery}, + }; #[test] fn proxy_methods() { - let app = App::>::custom(|_, _, _| {}); + let app = App::>::custom(|_, _, _| {}); let code_id = CodeId::< SvCustomMsg, sylvia::types::SvCustomMsg, SvCustomMsg, SvCustomMsg, - sylvia::types::SvCustomMsg, + SvCustomMsg, + SvCustomQuery, String, _, >::store_code(&app); diff --git a/examples/contracts/generic_contract/src/cw1.rs b/examples/contracts/generic_contract/src/cw1.rs index 410bd13d..80eb2021 100644 --- a/examples/contracts/generic_contract/src/cw1.rs +++ b/examples/contracts/generic_contract/src/cw1.rs @@ -5,14 +5,15 @@ use sylvia::types::{ExecCtx, QueryCtx}; #[contract(module = crate::contract)] #[messages(cw1 as Cw1)] -#[sv::custom(msg=sylvia::types::SvCustomMsg)] -impl Cw1 +#[sv::custom(msg=sylvia::types::SvCustomMsg, query=sylvia::types::SvCustomQuery)] +impl Cw1 for crate::contract::GenericContract< InstantiateParam, ExecParam, QueryParam, MigrateParam, RetType, + CtxQuery, FieldType, > { @@ -39,17 +40,21 @@ mod tests { use super::sv::test_utils::Cw1; use crate::contract::sv::multitest_utils::CodeId; use cosmwasm_std::{CosmosMsg, Empty}; - use sylvia::{multitest::App, types::SvCustomMsg}; + use sylvia::{ + multitest::App, + types::{SvCustomMsg, SvCustomQuery}, + }; #[test] fn proxy_methods() { - let app = App::>::custom(|_, _, _| {}); + let app = App::>::custom(|_, _, _| {}); let code_id = CodeId::< SvCustomMsg, sylvia::types::SvCustomMsg, SvCustomMsg, SvCustomMsg, - sylvia::types::SvCustomMsg, + SvCustomMsg, + SvCustomQuery, String, _, >::store_code(&app); diff --git a/examples/contracts/generic_contract/src/generic.rs b/examples/contracts/generic_contract/src/generic.rs index 27176d94..2173633a 100644 --- a/examples/contracts/generic_contract/src/generic.rs +++ b/examples/contracts/generic_contract/src/generic.rs @@ -6,7 +6,7 @@ use sylvia::types::{ExecCtx, QueryCtx, SvCustomMsg}; #[contract(module = crate::contract)] #[messages(generic as Generic)] #[sv::custom(msg=SvCustomMsg)] -impl +impl Generic for crate::contract::GenericContract< InstantiateParam, @@ -14,6 +14,7 @@ impl QueryParam, MigrateParam, RetType, + CtxQuery, FieldType, > { @@ -48,17 +49,18 @@ mod tests { use crate::contract::sv::multitest_utils::CodeId; use cosmwasm_std::CosmosMsg; use sylvia::multitest::App; - use sylvia::types::SvCustomMsg; + use sylvia::types::{SvCustomMsg, SvCustomQuery}; #[test] fn proxy_methods() { - let app = App::>::custom(|_, _, _| {}); + let app = App::>::custom(|_, _, _| {}); let code_id: CodeId< SvCustomMsg, sylvia::types::SvCustomMsg, SvCustomMsg, SvCustomMsg, sylvia::types::SvCustomMsg, + SvCustomQuery, String, _, > = CodeId::store_code(&app); diff --git a/examples/contracts/generic_iface_on_contract/src/contract.rs b/examples/contracts/generic_iface_on_contract/src/contract.rs index a8f92805..70c602fd 100644 --- a/examples/contracts/generic_iface_on_contract/src/contract.rs +++ b/examples/contracts/generic_iface_on_contract/src/contract.rs @@ -1,5 +1,5 @@ use cosmwasm_std::{Response, StdResult}; -use sylvia::types::{InstantiateCtx, SvCustomMsg}; +use sylvia::types::{InstantiateCtx, SvCustomMsg, SvCustomQuery}; use sylvia::{contract, schemars}; #[cfg(not(feature = "library"))] @@ -9,18 +9,21 @@ pub struct NonGenericContract; #[cfg_attr(not(feature = "library"), entry_points)] #[contract] -#[messages(generic as Generic: custom(msg))] -#[messages(custom_and_generic as CustomAndGeneric)] -#[messages(cw1 as Cw1: custom(msg))] +#[messages(generic as Generic: custom(msg, query))] +#[messages(custom_and_generic as CustomAndGeneric)] +#[messages(cw1 as Cw1: custom(msg, query))] /// Required if interface returns generic `Response` -#[sv::custom(msg=SvCustomMsg)] +#[sv::custom(msg=SvCustomMsg, query=SvCustomQuery)] impl NonGenericContract { pub const fn new() -> Self { Self } #[msg(instantiate)] - pub fn instantiate(&self, _ctx: InstantiateCtx) -> StdResult> { + pub fn instantiate( + &self, + _ctx: InstantiateCtx, + ) -> StdResult> { Ok(Response::new()) } } @@ -28,6 +31,7 @@ impl NonGenericContract { #[cfg(test)] mod tests { use cosmwasm_std::{CosmosMsg, Empty}; + use sylvia::types::SvCustomQuery; use sylvia::{multitest::App, types::SvCustomMsg}; use super::NonGenericContract; @@ -38,7 +42,7 @@ mod tests { #[test] fn mt_helpers() { let _ = NonGenericContract::new(); - let app = App::>::custom(|_, _, _| {}); + let app = App::>::custom(|_, _, _| {}); let code_id = super::sv::multitest_utils::CodeId::store_code(&app); let owner = "owner"; diff --git a/examples/contracts/generic_iface_on_contract/src/custom_and_generic.rs b/examples/contracts/generic_iface_on_contract/src/custom_and_generic.rs index 90052b86..346d4f27 100644 --- a/examples/contracts/generic_iface_on_contract/src/custom_and_generic.rs +++ b/examples/contracts/generic_iface_on_contract/src/custom_and_generic.rs @@ -1,12 +1,12 @@ use cosmwasm_std::{CosmosMsg, Response, StdError, StdResult}; use custom_and_generic::CustomAndGeneric; use sylvia::contract; -use sylvia::types::{ExecCtx, QueryCtx, SvCustomMsg}; +use sylvia::types::{ExecCtx, QueryCtx, SvCustomMsg, SvCustomQuery}; #[contract(module = crate::contract)] #[messages(custom_and_generic as CustomAndGeneric)] -#[sv::custom(msg=sylvia::types::SvCustomMsg)] -impl CustomAndGeneric +#[sv::custom(msg=sylvia::types::SvCustomMsg, query=SvCustomQuery)] +impl CustomAndGeneric for crate::contract::NonGenericContract { type Error = StdError; @@ -14,7 +14,7 @@ impl CustomAndGeneric #[msg(exec)] fn custom_generic_execute( &self, - _ctx: ExecCtx, + _ctx: ExecCtx, _msgs: Vec>, ) -> StdResult> { Ok(Response::new()) @@ -23,7 +23,7 @@ impl CustomAndGeneric #[msg(query)] fn custom_generic_query( &self, - _ctx: QueryCtx, + _ctx: QueryCtx, _msg: sylvia::types::SvCustomMsg, ) -> StdResult { Ok(SvCustomMsg {}) diff --git a/examples/interfaces/custom-and-generic/src/lib.rs b/examples/interfaces/custom-and-generic/src/lib.rs index f56d4503..d7ff14c7 100644 --- a/examples/interfaces/custom-and-generic/src/lib.rs +++ b/examples/interfaces/custom-and-generic/src/lib.rs @@ -6,11 +6,12 @@ use sylvia::types::{ExecCtx, QueryCtx}; use sylvia::{interface, schemars}; #[interface] -#[sv::custom(msg=RetType)] -pub trait CustomAndGeneric +#[sv::custom(msg=RetType, query=CtxQuery)] +pub trait CustomAndGeneric where for<'msg_de> ExecParam: CustomMsg + Deserialize<'msg_de>, QueryParam: sylvia::types::CustomMsg, + CtxQuery: sylvia::types::CustomQuery, RetType: CustomMsg + DeserializeOwned, { type Error: From; @@ -18,14 +19,14 @@ where #[msg(exec)] fn custom_generic_execute( &self, - ctx: ExecCtx, + ctx: ExecCtx, msgs: Vec>, ) -> Result, Self::Error>; #[msg(query)] fn custom_generic_query( &self, - ctx: QueryCtx, + ctx: QueryCtx, param: QueryParam, ) -> Result; } @@ -34,7 +35,7 @@ where mod tests { use cosmwasm_std::testing::mock_dependencies; use cosmwasm_std::{Addr, CosmosMsg, Empty, QuerierWrapper}; - use sylvia::types::{InterfaceApi, SvCustomMsg}; + use sylvia::types::{InterfaceApi, SvCustomMsg, SvCustomQuery}; use crate::sv::Querier; @@ -58,11 +59,11 @@ mod tests { // Construct messages with Interface extension let _ = - as InterfaceApi>::Query::custom_generic_query( + as InterfaceApi>::Query::custom_generic_query( SvCustomMsg {}, ); let _= - as InterfaceApi>::Exec::custom_generic_execute( + as InterfaceApi>::Exec::custom_generic_execute( vec![ CosmosMsg::Custom(SvCustomMsg{}), ]); } diff --git a/sylvia-derive/src/input.rs b/sylvia-derive/src/input.rs index 839702cc..edbee10c 100644 --- a/sylvia-derive/src/input.rs +++ b/sylvia-derive/src/input.rs @@ -209,7 +209,8 @@ impl<'a> ImplInput<'a> { let messages = self.emit_messages(); let remote = Remote::new(&self.interfaces).emit(); let querier_from_impl = self.interfaces.emit_querier_from_impl(); - let contract_api = ContractApi::new(item, generics, custom).emit(); + let contract_api = + ContractApi::new(item, generics, &item.generics.where_clause, custom).emit(); #[cfg(not(tarpaulin_include))] { diff --git a/sylvia-derive/src/message.rs b/sylvia-derive/src/message.rs index 2ac57d84..2a01c63f 100644 --- a/sylvia-derive/src/message.rs +++ b/sylvia-derive/src/message.rs @@ -398,9 +398,9 @@ impl<'a> ContractEnumMessage<'a> { let enum_name = msg_ty.emit_msg_name(false); let match_arms = variants.emit_dispatch_legs(); let unused_generics = variants.unused_generics(); - let unused_generics = emit_bracketed_generics(unused_generics); + let bracketed_unused_generics = emit_bracketed_generics(unused_generics); let used_generics = variants.used_generics(); - let used_generics = emit_bracketed_generics(used_generics); + let bracketed_used_generics = emit_bracketed_generics(used_generics); let mut variant_names = variants.as_names_snake_cased(); variant_names.sort(); @@ -419,22 +419,49 @@ impl<'a> ContractEnumMessage<'a> { let ep_name = msg_ty.emit_ep_name(); let messages_fn_name = Ident::new(&format!("{}_messages", ep_name), contract.span()); + let phantom = if used_generics.is_empty() { + quote! {} + } else if MsgType::Query == *msg_ty { + quote! { + #[serde(skip)] + #[returns((#(#used_generics,)*))] + _Phantom(std::marker::PhantomData<( #(#used_generics,)* )>), + } + } else { + quote! { + #[serde(skip)] + _Phantom(std::marker::PhantomData<( #(#used_generics,)* )>), + } + }; + + let match_arms = if !used_generics.is_empty() { + quote! { + #(#match_arms,)* + _Phantom(_) => Err(#sylvia ::cw_std::StdError::generic_err("Phantom message should not be constructed.")).map_err(Into::into), + } + } else { + quote! { + #(#match_arms,)* + } + }; + #[cfg(not(tarpaulin_include))] { quote! { #[allow(clippy::derive_partial_eq_without_eq)] #[derive(#sylvia ::serde::Serialize, #sylvia ::serde::Deserialize, Clone, Debug, PartialEq, #sylvia ::schemars::JsonSchema, #derive_query )] #[serde(rename_all="snake_case")] - pub enum #enum_name #used_generics { + pub enum #enum_name #bracketed_used_generics { #(#variants,)* + #phantom } - impl #used_generics #enum_name #used_generics { - pub fn dispatch #unused_generics (self, contract: &#contract, ctx: #ctx_type) -> #ret_type #where_clause { + impl #bracketed_used_generics #enum_name #bracketed_used_generics { + pub fn dispatch #bracketed_unused_generics (self, contract: &#contract, ctx: #ctx_type) -> #ret_type #where_clause { use #enum_name::*; match self { - #(#match_arms,)* + #match_arms } } @@ -1443,6 +1470,7 @@ pub struct ContractApi<'a> { instantiate_variants: MsgVariants<'a, GenericParam>, migrate_variants: MsgVariants<'a, GenericParam>, generics: &'a [&'a GenericParam], + where_clause: &'a Option, custom: &'a Custom<'a>, } @@ -1450,6 +1478,7 @@ impl<'a> ContractApi<'a> { pub fn new( source: &'a ItemImpl, generics: &'a [&'a GenericParam], + where_clause: &'a Option, custom: &'a Custom<'a>, ) -> Self { let exec_variants = MsgVariants::new( @@ -1487,6 +1516,7 @@ impl<'a> ContractApi<'a> { instantiate_variants, migrate_variants, generics, + where_clause, custom, } } @@ -1500,6 +1530,7 @@ impl<'a> ContractApi<'a> { instantiate_variants, migrate_variants, generics, + where_clause, custom, } = self; @@ -1522,7 +1553,7 @@ impl<'a> ContractApi<'a> { let custom_query = custom.query_or_default(); quote! { - impl #bracket_generics #sylvia ::types::ContractApi for #contract_name { + impl #bracket_generics #sylvia ::types::ContractApi for #contract_name #where_clause { type ContractExec = ContractExecMsg #exec_bracketed_generics; type ContractQuery = ContractQueryMsg #query_bracketed_generics; type Exec = ExecMsg #exec_bracketed_generics; diff --git a/sylvia/src/lib.rs b/sylvia/src/lib.rs index 66afeb6f..7ae1602f 100644 --- a/sylvia/src/lib.rs +++ b/sylvia/src/lib.rs @@ -1,6 +1,6 @@ //! Framework for creating CosmWasm Smart Contract with high-level abstraction layer //! -//! Most of implementation lies in `cw-derive-ng` crate which is reexported here +//! Most of implementation lies in `sylvia-derive` crate which is reexported here pub mod into_response; #[cfg(feature = "mt")] diff --git a/sylvia/src/types.rs b/sylvia/src/types.rs index d5c3d330..96648ce5 100644 --- a/sylvia/src/types.rs +++ b/sylvia/src/types.rs @@ -1,41 +1,41 @@ use cosmwasm_schema::cw_serde; -use cosmwasm_std::{CustomQuery, Deps, DepsMut, Empty, Env, MessageInfo}; +use cosmwasm_std::{Deps, DepsMut, Empty, Env, MessageInfo}; use serde::de::DeserializeOwned; -pub struct ReplyCtx<'a, C: CustomQuery = Empty> { +pub struct ReplyCtx<'a, C: cosmwasm_std::CustomQuery = Empty> { pub deps: DepsMut<'a, C>, pub env: Env, } -pub struct MigrateCtx<'a, C: CustomQuery = Empty> { +pub struct MigrateCtx<'a, C: cosmwasm_std::CustomQuery = Empty> { pub deps: DepsMut<'a, C>, pub env: Env, } -pub struct ExecCtx<'a, C: CustomQuery = Empty> { +pub struct ExecCtx<'a, C: cosmwasm_std::CustomQuery = Empty> { pub deps: DepsMut<'a, C>, pub env: Env, pub info: MessageInfo, } -pub struct InstantiateCtx<'a, C: CustomQuery = Empty> { +pub struct InstantiateCtx<'a, C: cosmwasm_std::CustomQuery = Empty> { pub deps: DepsMut<'a, C>, pub env: Env, pub info: MessageInfo, } -pub struct QueryCtx<'a, C: CustomQuery = Empty> { +pub struct QueryCtx<'a, C: cosmwasm_std::CustomQuery = Empty> { pub deps: Deps<'a, C>, pub env: Env, } -pub struct SudoCtx<'a, C: CustomQuery = Empty> { +pub struct SudoCtx<'a, C: cosmwasm_std::CustomQuery = Empty> { pub deps: DepsMut<'a, C>, pub env: Env, } #[cfg(not(tarpaulin_include))] -impl ExecCtx<'_, C> { +impl ExecCtx<'_, C> { pub fn branch(&'_ mut self) -> ExecCtx<'_, C> { ExecCtx { deps: self.deps.branch(), @@ -46,7 +46,7 @@ impl ExecCtx<'_, C> { } #[cfg(not(tarpaulin_include))] -impl InstantiateCtx<'_, C> { +impl InstantiateCtx<'_, C> { pub fn branch(&'_ mut self) -> InstantiateCtx<'_, C> { InstantiateCtx { deps: self.deps.branch(), @@ -57,7 +57,7 @@ impl InstantiateCtx<'_, C> { } #[cfg(not(tarpaulin_include))] -impl SudoCtx<'_, C> { +impl SudoCtx<'_, C> { pub fn branch(&'_ mut self) -> SudoCtx<'_, C> { SudoCtx { deps: self.deps.branch(), @@ -66,31 +66,33 @@ impl SudoCtx<'_, C> { } } -impl<'a, C: CustomQuery> From<(DepsMut<'a, C>, Env)> for MigrateCtx<'a, C> { +impl<'a, C: cosmwasm_std::CustomQuery> From<(DepsMut<'a, C>, Env)> for MigrateCtx<'a, C> { fn from((deps, env): (DepsMut<'a, C>, Env)) -> Self { Self { deps, env } } } -impl<'a, C: CustomQuery> From<(DepsMut<'a, C>, Env)> for ReplyCtx<'a, C> { +impl<'a, C: cosmwasm_std::CustomQuery> From<(DepsMut<'a, C>, Env)> for ReplyCtx<'a, C> { fn from((deps, env): (DepsMut<'a, C>, Env)) -> Self { Self { deps, env } } } -impl<'a, C: CustomQuery> From<(DepsMut<'a, C>, Env, MessageInfo)> for ExecCtx<'a, C> { +impl<'a, C: cosmwasm_std::CustomQuery> From<(DepsMut<'a, C>, Env, MessageInfo)> for ExecCtx<'a, C> { fn from((deps, env, info): (DepsMut<'a, C>, Env, MessageInfo)) -> Self { Self { deps, env, info } } } -impl<'a, C: CustomQuery> From<(DepsMut<'a, C>, Env, MessageInfo)> for InstantiateCtx<'a, C> { +impl<'a, C: cosmwasm_std::CustomQuery> From<(DepsMut<'a, C>, Env, MessageInfo)> + for InstantiateCtx<'a, C> +{ fn from((deps, env, info): (DepsMut<'a, C>, Env, MessageInfo)) -> Self { Self { deps, env, info } } } -impl<'a, C: CustomQuery> From<(Deps<'a, C>, Env)> for QueryCtx<'a, C> { +impl<'a, C: cosmwasm_std::CustomQuery> From<(Deps<'a, C>, Env)> for QueryCtx<'a, C> { fn from((deps, env): (Deps<'a, C>, Env)) -> Self { Self { deps, env } } @@ -100,11 +102,20 @@ pub trait CustomMsg: cosmwasm_std::CustomMsg + DeserializeOwned {} impl CustomMsg for T where T: cosmwasm_std::CustomMsg + DeserializeOwned {} +pub trait CustomQuery: cosmwasm_std::CustomQuery + DeserializeOwned {} + +impl CustomQuery for T where T: cosmwasm_std::CustomQuery + DeserializeOwned {} + #[cw_serde] pub struct SvCustomMsg; impl cosmwasm_std::CustomMsg for SvCustomMsg {} +#[cw_serde] +pub struct SvCustomQuery; + +impl cosmwasm_std::CustomQuery for SvCustomQuery {} + pub trait InterfaceApi { type Exec; type Query;