1use snafu::ResultExt;
2
3use cosmwasm::errors::{Result, SerializeErr, Unauthorized};
4use cosmwasm::serde::to_vec;
5use cosmwasm::traits::{Api, Extern, Storage};
6use cosmwasm::types::{Env, Response};
7
8use crate::msg::{CountResponse, HandleMsg, InitMsg, QueryMsg};
9use crate::state::{config, config_read, State};
10
11pub fn init<S: Storage, A: Api>(
12 deps: &mut Extern<S, A>,
13 env: Env,
14 msg: InitMsg,
15) -> Result<Response> {
16 let state = State {
17 count: msg.count,
18 owner: env.message.signer,
19 version: 1,
20 };
21
22 config(&mut deps.storage).save(&state)?;
23
24 Ok(Response::default())
25}
26
27pub fn handle<S: Storage, A: Api>(
28 deps: &mut Extern<S, A>,
29 env: Env,
30 msg: HandleMsg,
31) -> Result<Response> {
32 match msg {
33 HandleMsg::Increment {} => try_increment(deps, env),
34 HandleMsg::Reset { count } => try_reset(deps, env, count),
35 }
36}
37
38pub fn try_increment<S: Storage, A: Api>(deps: &mut Extern<S, A>, _env: Env) -> Result<Response> {
39 config(&mut deps.storage).update(&|mut state| {
40 state.count += 1;
41 Ok(state)
42 })?;
43
44 Ok(Response::default())
45}
46
47pub fn try_reset<S: Storage, A: Api>(
48 deps: &mut Extern<S, A>,
49 env: Env,
50 count: i32,
51) -> Result<Response> {
52 config(&mut deps.storage).update(&|mut state| {
53 if env.message.signer != state.owner {
54 Unauthorized {}.fail()?;
55 }
56
57 state.count = count;
58 Ok(state)
59 })?;
60 Ok(Response::default())
61}
62
63pub fn query<S: Storage, A: Api>(deps: &Extern<S, A>, msg: QueryMsg) -> Result<Vec<u8>> {
64 match msg {
65 QueryMsg::GetCount {} => query_count(deps),
66 }
67}
68
69fn query_count<S: Storage, A: Api>(deps: &Extern<S, A>) -> Result<Vec<u8>> {
70 let state = config_read(&deps.storage).load()?;
71
72 let resp = CountResponse { count: state.count };
73 to_vec(&resp).context(SerializeErr {
74 kind: "CountResponse",
75 })
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81 use cosmwasm::errors::Error;
82 use cosmwasm::mock::{dependencies, mock_env};
83 use cosmwasm::serde::from_slice;
84 use cosmwasm::types::coin;
85
86 #[test]
87 fn proper_initialization() {
88 let mut deps = dependencies(20);
89
90 let msg = InitMsg { count: 17 };
91 let env = mock_env(&deps.api, "creator", &coin("1000", "earth"), &[]);
92
93 let res = init(&mut deps, env, msg).unwrap();
95 assert_eq!(0, res.messages.len());
96
97 let res = query(&deps, QueryMsg::GetCount {}).unwrap();
99 let value: CountResponse = from_slice(&res).unwrap();
100 assert_eq!(17, value.count);
101 }
102
103 #[test]
104 fn increment() {
105 let mut deps = dependencies(20);
106
107 let msg = InitMsg { count: 17 };
108 let env = mock_env(
109 &deps.api,
110 "creator",
111 &coin("2", "token"),
112 &coin("2", "token"),
113 );
114 let _res = init(&mut deps, env, msg).unwrap();
115
116 let env = mock_env(&deps.api, "anyone", &coin("2", "token"), &[]);
118 let msg = HandleMsg::Increment {};
119 let _res = handle(&mut deps, env, msg).unwrap();
120
121 let res = query(&deps, QueryMsg::GetCount {}).unwrap();
123 let value: CountResponse = from_slice(&res).unwrap();
124 assert_eq!(18, value.count);
125 }
126
127 #[test]
128 fn reset() {
129 let mut deps = dependencies(20);
130
131 let msg = InitMsg { count: 17 };
132 let env = mock_env(
133 &deps.api,
134 "creator",
135 &coin("2", "token"),
136 &coin("2", "token"),
137 );
138 let _res = init(&mut deps, env, msg).unwrap();
139
140 let unauth_env = mock_env(&deps.api, "anyone", &coin("2", "token"), &[]);
142 let msg = HandleMsg::Reset { count: 5 };
143 let res = handle(&mut deps, unauth_env, msg);
144 match res {
145 Err(Error::Unauthorized { .. }) => {}
146 _ => panic!("Must return unauthorized error"),
147 }
148
149 let auth_env = mock_env(&deps.api, "creator", &coin("2", "token"), &[]);
151 let msg = HandleMsg::Reset { count: 5 };
152 let _res = handle(&mut deps, auth_env, msg).unwrap();
153
154 let res = query(&deps, QueryMsg::GetCount {}).unwrap();
156 let value: CountResponse = from_slice(&res).unwrap();
157 assert_eq!(5, value.count);
158 }
159}