Repository: CosmWasm/sylvia
Pull request #367 (2024-05-07 11:25:54)

fix: Allow storage of `Remote<dyn Interface>`

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/CosmWasm/sylvia/pull/367?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 85.25%. Comparing base [(`8cb52a2`)](https://app.codecov.io/gh/CosmWasm/sylvia/commit/8cb52a207239808c6fa9d9332bb83f212fdc4b5a?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm) to head [(`c65289b`)](https://app.codecov.io/gh/CosmWasm/sylvia/pull/367?dropdown=coverage&src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm).


<details><summary>Additional details and impacted files</summary>


```diff
@@             Coverage Diff             @@
##           cosmwasm_1     #367   +/-   ##
===========================================
  Coverage       85.25%   85.25%           
===========================================
  Files              37       37           
  Lines            2700     2700           
===========================================
  Hits             2302     2302           
  Misses            398      398           
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/CosmWasm/sylvia/pull/367?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm).


Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6864467..fb69144 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -127,3 +127,5 @@ jobs:
         uses:                   codecov/codecov-action@v2
         with:
           fail_ci_if_error:     true
+        env:
+          CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
diff --git a/examples/interfaces/custom-and-generic/src/lib.rs b/examples/interfaces/custom-and-generic/src/lib.rs
index e1f94df..f860b30 100644
--- a/examples/interfaces/custom-and-generic/src/lib.rs
+++ b/examples/interfaces/custom-and-generic/src/lib.rs
@@ -109,7 +109,7 @@ mod tests {
 
         let querier = sylvia::types::BoundQuerier::<
             _,
-            &dyn super::CustomAndGeneric<
+            dyn super::CustomAndGeneric<
                 RetT = SvCustomMsg,
                 Exec1T = SvCustomMsg,
                 Exec2T = SvCustomMsg,
diff --git a/examples/interfaces/generic/src/lib.rs b/examples/interfaces/generic/src/lib.rs
index 782818f..0624268 100644
--- a/examples/interfaces/generic/src/lib.rs
+++ b/examples/interfaces/generic/src/lib.rs
@@ -107,7 +107,7 @@ mod tests {
 
         let querier = sylvia::types::BoundQuerier::<
             Empty,
-            &dyn super::Generic<
+            dyn super::Generic<
                 Exec1T = SvCustomMsg,
                 Exec2T = SvCustomMsg,
                 Exec3T = SvCustomMsg,
diff --git a/sylvia-derive/src/querier.rs b/sylvia-derive/src/querier.rs
index 3e1f61d..788e949 100644
--- a/sylvia-derive/src/querier.rs
+++ b/sylvia-derive/src/querier.rs
@@ -72,7 +72,7 @@ where
                 #(#methods_declaration)*
             }
 
-            impl <'a, C: #sylvia ::cw_std::CustomQuery, #(#all_generics,)*> Querier for #sylvia ::types::BoundQuerier<'a, C, &dyn #interface_name <#( #all_generics = #all_generics,)*> > #where_clause {
+            impl <'a, C: #sylvia ::cw_std::CustomQuery, #(#all_generics,)*> Querier for #sylvia ::types::BoundQuerier<'a, C, dyn #interface_name <#( #all_generics = #all_generics,)*> > #where_clause {
                 #(type #generics = #generics;)*
 
                 #(#methods_trait_impl)*
diff --git a/sylvia/src/types.rs b/sylvia/src/types.rs
index 6e3315d..bab535c 100644
--- a/sylvia/src/types.rs
+++ b/sylvia/src/types.rs
@@ -1,15 +1,16 @@
 use cosmwasm_std::{Deps, DepsMut, Empty, Env, MessageInfo};
+use derivative::Derivative;
 use schemars::JsonSchema;
 use serde::de::DeserializeOwned;
 use serde::{Deserialize, Serialize};
 
-pub struct BoundQuerier<'a, C: cosmwasm_std::CustomQuery, Contract> {
+pub struct BoundQuerier<'a, C: cosmwasm_std::CustomQuery, Contract: ?Sized> {
     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> {
+impl<'a, C: cosmwasm_std::CustomQuery, Contract: ?Sized> BoundQuerier<'a, C, Contract> {
     pub fn querier(&self) -> &'a cosmwasm_std::QuerierWrapper<'a, C> {
         self.querier
     }
@@ -38,14 +39,42 @@ impl<'a, C: cosmwasm_std::CustomQuery, Contract> From<&'a BoundQuerier<'a, C, Co
     }
 }
 
-#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
-pub struct Remote<'a, Contract> {
+#[derive(Serialize, Deserialize, Derivative)]
+#[derivative(Clone, Debug, PartialEq)]
+pub struct Remote<'a, Contract: ?Sized> {
     addr: std::borrow::Cow<'a, cosmwasm_std::Addr>,
     #[serde(skip)]
+    #[derivative(Debug = "ignore")]
     _phantom: std::marker::PhantomData<Contract>,
 }
 
-impl<'a, Contract> Remote<'a, Contract> {
+// Custom `JsonSchema` implementation to remove bounds for `Contract`.
+impl<'a, Contract: ?Sized> schemars::JsonSchema for Remote<'a, Contract> {
+    fn schema_name() -> std::string::String {
+        "Remote".to_owned()
+    }
+    fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
+        {
+            let mut schema_object = schemars::schema::SchemaObject {
+                instance_type: Some(schemars::schema::InstanceType::Object.into()),
+                ..Default::default()
+            };
+            let object_validation = schema_object.object();
+            {
+                object_validation.properties.insert(
+                    "addr".to_owned(),
+                    gen.subschema_for::<std::borrow::Cow<'a, cosmwasm_std::Addr>>(),
+                );
+                if! <std::borrow::Cow<'a,cosmwasm_std::Addr>as schemars::JsonSchema> ::_schemars_private_is_option(){
+            object_validation.required.insert("addr".to_owned());
+          }
+            }
+            schemars::schema::Schema::Object(schema_object)
+        }
+    }
+}
+
+impl<'a, Contract: ?Sized> Remote<'a, Contract> {
     pub fn new(addr: cosmwasm_std::Addr) -> Self {
         Self {
             addr: std::borrow::Cow::Owned(addr),


Test patch:
diff --git a/sylvia/tests/remote.rs b/sylvia/tests/remote.rs
index 054d300..5910d46 100644
--- a/sylvia/tests/remote.rs
+++ b/sylvia/tests/remote.rs
@@ -1,5 +1,5 @@
 use cosmwasm_schema::cw_serde;
-use cosmwasm_std::{Response, StdResult};
+use cosmwasm_std::{Response, StdError, StdResult};
 use sylvia::contract;
 use sylvia::types::InstantiateCtx;
 
@@ -37,8 +37,10 @@ impl SomeContract {
 // Making sure `Remote` can be stored in `#[cw_serde]` types
 #[cw_serde]
 #[allow(dead_code)]
-struct CustomStorage<Contract> {
-    remote: sylvia::types::Remote<'static, Contract>,
+struct CustomStorage<'a, Contract> {
+    remote: sylvia::types::Remote<'a, Contract>,
+    interface_remote:
+        sylvia::types::Remote<'static, dyn some_interface::SomeInterface<Error = StdError>>,
 }
 
 #[cfg(test)]