Skip to content

Commit

Permalink
test: Duplicated queries in generic interface
Browse files Browse the repository at this point in the history
  • Loading branch information
jawoznia committed Dec 20, 2023
1 parent 9efc3d8 commit c245395
Show file tree
Hide file tree
Showing 8 changed files with 176 additions and 44 deletions.
2 changes: 1 addition & 1 deletion examples/contracts/generic_contract/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub struct GenericContract<
#[cfg_attr(not(feature = "library"), entry_points(generics<SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, sylvia::types::SvCustomMsg, String>))]
#[contract]
#[messages(cw1 as Cw1: custom(msg, query))]
#[messages(generic<SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg> as Generic: custom(msg, query))]
#[messages(generic<SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg> as Generic: custom(msg, query))]
#[messages(custom_and_generic<SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg,SvCustomMsg, sylvia::types::SvCustomMsg, SvCustomQuery> as CustomAndGeneric)]
#[sv::custom(msg=SvCustomMsg, query=SvCustomQuery)]
impl<InstantiateT, Exec1T, Exec2T, Exec3T, Query1T, Query2T, Query3T, MigrateT, FieldT>
Expand Down
36 changes: 32 additions & 4 deletions examples/contracts/generic_contract/src/generic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,23 @@ use serde::Deserialize;
use sylvia::contract;
use sylvia::types::{CustomMsg, ExecCtx, QueryCtx, SvCustomMsg};

type QueryAlias1 = SvCustomMsg;
type QueryAlias2 = SvCustomMsg;
type QueryAlias3 = SvCustomMsg;

#[contract(module = crate::contract)]
#[messages(generic as Generic)]
#[sv::custom(msg=SvCustomMsg, query=SvCustomQuery)]
impl<InstantiateT, Exec1T, Exec2T, Exec3T, Query1T, Query2T, Query3T, MigrateT, FieldT>
Generic<SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, sylvia::types::SvCustomMsg>
Generic<
SvCustomMsg,
SvCustomMsg,
SvCustomMsg,
QueryAlias1,
QueryAlias2,
QueryAlias3,
sylvia::types::SvCustomMsg,
>
for crate::contract::GenericContract<
InstantiateT,
Exec1T,
Expand Down Expand Up @@ -62,10 +74,21 @@ where
// F.e. if we this query would return `SvCustomMsg` and we would pass
// `sylvia::types::SvCustomMsg` to the `Generic` trait paths would not match.
#[msg(query)]
fn generic_query(
fn generic_query_one(
&self,
_ctx: QueryCtx,
_msg: SvCustomMsg,
_msg1: QueryAlias1,
_msg2: QueryAlias2,
) -> StdResult<sylvia::types::SvCustomMsg> {
Ok(SvCustomMsg {})
}

#[msg(query)]
fn generic_query_two(
&self,
_ctx: QueryCtx,
_msg1: QueryAlias2,
_msg2: QueryAlias3,
) -> StdResult<sylvia::types::SvCustomMsg> {
Ok(SvCustomMsg {})
}
Expand Down Expand Up @@ -118,6 +141,11 @@ mod tests {
)
.call(owner)
.unwrap();
contract.generic_query(SvCustomMsg).unwrap();
contract
.generic_query_one(SvCustomMsg, SvCustomMsg)
.unwrap();
contract
.generic_query_two(SvCustomMsg, SvCustomMsg)
.unwrap();
}
}
8 changes: 6 additions & 2 deletions examples/contracts/generic_iface_on_contract/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub struct NonGenericContract;

