Skip to main content

devx1/
contract.rs

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        // we can just call .unwrap() to assert this was a success
94        let res = init(&mut deps, env, msg).unwrap();
95        assert_eq!(0, res.messages.len());
96
97        // it worked, let's query the state
98        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        // beneficiary can release it
117        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        // should increase counter by 1
122        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        // beneficiary can release it
141        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        // only the original creator can reset the counter
150        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        // should now be 5
155        let res = query(&deps, QueryMsg::GetCount {}).unwrap();
156        let value: CountResponse = from_slice(&res).unwrap();
157        assert_eq!(5, value.count);
158    }
159}