This site requires Javascript to be enabled.

Interacting with your contract

Now that your contract is deployed and instantiated, it's time to start interacting with it. This involves generating transactions and retrieving information from the contract.

Querying contract data

Queries read data from the blockchain without altering any stored information, so they do not incur any gas fees.

There are several types of queries we can perform, but a common type of query we are interested in is the contract-state query, which we will execute in smart mode. This allows us to run queries with specific arguments to filter the resultset instead of retrieving the entire contract data or metadata.

If you have created the increment contract project, we will show you how to use the Archway Developer CLI and archwayd to get the contract's count state.

Query using Archway Developer CLI

The following is the general command structure for executing a query:

archway contracts query smart CONTRACT [STDININPUT] [--json] [--log-level debug|error|info|warn] [--no-validation] [--args <value> | --args-file <value>| ]

A basic example for the increment contract would be:

archway contracts query smart increment --args '{"get_count": {}}'

An example of the output would be:

{  "count": 0}

Query using archwayd

Please make sure to substitute [CONTRACT-ADDRESS] for your contract's address.

mainnet

testnet

archwayd query wasm contract-state smart [CONTRACT-ADDRESS] '{"get_count": {}}' --node https://rpc.mainnet.archway.io:443 --chain-id archway-1

An example of the output would be:

data:
  count: 1

Deeper dive

Why was the query argument {"get_count": {}}?

The query argument {"get_count": {}} is used to match the expected input format defined in the smart contract's Rust code. This specific JSON structure corresponds to the QueryMsg::GetCount variant in the contract's query function.

If we open src/contract.rs in your project and inspect the function pub fn query, you will see the case matching statement that corresponds to our JSON query:

pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {  match msg {      QueryMsg::GetCount {} => to_binary(&query_count(deps)?), // Here it is  }}

Here's a detailed breakdown:

  • pub fn query: This is the query function that handles all the queries for the contract. It takes three parameters: deps (dependencies), _env (environment), and msg (message).
  • msg: QueryMsg: The msg parameter is of type QueryMsg, which is an enum representing different types of query messages the contract can handle.
  • match msg: This line matches the msg parameter against different possible variants of the QueryMsg enum.
  • QueryMsg::GetCount {}: This variant corresponds to the {"get_count": {}} query argument. When this variant is matched, it calls the query_count function to get the current count.
  • to_binary(&query_count(deps)?): This line converts the result of the query_count function into a binary format suitable for returning to the caller.

To understand why the query argument is structured this way, let's look at the QueryMsg enum, which is defined in src/msg.rs:

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]#[serde(rename_all = "snake_case")]pub enum QueryMsg {    GetCount {},}
  • #derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema): This line uses Rust macros to automatically generate code for serialization, deserialization, cloning, debugging, partial equality, and JSON schema.
  • #serde(rename_all = "snake_case"): This attribute ensures that all enum variants are converted to snake_case when serialized to JSON.
  • pub enum QueryMsg: This defines the QueryMsg enum.
  • GetCount {}: This variant represents a query to get the current count.

When you execute the query command with {"get_count": {}}, it gets serialized into a QueryMsg::GetCount {} variant and passed to the query function. The match statement in the query function identifies this variant and calls the query_count function, which retrieves the current count and returns it as a binary response.

By understanding this structure, you can see how the JSON query argument maps directly to the Rust code in the smart contract, enabling precise and effective interactions with the contract's state.

Executing transactions

To increment the counter value, you'll need to execute a transaction that calls the function pub fn try_increment in src/contract.rs. This function is already public, but the transaction execution is handled by the function pub fn execute in src/contract.rs, which does pattern matching to call try_increment.

Increment count using the Archway Developer CLI

archway contracts execute increment --args '{"increment": {}}'

Info

If you ever receive an out of gas error you can always use the --gas-adjustment flag and set a value of 1.5 or more.

Sending an Increment transaction using archwayd

Please make sure to substitute [CONTRACT-ADDRESS] for your contract's address.

mainnet

testnet

archwayd tx wasm execute --chain-id archway-1 [CONTRACT-ADDRESS]  '{"increment": {}}' --from my-wallet --node https://rpc.mainnet.archway.io:443 --gas auto --gas-prices $(archwayd q rewards estimate-fees 1 --node 'https://rpc.mainnet.archway.io:443' --output json | jq -r '.gas_unit_price | (.amount + .denom)') --gas-adjustment 1.3

Example output:

✔ Enter the name or address of the account that will send the transaction … mywalletExecuting contract increment2  Chain: constantine-3  Signer: mywallet✅ Executed contract  increment2-0.1.0  Transaction: CEFC1B9F6AE482249C3F6F3ED1C723F25FA8C129F53F5169544931207769311A

Why is the Argument {"increment": {}}?

The argument {"increment": {}} is used to match the expected input format defined in the smart contract's Rust code. This specific JSON structure corresponds to the ExecuteMsg::Increment variant in the contract's execute function.

If we open src/contract.rs and inspect the pub fn execute function, we will see the pattern matching statement that corresponds to our JSON argument:

pub fn execute(  deps: DepsMut,  _env: Env,  info: MessageInfo,  msg: ExecuteMsg,) -> Result<Response, ContractError> {  match msg {    ExecuteMsg::Increment {} => try_increment(deps), // Here it is    ExecuteMsg::Reset { count } => try_reset(deps, info, count),  }}

Understanding the execute Function

Here's a detailed breakdown:

  • pub fn execute: This is the main function that handles all the execute messages for the contract. It takes four parameters: deps (mutable dependencies), _env (environment), info (message information), and msg (message).
  • msg: ExecuteMsg: The msg parameter is of type ExecuteMsg, which is an enum representing different types of execute messages the contract can handle.
  • match msg: This line matches the msg parameter against different possible variants of the ExecuteMsg enum.
  • ExecuteMsg::Increment {}: This variant corresponds to the {"increment": {}} JSON argument. When this variant is matched, it calls the try_increment function to increment the count.
  • ExecuteMsg::Reset { count }: This variant matches the {"reset": {"count": }} JSON argument. When this variant is matched, it calls the try_reset function to reset the count to the specified value.

Understanding the ExecuteMsg Enum

To understand why the execute argument is structured this way, let's look at the ExecuteMsg enum, which is typically defined in src/msg.rs:

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]#[serde(rename_all = "snake_case")]pub enum ExecuteMsg {    Increment {},    Reset { count: i32 },}
  • #derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema): This line uses Rust macros to automatically generate code for serialization, deserialization, cloning, debugging, partial equality, and JSON schema.
  • #serde(rename_all = "snake_case"): This attribute ensures that all enum variants are converted to snake_case when serialized to JSON.
  • pub enum ExecuteMsg: This defines the ExecuteMsg enum.
  • Increment {}: This variant represents a message to increment the count.
  • Reset { count: i32 }: This variant represents a message to reset the count to a specific value.

How the Execute Command Works

When you execute the command with {"increment": {}}, it gets serialized into an ExecuteMsg::Increment {} variant and passed to the execute function. The match statement in the execute function identifies this variant and calls the try_increment function, which increments the count and returns a response.

By understanding this structure, you can see how the JSON execute argument maps directly to the Rust code in the smart contract, enabling precise and effective interactions with the contract's state.

If our {"increment": {}} transaction succeeded and we query count again, it will have increased by 1:

archway contracts query smart increment --args '{"get_count": {}}'

Now outputs:

{  "count": 1}

This shows that the contract's state has been updated as expected.

Why is the argument {"increment": {}}?

If we open src/contract.rs and inspect the pub fn execute function, we'll see a pattern matching statement that matches our JSON argument:

pub fn execute(  deps: DepsMut,  _env: Env,  info: MessageInfo,  msg: ExecuteMsg,) -> Result<Response, ContractError> {  match msg {    ExecuteMsg::Increment {} => try_increment(deps), // Here it is    ExecuteMsg::Reset { count } => try_reset(deps, info, count),  }}

As you can see, enum attributes again are converted. ExecuteMsg::Increment {} becomes {"increment": {}} in the CLI.

If our { "increment": {}} transaction succeeded and we query count again, it will have increased by 1*:

archway contracts query smart increment --args '{"get_count": {}}'

Now outputs:

{  "count": 1}