Skip to content

Commit

Permalink
Merge pull request CosmWasm#652 from CosmWasm/controllers-custom-quer…
Browse files Browse the repository at this point in the history
…y-type

packages: support custom queries
  • Loading branch information
uint authored Feb 9, 2022
2 parents e299f59 + f4edd06 commit 49fceee
Show file tree
Hide file tree
Showing 12 changed files with 157 additions and 112 deletions.
24 changes: 15 additions & 9 deletions packages/controllers/src/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ use serde::{Deserialize, Serialize};
use std::fmt;
use thiserror::Error;

use cosmwasm_std::{attr, Addr, Deps, DepsMut, MessageInfo, Response, StdError, StdResult};
use cosmwasm_std::{
attr, Addr, CustomQuery, Deps, DepsMut, MessageInfo, Response, StdError, StdResult,
};
use cw_storage_plus::Item;

// TODO: should the return values end up in utils, so eg. cw4 can import them as well as this module?
Expand Down Expand Up @@ -32,17 +34,17 @@ impl<'a> Admin<'a> {
Admin(Item::new(namespace))
}

pub fn set(&self, deps: DepsMut, admin: Option<Addr>) -> StdResult<()> {
pub fn set<Q: CustomQuery>(&self, deps: DepsMut<Q>, admin: Option<Addr>) -> StdResult<()> {
self.0.save(deps.storage, &admin)
}

pub fn get(&self, deps: Deps) -> StdResult<Option<Addr>> {
pub fn get<Q: CustomQuery>(&self, deps: Deps<Q>) -> StdResult<Option<Addr>> {
self.0.load(deps.storage)
}

/// Returns Ok(true) if this is an admin, Ok(false) if not and an Error if
/// we hit an error with Api or Storage usage
pub fn is_admin(&self, deps: Deps, caller: &Addr) -> StdResult<bool> {
pub fn is_admin<Q: CustomQuery>(&self, deps: Deps<Q>, caller: &Addr) -> StdResult<bool> {
match self.0.load(deps.storage)? {
Some(owner) => Ok(caller == &owner),
None => Ok(false),
Expand All @@ -51,17 +53,21 @@ impl<'a> Admin<'a> {

/// Like is_admin but returns AdminError::NotAdmin if not admin.
/// Helper for a nice one-line auth check.
pub fn assert_admin(&self, deps: Deps, caller: &Addr) -> Result<(), AdminError> {
pub fn assert_admin<Q: CustomQuery>(
&self,
deps: Deps<Q>,
caller: &Addr,
) -> Result<(), AdminError> {
if !self.is_admin(deps, caller)? {
Err(AdminError::NotAdmin {})
} else {
Ok(())
}
}

pub fn execute_update_admin<C>(
pub fn execute_update_admin<C, Q: CustomQuery>(
&self,
deps: DepsMut,
deps: DepsMut<Q>,
info: MessageInfo,
new_admin: Option<Addr>,
) -> Result<Response<C>, AdminError>
Expand Down Expand Up @@ -160,14 +166,14 @@ mod tests {
let info = mock_info(imposter.as_ref(), &[]);
let new_admin = Some(friend.clone());
let err = control
.execute_update_admin::<Empty>(deps.as_mut(), info, new_admin.clone())
.execute_update_admin::<Empty, Empty>(deps.as_mut(), info, new_admin.clone())
.unwrap_err();
assert_eq!(AdminError::NotAdmin {}, err);

// owner can update
let info = mock_info(owner.as_ref(), &[]);
let res = control
.execute_update_admin::<Empty>(deps.as_mut(), info, new_admin)
.execute_update_admin::<Empty, Empty>(deps.as_mut(), info, new_admin)
.unwrap();
assert_eq!(0, res.messages.len());

Expand Down
8 changes: 6 additions & 2 deletions packages/controllers/src/claim.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use cosmwasm_std::{Addr, BlockInfo, Deps, StdResult, Storage, Uint128};
use cosmwasm_std::{Addr, BlockInfo, CustomQuery, Deps, StdResult, Storage, Uint128};
use cw_storage_plus::Map;
use cw_utils::Expiration;

Expand Down Expand Up @@ -86,7 +86,11 @@ impl<'a> Claims<'a> {
Ok(to_send)
}

pub fn query_claims(&self, deps: Deps, address: &Addr) -> StdResult<ClaimsResponse> {
pub fn query_claims<Q: CustomQuery>(
&self,
deps: Deps<Q>,
address: &Addr,
) -> StdResult<ClaimsResponse> {
let claims = self.0.may_load(deps.storage, address)?.unwrap_or_default();
Ok(ClaimsResponse { claims })
}
Expand Down
13 changes: 7 additions & 6 deletions packages/controllers/src/hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use std::fmt;
use thiserror::Error;

use cosmwasm_std::{
attr, Addr, Deps, DepsMut, MessageInfo, Response, StdError, StdResult, Storage, SubMsg,
attr, Addr, CustomQuery, Deps, DepsMut, MessageInfo, Response, StdError, StdResult, Storage,
SubMsg,
};
use cw_storage_plus::Item;

Expand Down Expand Up @@ -73,10 +74,10 @@ impl<'a> Hooks<'a> {
.collect()
}

pub fn execute_add_hook<C>(
pub fn execute_add_hook<C, Q: CustomQuery>(
&self,
admin: &Admin,
deps: DepsMut,
deps: DepsMut<Q>,
info: MessageInfo,
addr: Addr,
) -> Result<Response<C>, HookError>
Expand All @@ -94,10 +95,10 @@ impl<'a> Hooks<'a> {
Ok(Response::new().add_attributes(attributes))
}

pub fn execute_remove_hook<C>(
pub fn execute_remove_hook<C, Q: CustomQuery>(
&self,
admin: &Admin,
deps: DepsMut,
deps: DepsMut<Q>,
info: MessageInfo,
addr: Addr,
) -> Result<Response<C>, HookError>
Expand All @@ -115,7 +116,7 @@ impl<'a> Hooks<'a> {
Ok(Response::new().add_attributes(attributes))
}

pub fn query_hooks(&self, deps: Deps) -> StdResult<HooksResponse> {
pub fn query_hooks<Q: CustomQuery>(&self, deps: Deps<Q>) -> StdResult<HooksResponse> {
let hooks = self.0.may_load(deps.storage)?.unwrap_or_default();
let hooks = hooks.into_iter().map(String::from).collect();
Ok(HooksResponse { hooks })
Expand Down
52 changes: 34 additions & 18 deletions packages/cw20/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use cosmwasm_std::{
to_binary, Addr, CosmosMsg, Empty, Querier, QuerierWrapper, StdResult, Uint128, WasmMsg,
to_binary, Addr, CosmosMsg, CustomQuery, Querier, QuerierWrapper, StdResult, Uint128, WasmMsg,
WasmQuery,
};

Expand Down Expand Up @@ -34,11 +34,12 @@ impl Cw20Contract {
}

/// Get token balance for the given address
pub fn balance<Q: Querier, T: Into<String>>(
&self,
querier: &Q,
address: T,
) -> StdResult<Uint128> {
pub fn balance<Q, T, CQ>(&self, querier: &Q, address: T) -> StdResult<Uint128>
where
Q: Querier,
T: Into<String>,
CQ: CustomQuery,
{
let msg = Cw20QueryMsg::Balance {
address: address.into(),
};
Expand All @@ -47,29 +48,39 @@ impl Cw20Contract {
msg: to_binary(&msg)?,
}
.into();
let res: BalanceResponse = QuerierWrapper::<Empty>::new(querier).query(&query)?;
let res: BalanceResponse = QuerierWrapper::<CQ>::new(querier).query(&query)?;
Ok(res.balance)
}

/// Get metadata from the contract. This is a good check that the address
/// is a valid Cw20 contract.
pub fn meta<Q: Querier>(&self, querier: &Q) -> StdResult<TokenInfoResponse> {
pub fn meta<Q, CQ>(&self, querier: &Q) -> StdResult<TokenInfoResponse>
where
Q: Querier,
CQ: CustomQuery,
{
let msg = Cw20QueryMsg::TokenInfo {};
let query = WasmQuery::Smart {
contract_addr: self.addr().into(),
msg: to_binary(&msg)?,
}
.into();
QuerierWrapper::<Empty>::new(querier).query(&query)
QuerierWrapper::<CQ>::new(querier).query(&query)
}

/// Get allowance of spender to use owner's account
pub fn allowance<Q: Querier, T: Into<String>, U: Into<String>>(
pub fn allowance<Q, T, U, CQ>(
&self,
querier: &Q,
owner: T,
spender: U,
) -> StdResult<AllowanceResponse> {
) -> StdResult<AllowanceResponse>
where
Q: Querier,
T: Into<String>,
U: Into<String>,
CQ: CustomQuery,
{
let msg = Cw20QueryMsg::Allowance {
owner: owner.into(),
spender: spender.into(),
Expand All @@ -79,27 +90,32 @@ impl Cw20Contract {
msg: to_binary(&msg)?,
}
.into();
QuerierWrapper::<Empty>::new(querier).query(&query)
QuerierWrapper::<CQ>::new(querier).query(&query)
}

/// Find info on who can mint, and how much
pub fn minter<Q: Querier>(&self, querier: &Q) -> StdResult<Option<MinterResponse>> {
pub fn minter<Q, CQ>(&self, querier: &Q) -> StdResult<Option<MinterResponse>>
where
Q: Querier,
CQ: CustomQuery,
{
let msg = Cw20QueryMsg::Minter {};
let query = WasmQuery::Smart {
contract_addr: self.addr().into(),
msg: to_binary(&msg)?,
}
.into();
QuerierWrapper::<Empty>::new(querier).query(&query)
QuerierWrapper::<CQ>::new(querier).query(&query)
}

/// returns true if the contract supports the allowance extension
pub fn has_allowance<Q: Querier>(&self, querier: &Q) -> bool {
self.allowance(querier, self.addr(), self.addr()).is_ok()
pub fn has_allowance<Q: Querier, CQ: CustomQuery>(&self, querier: &Q) -> bool {
self.allowance::<_, _, _, CQ>(querier, self.addr(), self.addr())
.is_ok()
}

/// returns true if the contract supports the mintable extension
pub fn is_mintable<Q: Querier>(&self, querier: &Q) -> bool {
self.minter(querier).is_ok()
pub fn is_mintable<Q: Querier, CQ: CustomQuery>(&self, querier: &Q) -> bool {
self.minter::<_, CQ>(querier).is_ok()
}
}
7 changes: 4 additions & 3 deletions packages/cw4/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use cosmwasm_std::{
to_binary, Addr, CosmosMsg, Empty, QuerierWrapper, QueryRequest, StdResult, WasmMsg, WasmQuery,
to_binary, Addr, CosmosMsg, CustomQuery, QuerierWrapper, QueryRequest, StdResult, WasmMsg,
WasmQuery,
};

use crate::msg::Cw4ExecuteMsg;
Expand Down Expand Up @@ -54,7 +55,7 @@ impl Cw4Contract {
self.encode_msg(msg)
}

fn encode_smart_query(&self, msg: Cw4QueryMsg) -> StdResult<QueryRequest<Empty>> {
fn encode_smart_query<Q: CustomQuery>(&self, msg: Cw4QueryMsg) -> StdResult<QueryRequest<Q>> {
Ok(WasmQuery::Smart {
contract_addr: self.addr().into(),
msg: to_binary(&msg)?,
Expand All @@ -63,7 +64,7 @@ impl Cw4Contract {
}

/// Show the hooks
pub fn hooks(&self, querier: &QuerierWrapper) -> StdResult<Vec<String>> {
pub fn hooks<Q: CustomQuery>(&self, querier: &QuerierWrapper<Q>) -> StdResult<Vec<String>> {
let query = self.encode_smart_query(Cw4QueryMsg::Hooks {})?;
let res: HooksResponse = querier.query(&query)?;
Ok(res.hooks)
Expand Down
2 changes: 1 addition & 1 deletion packages/multi-test/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,7 @@ where
{
/// This registers contract code (like uploading wasm bytecode on a chain),
/// so it can later be used to instantiate a contract.
pub fn store_code(&mut self, code: Box<dyn Contract<CustomT::ExecT>>) -> u64 {
pub fn store_code(&mut self, code: Box<dyn Contract<CustomT::ExecT, CustomT::QueryT>>) -> u64 {
self.init_modules(|router, _, _| router.wasm.store_code(code) as u64)
}

Expand Down
Loading

0 comments on commit 49fceee

Please sign in to comment.