Introduction
Welcome back to my series. Sorry for this belated, we will discover the execute
contract in this part.
In the previous part, I explained that execute
will change the smart contract data.
Let's implement this.
Create the message to execute smart contracts.
First, we need to define the ExecuteMsg
and ExecuteResponse
by updating the following code in the src/msg.rs
:
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
Update {},
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct ExecuteResponse {
pub counter: i32,
}
ExecuteMsg
is an enum and has an Updates arm
. This arm
is simply to help counter
variable increment 1 when we execute the contract.
Let's create a file: execute.rs
in the src
folder. Our logic will be in this file.
First, import module execute
to lib.rs
We are implementing a function with the name try_update_counter
(don't use camel case, convention in rust use dash
to connect word in name of function or variable) and we pass the deps
as a parameter. The function return a Result<Response, ContractError>
. All logic of function will be as below:
#[cfg(not(feature = "library"))]
use cosmwasm_std::{to_binary, DepsMut, Response};
use crate::error::ContractError;
use crate::msg::ExecuteResponse;
use crate::state::{State, STATE};
pub fn try_update_counter(deps: DepsMut) -> Result<Response, ContractError> {
let current_state = STATE.load(deps.storage)?;
let mut current_counter = current_state.counter;
current_counter += 1;
let new_state = State {
counter: current_counter,
};
STATE.save(deps.storage, &new_state)?;
let resp = to_binary(&ExecuteResponse {
counter: current_counter,
})
.unwrap();
Ok(Response::new().set_data(resp))
}
Yea, I think it's easy to read and understand: we get the counter in the current state of the contract current.counter
, increment it by 1 and save it in the contract's store again, return it as a response.
But we have a wonder: where to implement try_update_counter
. We need to open src / contract.rs
and update it with the function below the immediate
second entry point.
#[cfg_attr(not(feature = "library"), entry_point)]
pub fn execute(
deps: DepsMut,
_env: Env,
_info: MessageInfo,
msg: ExecuteMsg,
) -> Result<Response, ContractError> {
match msg {
ExecuteMsg::Update {} => try_update_counter(deps),
}
}
Alright, we have implemented the second entry point of our contract! Don't forget to test the logic!
Next to the Testing module
section.
Testing module
Still in the file: execute.rs
. and update the below code to bottom:
#[cfg(test)]
mod tests {
use crate::contract::{execute, instantiate};
use crate::msg::{ExecuteMsg, ExecuteResponse};
use crate::state::STATE;
use crate::msg::InstantiateMsg;
use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
use cosmwasm_std::to_binary;
const ADDR: &str = "addr";
#[test]
fn test_execute() {
let mut deps = mock_dependencies();
let env = mock_env();
let info = mock_info(ADDR, &[]);
let expect_data = to_binary(&ExecuteResponse { counter: 1 }).unwrap();
let expect_number = 2;
// instantiate msg
let msg = InstantiateMsg {};
let _resp = instantiate(deps.as_mut(), env.clone(), info.clone(), msg).unwrap();
// execute one time
let msg = ExecuteMsg::Update {};
let resp = execute(deps.as_mut(), env.clone(), info.clone(), msg).unwrap();
println!("Execute once!");
assert_eq!(resp.data, Some(expect_data));
// execute two time
let msg = ExecuteMsg::Update {};
let _resp = execute(deps.as_mut(), env, info, msg);
let current_state = STATE.load(deps.as_mut().storage).unwrap();
println!("Execute twice!");
assert_eq!(current_state.counter, expect_number);
}
}
We create a module test and unit test function test_execute
.
We still import all dependencies and create two values, one for a response from try_update_counter
is expected_data
and one compare with our state is expected_number
.
We also import InstantiateMsg to create our state, of cause, counter
will be 0.
One time to execute, we call execute
function, update counter equal 1 and assert_eq resp.data
with expect_data
Two time to execute, we also call execute
function, update counter equal 2 and assert_eq current_state.counter
with expect_number
.
Very simple to understand.
Run cargo-test
in the terminal
If your output is like the below, everything is right:
running 2 tests
test contract::tests::test_instantiate ... ok
test execute::tests::test_execute ... ok
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Doc-tests cw-starter
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
It run 1 test case, and 1 passed.
Summary
We just have created second entry point of smart contract is execute
: ExecuteMsg, ExecuteResponse and try_update_counter
.
We also create a module for testing this.
I will mention the last entry point naming: query
in the next part.
Thanks, everyone to read the post.
Top comments (0)