You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -5,165 +5,176 @@ description: Add a function to your smart contract so you can query addresses by
5
5
6
6
# First contract Query
7
7
8
-
In the previous section, you added a message to register an address under a name in storage. In this section, you make it possible to easily query for said stored values.
8
+
In the previous section, you added a message to register an address under a name in storage.
9
+
In this section, you make it possible to easily query for said stored values.
If you skipped the previous section, you can just switch the project to its [`first-execute-message`](https://github.com/b9lab/cw-my-nameservice/tree/first-execute-message) branch and take it from there.
13
+
If you skipped the previous section, you can just switch the project to its
To query from storage, you add a specific query message and its corresponding response. Add a `QueryResponse` import to `src/msg.rs`:
19
22
20
-
<CodeBlocktitle="src/msg.rs">
21
-
```diff-rs
22
-
- use cosmwasm_schema::cw_serde;
23
-
+ use cosmwasm_schema::{cw_serde, QueryResponses};
24
-
```
25
-
</CodeBlock>
23
+
```rust title="src/msg.rs"
24
+
//diff-del
25
+
-usecosmwasm_schema::cw_serde;
26
+
//diff-add
27
+
+usecosmwasm_schema::{cw_serde, QueryResponses};
28
+
```
26
29
27
30
Then add the new enum and struct:
28
31
29
-
<CodeBlocktitle="src/msg.rs">
30
-
```rust
31
-
#[cw_serde]
32
-
#[derive(QueryResponses)]
33
-
pub enum QueryMsg {
34
-
#[returns(ResolveRecordResponse)]
35
-
ResolveRecord { name: String },
36
-
}
37
-
38
-
#[cw_serde]
39
-
pub struct ResolveRecordResponse {
40
-
pub address: Option<String>,
41
-
}
42
-
```
43
-
</CodeBlock>
32
+
```rust title="src/msg.rs"
33
+
#[cw_serde]
34
+
#[derive(QueryResponses)]
35
+
pubenumQueryMsg {
36
+
#[returns(ResolveRecordResponse)]
37
+
ResolveRecord { name:String },
38
+
}
39
+
40
+
#[cw_serde]
41
+
pubstructResolveRecordResponse {
42
+
pubaddress:Option<String>,
43
+
}
44
+
```
44
45
45
46
Note how:
46
47
47
-
* As with the transaction message, the `QueryMsg` is an enum.
48
-
* The `ResolveRecord` type mentions the type it returns with the use of the `returns` macro.
49
-
*`QueryResponses` is a [macro](https://github.com/CosmWasm/cosmwasm/blob/main/packages/schema-derive/src/lib.rs#L12).
50
-
*`ResolveRecordResponse` contains an `Option<String>` to account for the fact that a missing owner is a valid result when resolving a name.
51
-
*`ResolveRecordResponse` otherwise looks very much like a `NameRecord`, but it could be different and collect different values from different places, depending on what is needed with this query.
48
+
- As with the transaction message, the `QueryMsg` is an enum.
49
+
- The `ResolveRecord` type mentions the type it returns with the use of the `returns` macro.
50
+
-`QueryResponses` is a [macro](https://github.com/CosmWasm/cosmwasm/blob/main/packages/schema-derive/src/lib.rs#L12).
51
+
-`ResolveRecordResponse` contains an `Option<String>` to account for the fact that a missing owner is a valid result when resolving a name.
52
+
-`ResolveRecordResponse` otherwise looks very much like a `NameRecord`, but it could be different and collect
53
+
different values from different places, depending on what is needed with this query.
52
54
53
55
## The query function
54
56
55
57
You define the message handling in `src/contract.rs`. Adjust the imports:
* Just as for the `execute` function, the `query` function is only here to dispatch to other functions depending on the message variant.
100
-
* Unlike the `execute` function, it takes a non-mutable `Deps`. Indeed, a query is not meant to modify storage, and Rust can catch such errors at compilation instead of run time.
101
-
* The function uses the `.may_load` method to handle potential errors gracefully. See Rust's `?` conditional `return`.
102
-
* The `address` variable is an `Option<String>` because a missing value in storage is a valid response.
103
-
* The return type is JSON binary, that you create by calling the standard `serde` function `to_json_binary`.
103
+
- Just as for the `execute` function, the `query` function is only here to dispatch to other functions
104
+
depending on the message variant.
105
+
- Unlike the `execute` function, it takes a non-mutable `Deps`. Indeed, a query is not meant to modify storage,
106
+
and Rust can catch such errors at compilation instead of run time.
107
+
- The function uses the `.may_load` method to handle potential errors gracefully. See Rust's `?` conditional `return`.
108
+
- The `address` variable is an `Option<String>` because a missing value in storage is a valid response.
109
+
- The return type is JSON binary, that you create by calling the standard `serde` function `to_json_binary`.
104
110
105
111
With this done, you can now query registered addresses by their names.
106
112
107
113
## Unit testing
108
114
109
115
It's time for your third unit test. In `src/contract.rs`, add the following:
110
116
111
-
<CodeBlock title="src/contract.rs">
112
-
```diff-rs
113
-
...
114
-
115
-
#[cfg(test)]
116
-
mod tests {
117
-
use crate::{
118
-
- msg::{ExecuteMsg, InstantiateMsg},
119
-
+ msg::{ExecuteMsg, InstantiateMsg, QueryMsg},
120
-
state::{NameRecord, NAME_RESOLVER},
121
-
};
122
-
- use cosmwasm_std::{testing, Addr, Response};
123
-
+ use cosmwasm_std::{testing, Addr, Binary, Response};
124
-
125
-
...
126
-
127
-
#[test]
128
-
fn test_execute() {
129
-
...
130
-
}
131
-
132
-
+ #[test]
133
-
+ fn test_query() {
134
-
+ // Arrange
135
-
+ let mut mocked_deps_mut = testing::mock_dependencies();
136
-
+ let mocked_env = testing::mock_env();
137
-
+ let name = "alice".to_owned();
138
-
+ let mocked_addr_value = "addr".to_owned();
139
-
+ let mocked_addr = Addr::unchecked(mocked_addr_value.clone());
140
-
+ let mocked_msg_info = testing::message_info(&mocked_addr, &[]);
141
-
+ let _ = super::execute_register(mocked_deps_mut.as_mut(), mocked_msg_info, name.clone())
142
-
+ .expect("Failed to register alice");
143
-
+ let query_msg = QueryMsg::ResolveRecord { name };
144
-
+
145
-
+ // Act
146
-
+ let query_result = super::query(mocked_deps_mut.as_ref(), mocked_env, query_msg);
147
-
+
148
-
+ // Assert
149
-
+ assert!(query_result.is_ok(), "Failed to query alice name");
150
-
+ let expected_response = format!(r#"{{"address":"{mocked_addr_value}"}}"#);
151
-
+ let expected = Binary::new(expected_response.as_bytes().to_vec());
At this stage, you should have something similar to the [`first-query-message`](https://github.com/b9lab/cw-my-nameservice/tree/first-query-message) branch, with [this](https://github.com/b9lab/cw-my-nameservice/compare/first-execute-message..first-query-message) as the diff.
192
+
At this stage, you should have something similar to the
with [this](https://github.com/b9lab/cw-my-nameservice/compare/first-execute-message..first-query-message) as the diff.
182
195
183
-
</HighlightBox>
196
+
:::
184
197
185
-
So far your unit tests have only tested functions in isolation and run within Rust, without touching WebAssembly or CosmWasm. You expand a bit in the next section by having your functions interact with a mocked app chain.
198
+
So far your unit tests have only tested functions in isolation and run within Rust,
199
+
without touching WebAssembly or CosmWasm. You expand a bit in the next section by having
0 commit comments