Skip to main content

Query

So you're asking, How do we change the state of our contract but what if we want to read some details? We don't need to pay transaction fees on that, do we? No, my friend, this is what querying is for!

Querying is the other half of the coin to messages. You can think of queries as a database read, or a way of querying state.

So as we did with all other sections let's head to where it starts src/msg.rs.

Define QueryMsg and Query response

src/msg.rs
pub enum QueryMsg {
GetConfig {},
}

pub struct ConfigResponse {
pub owner: Addr,
pub cw20_address: Addr,
pub cw721_address: Option<Addr>,
pub max_tokens: u32,
pub unit_price: Uint128,
pub name: String,
pub symbol: String,
pub token_uri: String,
pub extension: Extension,
pub unused_token_id: u32,
}

Our QueryMsg is very simple. Because we only define a single state - the Config struct, so we only need a single QueryMsg to get the Config.

Below QueryMsg, we define the ConfigResponse struct to be used as the return result for the GetConfig {} query. Its fields are the same as the Config struct state.

Write querying logic

src/contract.rs
#[cfg_attr(not(feature = "library"), entry_point)]
pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
match msg {
QueryMsg::GetConfig {} => to_binary(&query_config(deps)?),
}
}

fn query_config(deps: Deps) -> StdResult<ConfigResponse> {
let config = CONFIG.load(deps.storage)?;
Ok(ConfigResponse {
owner: config.owner,
cw20_address: config.cw20_address,
cw721_address: config.cw721_address,
max_tokens: config.max_tokens,
unit_price: config.unit_price,
name: config.name,
symbol: config.symbol,
token_uri: config.token_uri,
extension: config.extension,
unused_token_id: config.unused_token_id,
})
}

You can see in query function, QueryMsg are handled differently than InstantiateMsg or ExecuteMsg. When returning from a query you don't return via a Response. You must define a custom struct which can then be encoded to Binary.

When msg matches with QueryMsg::GetConfig{}, the query thread are passed to the query_config function.

About the query_config function, in the first line, by using load(), we get the CONFIG Item data previously stored in the store and assign it to a config variable.

And at the end, it's a simple return line using the Ok structure, inside it is a ConfigResponse struct containing the return result.

Ok, next chapter we will test some thing that we write from Instantiate to Query chapter. For now, we're done!