Repository: CosmWasm/sylvia
Pull request #318 (2024-03-05 13:00:21)

feat: `#[contract(module=...)]` and `#[messages]` not needed for trait impl


Patch:
diff --git a/examples/interfaces/custom-and-generic/src/lib.rs b/examples/interfaces/custom-and-generic/src/lib.rs
index a06a6cb..fb20955 100644
--- a/examples/interfaces/custom-and-generic/src/lib.rs
+++ b/examples/interfaces/custom-and-generic/src/lib.rs
@@ -103,18 +103,20 @@ mod tests {
         let deps = mock_dependencies();
         let querier_wrapper: QuerierWrapper = QuerierWrapper::new(&deps.querier);
 
-        let querier = super::sv::BoundQuerier::<
+        let querier = sylvia::types::BoundQuerier::<
             _,
-            Empty,
-            SvCustomMsg,
-            SvCustomMsg,
-            SvCustomMsg,
-            SvCustomMsg,
-            SvCustomMsg,
-            SvCustomMsg,
-            SvCustomMsg,
-            SvCustomMsg,
-            SvCustomMsg,
+            std::marker::PhantomData<(
+                Empty,
+                SvCustomMsg,
+                SvCustomMsg,
+                SvCustomMsg,
+                SvCustomMsg,
+                SvCustomMsg,
+                SvCustomMsg,
+                SvCustomMsg,
+                SvCustomMsg,
+                SvCustomMsg,
+            )>,
         >::borrowed(&contract, &querier_wrapper);
 
         let _: Result<SvCustomMsg, _> =
diff --git a/examples/interfaces/generic/src/lib.rs b/examples/interfaces/generic/src/lib.rs
index 4bf9b40..95aeebd 100644
--- a/examples/interfaces/generic/src/lib.rs
+++ b/examples/interfaces/generic/src/lib.rs
@@ -100,18 +100,20 @@ mod tests {
         let deps = mock_dependencies();
         let querier_wrapper: QuerierWrapper = QuerierWrapper::new(&deps.querier);
 
-        let querier = super::sv::BoundQuerier::<
+        let querier = sylvia::types::BoundQuerier::<
             Empty,
-            SvCustomMsg,
-            SvCustomMsg,
-            SvCustomMsg,
-            SvCustomMsg,
-            SvCustomMsg,
-            SvCustomMsg,
-            SvCustomMsg,
-            SvCustomMsg,
-            SvCustomMsg,
-            SvCustomMsg,
+            std::marker::PhantomData<(
+                SvCustomMsg,
+                SvCustomMsg,
+                SvCustomMsg,
+                SvCustomMsg,
+                SvCustomMsg,
+                SvCustomMsg,
+                SvCustomMsg,
+                SvCustomMsg,
+                SvCustomMsg,
+                SvCustomMsg,
+            )>,
         >::borrowed(&contract, &querier_wrapper);
         let _: Result<SvCustomMsg, _> =
             super::sv::Querier::generic_query_one(&querier, SvCustomMsg {}, SvCustomMsg {});
diff --git a/sylvia-derive/src/associated_types.rs b/sylvia-derive/src/associated_types.rs
index 1aff92a..a95a586 100644
--- a/sylvia-derive/src/associated_types.rs
+++ b/sylvia-derive/src/associated_types.rs
@@ -69,12 +69,6 @@ impl<'a> AssociatedTypes<'a> {
         self.filtered().map(|associated| &associated.ident)
     }
 
-    pub fn emit_types_definition(&self) -> Vec<TokenStream> {
-        self.as_names()
-            .map(|name| quote! { type #name = #name; })
-            .collect()
-    }
-
     pub fn emit_contract_predicate(&self, trait_name: &Ident) -> TokenStream {
         let predicate = quote! { ContractT: #trait_name };
         if self.0.is_empty() {
@@ -120,12 +114,6 @@ impl<'a> ImplAssociatedTypes<'a> {
         Self(associated_types)
     }
 
-    pub fn as_names(&self) -> Vec<&Ident> {
-        self.filtered()
-            .map(|associated| &associated.ident)
-            .collect()
-    }
-
     pub fn as_types(&self) -> Vec<&Type> {
         self.filtered().map(|associated| &associated.ty).collect()
     }
diff --git a/sylvia-derive/src/input.rs b/sylvia-derive/src/input.rs
index d6c69b6..dbb74d0 100644
--- a/sylvia-derive/src/input.rs
+++ b/sylvia-derive/src/input.rs
@@ -3,7 +3,7 @@ use proc_macro_error::emit_error;
 use quote::quote;
 use syn::{GenericParam, Ident, ItemImpl, ItemTrait, TraitItem};
 
-use crate::associated_types::{AssociatedTypes, ImplAssociatedTypes, ItemType};
+use crate::associated_types::{AssociatedTypes, ItemType};
 use crate::interfaces::Interfaces;
 use crate::message::{
     ContractApi, ContractEnumMessage, EnumMessage, GlueMessage, InterfaceApi, MsgVariants,
@@ -14,8 +14,7 @@ use crate::parser::attributes::msg::MsgType;
 use crate::parser::{
     ContractArgs, ContractErrorAttr, Custom, OverrideEntryPoint, ParsedSylviaAttributes,
 };
-use crate::querier::{ContractQuerier, ImplQuerier, TraitQuerier};
-use crate::remote::{ContractRemote, InterfaceRemote};
+use crate::querier::{ContractQuerier, TraitQuerier};
 use crate::variant_descs::AsVariantDescs;
 
 /// Preprocessed `interface` macro input
@@ -65,12 +64,12 @@ impl<'a> TraitInput<'a> {
             custom,
         } = self;
         let messages = self.emit_messages();
-        let remote = InterfaceRemote::new(associated_types).emit();
         let associated_names: Vec<_> = associated_types.as_names().collect();
 
         let query_variants =
             MsgVariants::new(item.as_variants(), MsgType::Query, &associated_names, &None);
-        let querier = TraitQuerier::new(&query_variants, associated_types).emit_trait_querier();
+        let querier =
+            TraitQuerier::new(&query_variants, associated_types, &item.ident).emit_trait_querier();
 
         let interface_messages = InterfaceApi::new(item, associated_types, custom).emit();
 
@@ -79,8 +78,6 @@ impl<'a> TraitInput<'a> {
                 use super::*;
                 #messages
 
-                #remote
-
                 #querier
 
                 #interface_messages
@@ -150,33 +147,16 @@ impl<'a> ImplTraitInput<'a> {
 
     pub fn process(&self) -> TokenStream {
         let multitest_helpers = self.emit_multitest_helpers();
-        let querier = self.emit_querier_for_bound_impl();
 
         quote! {
             pub mod sv {
                 use super::*;
 
                 #multitest_helpers
-
-                #querier
             }
         }
     }
 
-    fn emit_querier_for_bound_impl(&self) -> TokenStream {
-        let variants_args =
-            MsgVariants::<GenericParam>::new(self.item.as_variants(), MsgType::Query, &[], &None);
-        let associated_types = ImplAssociatedTypes::new(self.item);
-        ImplQuerier::new(
-            self.item,
-            &variants_args,
-            &associated_types,
-            &self.interfaces,
-            &self.attributes.module,
-        )
-        .emit()
-    }
-
     fn emit_multitest_helpers(&self) -> TokenStream {
         if !cfg!(feature = "mt") {
             return quote! {};
@@ -230,9 +210,8 @@ impl<'a> ImplInput<'a> {
         } = self;
         let multitest_helpers = self.emit_multitest_helpers();
 
-        let querier = ContractQuerier::new(item, interfaces).emit();
+        let querier = ContractQuerier::new(item).emit();
         let messages = self.emit_messages();
-        let remote = ContractRemote::new(item, interfaces).emit();
         let contract_api = ContractApi::new(item, generics, custom, interfaces).emit();
 
         quote! {
@@ -243,8 +222,6 @@ impl<'a> ImplInput<'a> {
 
                 #multitest_helpers
 
-                #remote
-
                 #querier
 
                 #contract_api
diff --git a/sylvia-derive/src/interfaces.rs b/sylvia-derive/src/interfaces.rs
index cbed77c..f4e87cb 100644
--- a/sylvia-derive/src/interfaces.rs
+++ b/sylvia-derive/src/interfaces.rs
@@ -2,7 +2,7 @@ use proc_macro2::{Ident, TokenStream};
 use proc_macro_error::emit_error;
 use quote::quote;
 use syn::spanned::Spanned;
-use syn::{GenericArgument, GenericParam, ItemImpl};
+use syn::{GenericArgument, ItemImpl};
 
 use crate::crate_module;
 use crate::parser::attributes::msg::MsgType;
@@ -19,24 +19,6 @@ impl Interfaces {
         Self { interfaces }
     }
 
-    pub fn emit_querier_from_impl(&self, contract_generics: &[&GenericParam]) -> Vec<TokenStream> {
-        let sylvia = crate_module();
-
-        self.interfaces
-            .iter()
-            .map(|interface| {
-                let ContractMessageAttr { module, generics ,..} = interface;
-                quote! {
-                    impl<'a, C: #sylvia ::cw_std::CustomQuery, #(#contract_generics,)* > From<&'a BoundQuerier<'a, C, #(#contract_generics,)* >> for #module ::sv::BoundQuerier<'a, C, #generics > {
-                        fn from(querier: &'a BoundQuerier<'a, C, #(#contract_generics,)* >) -> Self {
-                            Self::borrowed(querier.contract(),  querier.querier())
-                        }
-                    }
-                }
-            })
-            .collect()
-    }
-
     pub fn emit_glue_message_variants(&self, msg_ty: &MsgType) -> Vec<TokenStream> {
         let sylvia = crate_module();
 
@@ -126,22 +108,6 @@ impl Interfaces {
             .collect()
     }
 
-    pub fn emit_remote_from_impl(&self, contract_generics: &[&GenericParam]) -> Vec<TokenStream> {
-        self.interfaces.iter().map(|interface| {
-            let ContractMessageAttr {
-                module, generics, ..
-            } = interface;
-
-            quote! {
-                impl<'a, #(#contract_generics,)* > From<&'a Remote<'a, #(#contract_generics,)* >> for #module ::sv::Remote<'a, #generics > {
-                    fn from(remote: &'a Remote<'a, #(#contract_generics,)* >) -> Self {
-                        #module ::sv::Remote::borrowed(remote.as_ref())
-                    }
-                }
-            }
-        }).collect()
-    }
-
     pub fn emit_dispatch_arms(&self, msg_ty: &MsgType) -> Vec<TokenStream> {
         let sylvia = crate_module();
         let contract_enum_name = msg_ty.emit_msg_wrapper_name();
diff --git a/sylvia-derive/src/lib.rs b/sylvia-derive/src/lib.rs
index faa2ab3..e6c70ec 100644
--- a/sylvia-derive/src/lib.rs
+++ b/sylvia-derive/src/lib.rs
@@ -15,7 +15,6 @@ mod message_type;
 mod multitest;
 mod parser;
 mod querier;
-mod remote;
 mod strip_generics;
 mod strip_input;
 mod strip_self_path;
diff --git a/sylvia-derive/src/message.rs b/sylvia-derive/src/message.rs
index 2209037..8738111 100644
--- a/sylvia-derive/src/message.rs
+++ b/sylvia-derive/src/message.rs
@@ -542,7 +542,7 @@ impl<'a> MsgVariant<'a> {
         }
     }
 
-    pub fn emit_trait_querier_impl(&self, associated_name: &[&Ident]) -> TokenStream {
+    pub fn emit_trait_querier_impl(&self, associated_name: &[TokenStream]) -> TokenStream {
         let sylvia = crate_module();
         let Self {
             name,
@@ -551,7 +551,7 @@ impl<'a> MsgVariant<'a> {
             ..
         } = self;
 
-        let parameters = fields.iter().map(MsgField::emit_method_field);
+        let parameters = fields.iter().map(MsgField::emit_method_field_assoc_type);
         let fields_names = fields.iter().map(MsgField::name);
         let variant_name = Ident::new(&name.to_string().to_case(Case::Snake), name.span());
         let bracketed_generics = emit_bracketed_generics(associated_name);
@@ -1117,6 +1117,15 @@ impl<'a> MsgField<'a> {
         }
     }
 
+    /// Emits method field
+    pub fn emit_method_field_assoc_type(&self) -> TokenStream {
+        let Self { name, ty, .. } = self;
+
+        quote! {
+            #name: #ty
+        }
+    }
+
     pub fn emit_method_field_folded<FoldT>(&self, fold: &mut FoldT) -> TokenStream
     where
         FoldT: Fold,
@@ -1475,8 +1484,8 @@ impl<'a> ContractApi<'a> {
                 type Sudo = SudoMsg #sudo_bracketed_generics;
                 type Instantiate = InstantiateMsg #instantiate_bracketed_generics;
                 #migrate_type
-                type Remote<'remote> = Remote<'remote, #(#generics,)* >;
-                type Querier<'querier> = BoundQuerier<'querier, #custom_query, #(#generics,)* >;
+                type Remote<'remote> = #sylvia ::types::Remote<'remote, Self >;
+                type Querier<'querier> = #sylvia ::types::BoundQuerier<'querier, #custom_query, Self >;
             }
         }
     }
@@ -1560,7 +1569,7 @@ impl<'a> InterfaceApi<'a> {
                 type Exec = ExecMsg #exec_bracketed_generics;
                 type Query = QueryMsg #query_bracketed_generics;
                 type Sudo = SudoMsg #sudo_bracketed_generics;
-                type Querier<'querier> = BoundQuerier<'querier, #custom_query, #(#generics,)* >;
+                type Querier<'querier, Contract> = #sylvia ::types::BoundQuerier<'querier, #custom_query, Contract >;
             }
         }
     }
diff --git a/sylvia-derive/src/querier.rs b/sylvia-derive/src/querier.rs
index 4d9580a..4ab30b0 100644
--- a/sylvia-derive/src/querier.rs
+++ b/sylvia-derive/src/querier.rs
@@ -1,11 +1,10 @@
 use proc_macro2::TokenStream;
 use quote::{quote, ToTokens};
-use syn::{GenericParam, ItemImpl, Path};
+use syn::{GenericParam, Ident, ItemImpl};
 
-use crate::associated_types::{AssociatedTypes, EmitAssociated, ImplAssociatedTypes, ItemType};
+use crate::associated_types::{AssociatedTypes, EmitAssociated, ItemType};
 use crate::check_generics::GetPath;
 use crate::crate_module;
-use crate::interfaces::Interfaces;
 use crate::message::MsgVariants;
 use crate::parser::attributes::msg::MsgType;
 use crate::variant_descs::AsVariantDescs;
@@ -13,6 +12,7 @@ use crate::variant_descs::AsVariantDescs;
 pub struct TraitQuerier<'a, Generic> {
     variants: &'a MsgVariants<'a, Generic>,
     associated_types: &'a AssociatedTypes<'a>,
+    interface_name: &'a Ident,
 }
 
 impl<'a, Generic> TraitQuerier<'a, Generic>
@@ -22,10 +22,12 @@ where
     pub fn new(
         variants: &'a MsgVariants<'a, Generic>,
         associated_types: &'a AssociatedTypes,
+        interface_name: &'a Ident,
     ) -> Self {
         Self {
             variants,
             associated_types,
+            interface_name,
         }
     }
 
@@ -34,17 +36,24 @@ where
         let Self {
             variants,
             associated_types,
-            ..
+            interface_name,
         } = self;
 
         let generics: Vec<_> = associated_types
             .without_special()
             .map(ItemType::as_name)
             .collect();
-        let methods_impl = variants
+
+        let assoc_types: Vec<_> = associated_types
+            .without_special()
+            .map(ItemType::as_name)
+            .map(|assoc| quote! {Self:: #assoc})
+            .collect();
+        let methods_trait_impl = variants
             .variants()
             .iter()
-            .map(|variant| variant.emit_trait_querier_impl(&generics));
+            .map(|variant| variant.emit_trait_querier_impl(&assoc_types))
+            .collect::<Vec<_>>();
 
         let methods_declaration = variants
             .variants()
@@ -52,115 +61,25 @@ where
             .map(|variant| variant.emit_querier_declaration(&generics));
 
         let types_declaration = associated_types.filtered();
-        let types_definition = associated_types.emit_types_definition();
         let where_clause = associated_types.as_where_clause();
 
         quote! {
-            pub struct BoundQuerier<'a, C: #sylvia ::cw_std::CustomQuery, #(#generics,)* > {
-                contract: &'a #sylvia ::cw_std::Addr,
-                querier: &'a #sylvia ::cw_std::QuerierWrapper<'a, C>,
-                _phantom: std::marker::PhantomData<( #(#generics,)* )>,
-            }
-
-            impl<'a, C: #sylvia ::cw_std::CustomQuery, #(#generics,)* > BoundQuerier<'a, C, #(#generics,)* > {
-                pub fn querier(&self) -> &'a #sylvia ::cw_std::QuerierWrapper<'a, C> {
-                    self.querier
-                }
-
-                pub fn contract(&self) -> &'a #sylvia ::cw_std::Addr {
-                    self.contract
-                }
-
-                pub fn borrowed(contract: &'a #sylvia ::cw_std::Addr, querier: &'a #sylvia ::cw_std::QuerierWrapper<'a, C>) -> Self {
-                    Self { contract, querier, _phantom: std::marker::PhantomData }
-                }
-            }
-
-            impl <'a, C: #sylvia ::cw_std::CustomQuery, #(#generics,)* > Querier for BoundQuerier<'a, C, #(#generics,)* > #where_clause {
-                #(#types_definition)*
-
-                #(#methods_impl)*
-            }
-
             pub trait Querier {
                 #(#types_declaration)*
 
                 #(#methods_declaration)*
             }
-        }
-    }
-}
-
-pub struct ImplQuerier<'a, Generic> {
-    source: &'a ItemImpl,
-    variants: &'a MsgVariants<'a, Generic>,
-    associated_types: &'a ImplAssociatedTypes<'a>,
-    interfaces: &'a Interfaces,
-    contract_module: &'a Path,
-}
-
-impl<'a, Generic> ImplQuerier<'a, Generic>
-where
-    Generic: GetPath + PartialEq + ToTokens,
-{
-    pub fn new(
-        source: &'a ItemImpl,
-        variants: &'a MsgVariants<'a, Generic>,
-        associated_types: &'a ImplAssociatedTypes,
-        interfaces: &'a Interfaces,
-        contract_module: &'a Path,
-    ) -> Self {
-        Self {
-            source,
-            variants,
-            associated_types,
-            interfaces,
-            contract_module,
-        }
-    }
-
-    pub fn emit(&self) -> TokenStream {
-        let sylvia = crate_module();
-        let Self {
-            source,
-            variants,
-            associated_types,
-            interfaces,
-            contract_module,
-        } = self;
-
-        let trait_module = interfaces
-            .get_only_interface()
-            .map(|interface| &interface.module);
-        let accessor = MsgType::Query.as_accessor_name();
-
-        let generic_params = &source.generics.params;
-        let where_clause = &source.generics.where_clause;
-        let associated_generics = associated_types.as_types();
-        let associated_names = associated_types.as_names();
-        let bracketed_generics = if !associated_generics.is_empty() {
-            quote! { ::< #(#associated_generics,)* > }
-        } else {
-            quote! {}
-        };
-        let api_path = quote! { < #trait_module ::sv::Api #bracketed_generics as #sylvia ::types::InterfaceApi>:: #accessor };
-
-        let methods_impl = variants
-            .variants()
-            .iter()
-            .map(|variant| variant.emit_querier_impl(&api_path, &associated_names));
 
-        let querier = trait_module
-            .map(|module| quote! { #module ::sv::Querier })
-            .unwrap_or_else(|| quote! { sv::Querier });
+            impl <'a, C: #sylvia ::cw_std::CustomQuery, #(#generics,)*> Querier for #sylvia ::types::BoundQuerier<'a, C, std::marker::PhantomData< (#(#generics,)*) > > #where_clause {
+                #(type #generics = #generics;)*
 
-        let types_definition = associated_types.as_item_types();
+                #(#methods_trait_impl)*
+            }
 
-        quote! {
-            impl <'a, C: #sylvia ::cw_std::CustomQuery, #generic_params > #querier for #contract_module ::sv::BoundQuerier<'a, C, #generic_params > #where_clause {
-                #(#types_definition)*
+            impl <'a, C: #sylvia ::cw_std::CustomQuery, Contract: #interface_name> Querier for #sylvia ::types::BoundQuerier<'a, C, Contract> {
+                #(type #generics = <Contract as #interface_name > :: #generics;)*
 
-                #(#methods_impl)*
+                #(#methods_trait_impl)*
             }
         }
     }
@@ -169,25 +88,18 @@ where
 pub struct ContractQuerier<'a> {
     source: &'a ItemImpl,
     variants: MsgVariants<'a, GenericParam>,
-    interfaces: &'a Interfaces,
 }
 
 impl<'a> ContractQuerier<'a> {
-    pub fn new(source: &'a ItemImpl, interfaces: &'a Interfaces) -> Self {
+    pub fn new(source: &'a ItemImpl) -> Self {
         let variants = MsgVariants::new(source.as_variants(), MsgType::Query, &[], &None);
-        Self {
-            source,
-            variants,
-            interfaces,
-        }
+        Self { source, variants }
     }
 
     pub fn emit(&self) -> TokenStream {
         let sylvia = crate_module();
         let Self {
-            source,
-            variants,
-            interfaces,
+            source, variants, ..
         } = self;
 
         let where_clause = &source.generics.where_clause;
@@ -215,42 +127,21 @@ impl<'a> ContractQuerier<'a> {
             .as_ref()
             .map(EmitAssociated::emit_implementation)
             .unwrap_or(vec![]);
-        let from_implementations = interfaces.emit_querier_from_impl(&generics);
 
-        quote! {
-            pub struct BoundQuerier<'a, C: #sylvia ::cw_std::CustomQuery, #(#generics,)* > {
-                contract: &'a #sylvia ::cw_std::Addr,
-                querier: &'a #sylvia ::cw_std::QuerierWrapper<'a, C>,
-                _phantom: std::marker::PhantomData<( #(#generics,)* )>,
-            }
+        let contract_name = *source.self_ty.clone();
 
-            impl<'a, C: #sylvia ::cw_std::CustomQuery, #(#generics,)* > BoundQuerier<'a, C, #(#generics,)* > {
-                pub fn querier(&self) -> &'a #sylvia ::cw_std::QuerierWrapper<'a, C> {
-                    self.querier
-                }
-
-                pub fn contract(&self) -> &'a #sylvia ::cw_std::Addr {
-                    self.contract
-                }
+        quote! {
+            pub trait Querier {
+                #(#types_declaration)*
 
-                pub fn borrowed(contract: &'a #sylvia ::cw_std::Addr, querier: &'a #sylvia ::cw_std::QuerierWrapper<'a, C>) -> Self {
-                    Self {contract, querier, _phantom: std::marker::PhantomData}
-                }
+                #(#methods_declaration)*
             }
 
-            impl <'a, C: #sylvia ::cw_std::CustomQuery, #(#generics,)* > Querier for BoundQuerier<'a, C, #(#generics,)* > #where_clause {
+            impl <'a, C: #sylvia ::cw_std::CustomQuery, #(#generics,)*> Querier for #sylvia ::types::BoundQuerier<'a, C, #contract_name > #where_clause {
                 #(#types_implementation)*
 
                 #(#methods_impl)*
             }
-
-            pub trait Querier {
-                #(#types_declaration)*
-
-                #(#methods_declaration)*
-            }
-
-            #(#from_implementations)*
         }
     }
 }
diff --git a/sylvia-derive/src/remote.rs b/sylvia-derive/src/remote.rs
deleted file mode 100644
index f425f23..0000000
--- a/sylvia-derive/src/remote.rs
+++ /dev/null
@@ -1,93 +0,0 @@
-use proc_macro2::TokenStream;
-use quote::{quote, ToTokens};
-use syn::{GenericParam, ItemImpl};
-
-use crate::associated_types::AssociatedTypes;
-use crate::crate_module;
-use crate::interfaces::Interfaces;
-
-pub struct InterfaceRemote<'a> {
-    associated_types: &'a AssociatedTypes<'a>,
-}
-
-pub struct ContractRemote<'a> {
-    interfaces: &'a Interfaces,
-    contract_generics: Vec<&'a GenericParam>,
-}
-
-impl<'a> InterfaceRemote<'a> {
-    pub fn new(associated_types: &'a AssociatedTypes<'a>) -> Self {
-        Self { associated_types }
-    }
-
-    pub fn emit(&self) -> TokenStream {
-        let generics: Vec<_> = self.associated_types.as_names().collect();
-
-        emit(&generics)
-    }
-}
-
-impl<'a> ContractRemote<'a> {
-    pub fn new(source: &'a ItemImpl, interfaces: &'a Interfaces) -> Self {
-        let contract_generics = source.generics.params.iter().collect();
-        Self {
-            contract_generics,
-            interfaces,
-        }
-    }
-
-    pub fn emit(&self) -> TokenStream {
-        let from_impls = self
-            .interfaces
-            .emit_remote_from_impl(&self.contract_generics);
-        let querier = emit(&self.contract_generics);
-
-        quote! {
-            #querier
-            #(#from_impls)*
-        }
-    }
-}
-
-fn emit(generics: &[impl ToTokens]) -> TokenStream {
-    let sylvia = crate_module();
-
-    quote! {
-        #[derive(#sylvia ::serde::Serialize, #sylvia ::serde::Deserialize, Clone, Debug, PartialEq, #sylvia ::schemars::JsonSchema)]
-        pub struct Remote<'a, #(#generics,)* > {
-            addr: std::borrow::Cow<'a, #sylvia ::cw_std::Addr>,
-            #[serde(skip)]
-            _phantom: std::marker::PhantomData<( #(#generics,)* )>,
-        }
-
-        impl<'a, #(#generics,)* > Remote<'a, #(#generics,)* > {
-            pub fn new(addr: #sylvia ::cw_std::Addr) -> Self {
-                Self {
-                    addr: std::borrow::Cow::Owned(addr),
-                    _phantom: std::marker::PhantomData
-                }
-            }
-
-            pub fn borrowed(addr: &'a #sylvia ::cw_std::Addr) -> Self {
-                Self {
-                    addr: std::borrow::Cow::Borrowed(addr),
-                    _phantom: std::marker::PhantomData}
-                }
-
-            pub fn querier<C: #sylvia ::cw_std::CustomQuery>(&'a self, querier: &'a #sylvia ::cw_std::QuerierWrapper<'a, C>) -> BoundQuerier<'a, C, #(#generics,)* > {
-                BoundQuerier {
-                    contract: &self.addr,
-                    querier,
-                    _phantom: std::marker::PhantomData,
-                }
-            }
-        }
-
-        impl<'a, #(#generics,)* > AsRef<#sylvia ::cw_std::Addr> for Remote<'a, #(#generics,)* > {
-            fn as_ref(&self) -> &#sylvia ::cw_std::Addr {
-                &self.addr
-            }
-        }
-
-    }
-}
diff --git a/sylvia/src/types.rs b/sylvia/src/types.rs
index 3507102..c940756 100644
--- a/sylvia/src/types.rs
+++ b/sylvia/src/types.rs
@@ -2,6 +2,82 @@ use cosmwasm_schema::cw_serde;
 use cosmwasm_std::{Deps, DepsMut, Empty, Env, MessageInfo};
 use schemars::JsonSchema;
 use serde::de::DeserializeOwned;
+use serde::{Deserialize, Serialize};
+
+pub struct BoundQuerier<'a, C: cosmwasm_std::CustomQuery, Contract> {
+    contract: &'a cosmwasm_std::Addr,
+    querier: &'a cosmwasm_std::QuerierWrapper<'a, C>,
+    _phantom: std::marker::PhantomData<Contract>,
+}
+
+impl<'a, C: cosmwasm_std::CustomQuery, Contract> BoundQuerier<'a, C, Contract> {
+    pub fn querier(&self) -> &'a cosmwasm_std::QuerierWrapper<'a, C> {
+        self.querier
+    }
+
+    pub fn contract(&self) -> &'a cosmwasm_std::Addr {
+        self.contract
+    }
+
+    pub fn borrowed(
+        contract: &'a cosmwasm_std::Addr,
+        querier: &'a cosmwasm_std::QuerierWrapper<'a, C>,
+    ) -> Self {
+        Self {
+            contract,
+            querier,
+            _phantom: std::marker::PhantomData,
+        }
+    }
+}
+
+impl<'a, C: cosmwasm_std::CustomQuery, Contract> From<&'a BoundQuerier<'a, C, Contract>>
+    for BoundQuerier<'a, C, Contract>
+{
+    fn from(input: &'a BoundQuerier<'a, C, Contract>) -> Self {
+        BoundQuerier::borrowed(input.contract, input.querier)
+    }
+}
+
+#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
+pub struct Remote<'a, Contract> {
+    addr: std::borrow::Cow<'a, cosmwasm_std::Addr>,
+    #[serde(skip)]
+    _phantom: std::marker::PhantomData<Contract>,
+}
+
+impl<'a, Contract> Remote<'a, Contract> {
+    pub fn new(addr: cosmwasm_std::Addr) -> Self {
+        Self {
+            addr: std::borrow::Cow::Owned(addr),
+            _phantom: std::marker::PhantomData,
+        }
+    }
+
+    pub fn borrowed(addr: &'a cosmwasm_std::Addr) -> Self {
+        Self {
+            addr: std::borrow::Cow::Borrowed(addr),
+            _phantom: std::marker::PhantomData,
+        }
+    }
+
+    pub fn querier<C: cosmwasm_std::CustomQuery>(
+        &'a self,
+        querier: &'a cosmwasm_std::QuerierWrapper<'a, C>,
+    ) -> BoundQuerier<'a, C, Contract> {
+        BoundQuerier {
+            contract: &self.addr,
+            querier,
+            _phantom: std::marker::PhantomData,
+        }
+    }
+}
+
+impl<'a, Contract> AsRef<cosmwasm_std::Addr> for Remote<'a, Contract> {
+    fn as_ref(&self) -> &cosmwasm_std::Addr {
+        &self.addr
+    }
+}
 
 /// Represantation of `reply` context received in entry point as
 /// (DepsMut, Env) tuple.
@@ -139,7 +215,7 @@ pub trait InterfaceApi {
     type Exec;
     type Query;
     type Sudo;
-    type Querier<'querier>;
+    type Querier<'querier, Contract>;
 }
 
 /// Api trait for easier access to generated types and messages.


Test patch:
diff --git a/sylvia/tests/api.rs b/sylvia/tests/api.rs
index 4f7da40..a506c55 100644
--- a/sylvia/tests/api.rs
+++ b/sylvia/tests/api.rs
@@ -105,12 +105,7 @@ mod tests {
             query
         );
 
-        let _: crate::sv::Remote<'_,
-            SvCustomMsg,
-            SvCustomMsg,
-            SvCustomMsg,
-            SvCustomMsg,
-            SvCustomMsg,> = <SomeContract<
+        let _: sylvia::types::Remote<'_, _> = <SomeContract<
             SvCustomMsg,
             SvCustomMsg,
             SvCustomMsg,
@@ -120,12 +115,7 @@ mod tests {
 
         let deps = mock_dependencies();
         let querier_wrapper: QuerierWrapper = QuerierWrapper::new(&deps.querier);
-        let _: crate::sv::BoundQuerier<'_, cosmwasm_std::Empty,
-            SvCustomMsg,
-            SvCustomMsg,
-            SvCustomMsg,
-            SvCustomMsg,
-            SvCustomMsg,> = <SomeContract<
+        let _: sylvia::types::BoundQuerier<'_, cosmwasm_std::Empty, _> = <SomeContract<
             SvCustomMsg,
             SvCustomMsg,
             SvCustomMsg,
diff --git a/sylvia/tests/querier.rs b/sylvia/tests/querier.rs
index b2bdced..2e4d0d2 100644
--- a/sylvia/tests/querier.rs
+++ b/sylvia/tests/querier.rs
@@ -78,10 +78,12 @@ pub mod impl_counter {
         #[sv::msg(exec)]
         fn decrease_by_count(&self, ctx: ExecCtx) -> StdResult<Response> {
             let remote = self.remote.load(ctx.deps.storage)?;
-            let other_count =
-                crate::counter::sv::BoundQuerier::borrowed(remote.as_ref(), &ctx.deps.querier)
-                    .count()?
-                    .count;
+            let other_count = sylvia::types::BoundQuerier::<_, Self>::borrowed(
+                remote.as_ref(),
+                &ctx.deps.querier,
+            )
+            .count()?
+            .count;
             self.count.update(ctx.deps.storage, |count| {
                 let count = count.saturating_sub(other_count);
                 Ok::<_, StdError>(count)
@@ -94,7 +96,7 @@ pub mod impl_counter {
 
 pub struct CounterContract<'a> {
     pub count: Item<'static, u64>,
-    pub remote: Item<'static, sv::Remote<'a>>,
+    pub remote: Item<'static, sylvia::types::Remote<'a, CounterContract<'a>>>,
 }
 
 #[contract]
@@ -112,7 +114,7 @@ impl CounterContract<'_> {
     fn instantiate(&self, ctx: InstantiateCtx, remote_addr: Addr) -> StdResult<Response> {
         self.count.save(ctx.deps.storage, &0)?;
         self.remote
-            .save(ctx.deps.storage, &sv::Remote::new(remote_addr))?;
+            .save(ctx.deps.storage, &sylvia::types::Remote::new(remote_addr))?;
         Ok(Response::new())
     }
 }
@@ -133,16 +135,19 @@ mod tests {
         let remote_addr = Addr::unchecked("remote");
 
         // Remote generation
-        let remote = super::counter::sv::Remote::new(remote_addr.clone());
-        let _: super::counter::sv::BoundQuerier<_> = remote.querier(&querier_wrapper);
-        let remote = super::sv::Remote::new(remote_addr.clone());
-        let _: super::sv::BoundQuerier<_> = remote.querier(&querier_wrapper);
+        let remote = sylvia::types::Remote::<super::CounterContract<'_>>::new(remote_addr.clone());
+        let _: sylvia::types::BoundQuerier<_, _> = remote.querier(&querier_wrapper);
+        let remote = sylvia::types::Remote::<super::CounterContract<'_>>::new(remote_addr.clone());
+        let _: sylvia::types::BoundQuerier<_, _> = remote.querier(&querier_wrapper);
 
         // Querier generation
-        let _ = super::counter::sv::BoundQuerier::borrowed(&remote_addr, &querier_wrapper);
-        let querier = super::sv::BoundQuerier::borrowed(&remote_addr, &querier_wrapper);
+        let _ = sylvia::types::BoundQuerier::<_, super::CounterContract<'_>>::borrowed(
+            &remote_addr,
+            &querier_wrapper,
+        );
+        let querier = sylvia::types::BoundQuerier::borrowed(&remote_addr, &querier_wrapper);
 
-        let _ = super::counter::sv::BoundQuerier::from(&querier);
+        let _ = sylvia::types::BoundQuerier::<_, super::CounterContract<'_>>::from(&querier);
     }
 
     #[test]
diff --git a/sylvia/tests/remote.rs b/sylvia/tests/remote.rs
index 6021a28..025ecc2 100644
--- a/sylvia/tests/remote.rs
+++ b/sylvia/tests/remote.rs
@@ -36,30 +36,24 @@ impl SomeContract {
 // Making sure `Remote` can be stored in `#[cw_serde]` types
 #[cw_serde]
 #[allow(dead_code)]
-struct CustomStorage {
-    remote: crate::sv::Remote<'static>,
+struct CustomStorage<Contract> {
+    remote: sylvia::types::Remote<'static, Contract>,
 }
 
 #[cfg(test)]
 mod tests {
     use cosmwasm_std::Addr;
 
-    use crate::some_interface;
-
     #[test]
     fn remote_generation() {
         // interface
-        let _ = some_interface::sv::Remote::new(Addr::unchecked("some_interface"));
+        let _ = sylvia::types::Remote::<()>::new(Addr::unchecked("some_interface"));
         let addr = Addr::unchecked("some_interface");
-        let _ = some_interface::sv::Remote::borrowed(&addr);
+        let _ = sylvia::types::Remote::<()>::borrowed(&addr);
 
         // contract
-        let new_remote = crate::sv::Remote::new(Addr::unchecked("some_contract"));
         let addr = Addr::unchecked("some_contract");
-        let borrowed_remote = crate::sv::Remote::borrowed(&addr);
+        let borrowed_remote = sylvia::types::Remote::<()>::borrowed(&addr);
         assert_eq!(&Addr::unchecked("some_contract"), borrowed_remote.as_ref());
-
-        let _ = some_interface::sv::Remote::from(&borrowed_remote);
-        let _ = some_interface::sv::Remote::from(&new_remote);
     }
 }