#[cfg_attr(not(feature = "library"), entry_points)]
#[contract]
#[messages(generic<SvCustomMsg, SvCustomMsg, SvCustomMsg, sylvia::types::SvCustomMsg, SvCustomMsg> as Generic: custom(msg, query))]
#[messages(generic<SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, sylvia::types::SvCustomMsg, SvCustomMsg> as Generic: custom(msg, query))]
#[messages(custom_and_generic<SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, sylvia::types::SvCustomMsg, SvCustomQuery> as CustomAndGeneric)]
#[messages(cw1 as Cw1: custom(msg, query))]
/// Required if interface returns generic `Response`
Expand Down Expand Up @@ -67,7 +67,11 @@ mod tests {
// Non-Custom generic Interface
contract
.generic_proxy()
.generic_query(SvCustomMsg {})
.generic_query_one(SvCustomMsg {}, SvCustomMsg {})
.unwrap();
contract
.generic_proxy()
.generic_query_two(SvCustomMsg {}, SvCustomMsg {})
.unwrap();
contract
.generic_proxy()
Expand Down
31 changes: 27 additions & 4 deletions examples/contracts/generic_iface_on_contract/src/generic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,23 @@ use generic::Generic;
use sylvia::contract;
use sylvia::types::{ExecCtx, QueryCtx, SvCustomMsg};

type QueryAlias1 = SvCustomMsg;
type QueryAlias2 = SvCustomMsg;
type QueryAlias3 = SvCustomMsg;

#[contract(module = crate::contract)]
#[messages(generic as Generic)]
#[sv::custom(msg = SvCustomMsg)]
impl Generic<SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, sylvia::types::SvCustomMsg>
for crate::contract::NonGenericContract
impl
Generic<
SvCustomMsg,
SvCustomMsg,
SvCustomMsg,
QueryAlias1,
QueryAlias2,
QueryAlias3,
sylvia::types::SvCustomMsg,
> for crate::contract::NonGenericContract
{
type Error = StdError;

Expand Down Expand Up @@ -36,10 +48,21 @@ impl Generic<SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, sylvia::types::
// 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(
fn generic_query_one(
&self,
_ctx: QueryCtx,
_msg1: QueryAlias1,
_msg2: QueryAlias2,
) -> StdResult<SvCustomMsg> {
Ok(SvCustomMsg {})
}

#[msg(query)]
fn generic_query_two(
&self,
_ctx: QueryCtx,
_msg: sylvia::types::SvCustomMsg,
_msg1: QueryAlias2,
_msg2: QueryAlias3,
) -> StdResult<SvCustomMsg> {
Ok(SvCustomMsg {})
}
Expand Down
2 changes: 1 addition & 1 deletion examples/contracts/generics_forwarded/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub struct GenericsForwardedContract<

// TODO: Add entry points call.
#[contract]
#[messages(generic<Exec1T, Exec2T, Exec3T, Query1T, SvCustomMsg> as Generic: custom(msg, query))]
#[messages(generic<Exec1T, Exec2T, Exec3T, Query1T, Query2T, Query3T, SvCustomMsg> as Generic: custom(msg, query))]
#[messages(cw1 as Cw1: custom(msg, query))]
#[messages(custom_and_generic<Exec1T, Exec2T, Exec3T, Query1T, Query2T, Query3T, SvCustomMsg, CustomMsgT, CustomQueryT> as CustomAndGeneric)]
#[sv::custom(msg=CustomMsgT, query=CustomQueryT)]
Expand Down
26 changes: 23 additions & 3 deletions examples/contracts/generics_forwarded/src/generic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ impl<
CustomMsgT,
CustomQueryT,
FieldT,
> Generic<Exec1T, Exec2T, Exec3T, Query1T, SvCustomMsg>
> Generic<Exec1T, Exec2T, Exec3T, Query1T, Query2T, Query3T, SvCustomMsg>
for crate::contract::GenericsForwardedContract<
InstantiateT,
Exec1T,
Expand Down Expand Up @@ -69,7 +69,22 @@ where
}

#[msg(query)]
fn generic_query(&self, _ctx: QueryCtx, _msg: Query1T) -> StdResult<SvCustomMsg> {
fn generic_query_one(
&self,
_ctx: QueryCtx,
_msg1: Query1T,
_msg2: Query2T,
) -> StdResult<SvCustomMsg> {
Ok(SvCustomMsg {})
}

#[msg(query)]
fn generic_query_two(
&self,
_ctx: QueryCtx,
_msg1: Query2T,
_msg2: Query3T,
) -> StdResult<SvCustomMsg> {
Ok(SvCustomMsg {})
}
}
Expand Down Expand Up @@ -124,6 +139,11 @@ mod tests {
)
.call(owner)
.unwrap();
contract.generic_query(SvCustomMsg).unwrap();
contract
.generic_query_one(SvCustomMsg, SvCustomMsg)
.unwrap();
contract
.generic_query_two(SvCustomMsg, SvCustomMsg)
.unwrap();
}
}
7 changes: 0 additions & 7 deletions examples/interfaces/custom-and-generic/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,6 @@ mod tests {

let querier = super::sv::BoundQuerier::borrowed(&contract, &querier_wrapper);

// TODO: Allow generic querier calls without fully qualified path.
// ISSUE: BoundQuerier is a non generic type. We try to use method from a generic trait
// Querier. Because of that generic values are unknown at the time we call these methods.
// This issue is present when we have multiple queries using different generic types and
// Rust compiler cannot deduce types of these generics while constructing `QueryMsg`.
// FIX: Solution might be to change the `BoundQuerier` to be generic over the same types as
// `Querier`. I think this should be possible with `BoundQuerier` exposed via `InterfaceApi`.
let _: Result<SvCustomMsg, _> =
super::sv::Querier::<_, _, _, SvCustomMsg>::custom_generic_query_one(
&querier,
Expand Down
108 changes: 86 additions & 22 deletions examples/interfaces/generic/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
use cosmwasm_std::{CosmosMsg, CustomMsg, Response, StdError};
use cosmwasm_std::{CosmosMsg, Response, StdError};

use serde::{de::DeserializeOwned, Deserialize};
use sylvia::types::{ExecCtx, QueryCtx};
use serde::Deserialize;
use sylvia::types::{CustomMsg, ExecCtx, QueryCtx};
use sylvia::{interface, schemars};

#[interface]
pub trait Generic<Exec1T, Exec2T, Exec3T, QueryT, RetT>
pub trait Generic<Exec1T, Exec2T, Exec3T, Query1T, Query2T, Query3T, RetT>
where
for<'msg_de> Exec1T: CustomMsg + Deserialize<'msg_de>,
Exec2T: sylvia::types::CustomMsg,
Exec3T: sylvia::types::CustomMsg,
QueryT: sylvia::types::CustomMsg,
RetT: CustomMsg + DeserializeOwned,
Exec2T: CustomMsg,
Exec3T: CustomMsg,
Query1T: CustomMsg,
Query2T: CustomMsg,
Query3T: CustomMsg,
RetT: CustomMsg,
{
type Error: From<StdError>;

Expand All @@ -32,22 +34,40 @@ where
) -> Result<Response, Self::Error>;

#[msg(query)]
fn generic_query(&self, ctx: QueryCtx, param: QueryT) -> Result<RetT, Self::Error>;
fn generic_query_one(
&self,
ctx: QueryCtx,
param1: Query1T,
param2: Query2T,
) -> Result<RetT, Self::Error>;

#[msg(query)]
fn generic_query_two(
&self,
ctx: QueryCtx,
param1: Query2T,
param2: Query3T,
) -> Result<RetT, Self::Error>;
}

#[cfg(test)]
mod tests {
use cosmwasm_std::{testing::mock_dependencies, Addr, CosmosMsg, Empty, QuerierWrapper};
use sylvia::types::{InterfaceApi, SvCustomMsg};

use crate::sv::Querier;

#[test]
fn construct_messages() {
let contract = Addr::unchecked("contract");

// Direct message construction
let _ = super::sv::QueryMsg::<_, Empty>::generic_query(SvCustomMsg {});
let _ = super::sv::QueryMsg::<_, _, Empty, SvCustomMsg>::generic_query_one(
SvCustomMsg {},
SvCustomMsg {},
);
let _ = super::sv::QueryMsg::<SvCustomMsg, _, Empty, _>::generic_query_two(
SvCustomMsg {},
SvCustomMsg {},
);
let _ = super::sv::ExecMsg::<_, _, SvCustomMsg>::generic_exec_one(
vec![CosmosMsg::Custom(SvCustomMsg {})],
vec![CosmosMsg::Custom(SvCustomMsg {})],
Expand All @@ -62,19 +82,63 @@ mod tests {
let querier_wrapper: QuerierWrapper = QuerierWrapper::new(&deps.querier);

let querier = super::sv::BoundQuerier::borrowed(&contract, &querier_wrapper);
let _: Result<SvCustomMsg, _> = super::sv::Querier::generic_query(&querier, SvCustomMsg {});
let _: Result<SvCustomMsg, _> = querier.generic_query(SvCustomMsg {});
let _: Result<SvCustomMsg, _> =
super::sv::Querier::<_, _, _, SvCustomMsg>::generic_query_one(
&querier,
SvCustomMsg {},
SvCustomMsg {},
);
let _: Result<SvCustomMsg, _> =
super::sv::Querier::<SvCustomMsg, _, _, _>::generic_query_two(
&querier,
SvCustomMsg {},
SvCustomMsg {},
);
// let _: Result<SvCustomMsg, _> = querier.generic_query_one(SvCustomMsg {}, SvCustomMsg {});
// let _: Result<SvCustomMsg, _> = querier.generic_query_two(SvCustomMsg {}, SvCustomMsg {});

// Construct messages with Interface extension
let _ = <super::sv::Api<SvCustomMsg, SvCustomMsg, SvCustomMsg, _, SvCustomMsg> as InterfaceApi>::Query::generic_query(
SvCustomMsg {},
let _ = <super::sv::Api<
SvCustomMsg,
SvCustomMsg,
SvCustomMsg,
_,
_,
SvCustomMsg,
SvCustomMsg,
> as InterfaceApi>::Query::generic_query_one(SvCustomMsg {}, SvCustomMsg {});
let _ = <super::sv::Api<
SvCustomMsg,
SvCustomMsg,
SvCustomMsg,
SvCustomMsg,
_,
_,
SvCustomMsg,
> as InterfaceApi>::Query::generic_query_two(SvCustomMsg {}, SvCustomMsg {});
let _ = <super::sv::Api<
_,
_,
SvCustomMsg,
SvCustomMsg,
SvCustomMsg,
SvCustomMsg,
cosmwasm_std::Empty,
> as InterfaceApi>::Exec::generic_exec_one(
vec![CosmosMsg::Custom(SvCustomMsg {})],
vec![CosmosMsg::Custom(SvCustomMsg {})],
);
let _=
<super::sv::Api<_, _, SvCustomMsg, SvCustomMsg, cosmwasm_std::Empty> as InterfaceApi>::Exec::generic_exec_one(vec![
CosmosMsg::Custom(SvCustomMsg{}),
],vec![
CosmosMsg::Custom(SvCustomMsg{}),
]
let _ = <super::sv::Api<
SvCustomMsg,
_,
_,
SvCustomMsg,
SvCustomMsg,
SvCustomMsg,
cosmwasm_std::Empty,
> as InterfaceApi>::Exec::generic_exec_two(
vec![CosmosMsg::Custom(SvCustomMsg {})],
vec![CosmosMsg::Custom(SvCustomMsg {})],
);
}
}

0 comments on commit c245395

Please sign in to comment.