Skip to main content

Counter Contract

In this section

We introduce counter which is a simple decentralized application(dApp) that stores a number and exposes methods to increment, reset and query it.

Create Counter Project

In the environment setup section we covered the installation of Beaker, a very useful toolchain. We will be using it here for this tutorial. You can also use cargo generate instead of following along, but we strongly suggest you use beaker instead.

To create the project, run the following command:

beaker new counter-dapp

This gives you 2 template options to choose from. For the sake of this tutorial, let's use the down arrow button to select counter-example.

? 🤷   Which starting template would you like to use? ›
minimal
❯ counter-example

This will generate new directory called counter-dapp which should come from this template.

So what's in the template? Let's have a look at the generated project structure.

.
├── .beaker
├── .cargo
├── contracts
├── frontend
├── ts/sdk
├── .gitignore
├── Beaker.toml
└── Cargo.toml

Let's break down each file:

.beaker

It contains information about smart-contract such as code_id, addresses, label for each network when you store smart-contract successfully. While the state.json file is there for mainnet and testnet state, state.local.json file is intended to use locally and being gitignored since its state will not make any sense on any other machine.

contracts/

This is where smart contracts are stored. A single workspace can contain multiple contracts.

With the counter-example template, it should have the counter contract pregenerated. Besides this, you can scaffold many contracts in this folder by running this command:

beaker wasm new <contract_name>

frontend/

This should be self explanatory, it's where frontend and contracts are stored.

With the counter-example template, it demonstrates how frontend apps can access deployed contract's info through .beaker. It does so by symlinking .beaker into the frontend directory, and since states in .beaker are in json format, javascript code can import and use them without any extra work.

With the minimal template, this directory does not exist, which means it does not assume your frontend choice. In that case, you might want to checkout create-cosmos-app for creating your frontend or just create one from scratch.

Beaker.toml

All the project configuration needs to be specified here. Now let's have a look.

name = ''
gas_price = '0.025uaura'
gas_adjustment = 1.3
account_prefix = 'aura'
derivation_path = '''m/44'/118'/0'/0/0'''

[networks.serenity]
chain_id = 'auradev_1236-2'
network_variant = 'Shared'
grpc_endpoint = 'https://grpc.serenity.aura.network:9092'
rpc_endpoint = 'https://rpc.serenity.aura.network'

[accounts.signer]
mnemonic = 'your mnemonic'

You can check out the details of the configuration file here.

Contract

The contract presents 2 methods: execute and query. These should be self-explanatory, but if not you can think of them as write and read type methods respectively.

Deploy contract

For each network you want to store and instantiate the contracts to, you must specify them in the Beaker.toml file. You can copy the example configuration above for the purposes of this tutorial.

Now the contract can be deployed (build + store-code + instantiate) using the following command:

beaker wasm deploy counter --signer-account signer --no-wasm-opt --raw '{ "count": 0 }' --network serenity

What's happening here equivalent to the following command sequence:

# build .wasm file
# stored in `target/wasm32-unknown-unknown/release/<CONTRACT_NAME>.wasm`
# `--no-wasm-opt` is suitable for development, explained below
beaker wasm build --no-wasm-opt

# read .wasm in `target/wasm32-unknown-unknown/release/<CONTRACT_NAME>.wasm` due to `--no-wasm-opt` flag
# use `--signer-account test1` which is predefined.
# The list of all predefined accounts are here: https://github.com/osmosis-labs/LocalOsmosis#accounts
# `code-id` is stored in the beaker state, local by default
beaker wasm store-code counter --signer-account signer --no-wasm-opt --network serenity

# instantiate counter contract
# with instantiate msg: '{ "count": 0 }'
beaker wasm instantiate counter --signer-account signer --raw '{ "count": 0 }' --network serenity

The flag --no-wasm-opt is skipping rust-optimizer for faster development iteration, but for other uses, we recommend you use optimization since it reduces the bytecode size significantly.

When the deployment is successful, both the code_id and contract_address ara automatically added to the .beaker file. You can now interact with the contract via cli.

Frontend

The Counter template also comes with a frontend template. But in order to interact with it you need:

  • Keplr installed on your machine.

  • Keplr chain setup for network you want interact. In this guide, we use Serenity chain.

  • Have setup your wallet on Keplr. You can restore the account by importing your mnemonic into Keplr wallet.

  • Updated the environment configuration file (counter-dapp/frontend/.env.test) for running on Serenity testnet as shown below:

    NEXT_PUBLIC_NETWORK=serenity
    NEXT_PUBLIC_RPC_ENDPOINT="https://rpc.serenity.aura.network"
    NEXT_PUBLIC_CHAIN_ID=auradev_1236-2

After all of that is done, we can now start our dev frontend:

cd frontend
yarn && yarn dev

Then open http://localhost:3000/ in the browser and that's it. You are now running a CosmWasm smart contract dapp on Aura Serenity Testnet. Congratulations, developer. Have Fun!