Skip to content

Commit

Permalink
Workshop (#1)
Browse files Browse the repository at this point in the history
* Generate cw template

* Add msgs

* Implement instantiate endpoint

* Fix InstantiateMsg

* Implement execute msg

* implement query msg

* Fix contract

* Add README.md
  • Loading branch information
pinosu authored Dec 4, 2024
1 parent 0a71d34 commit d1a6285
Show file tree
Hide file tree
Showing 20 changed files with 2,045 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/neutron
200 changes: 199 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,199 @@
# CosmWasm-Workshop
# CosmWasm-Workshop

Getting Started with CosmWasm Smart Contracts

## Environment Setup

- Install Go 1.22: https://go.dev/doc/install
- Install Rust: https://www.rust-lang.org/tools/install
- Install Docker: https://docs.docker.com/engine/install/

- Add wasm target:
`rustup target add wasm32-unknown-unknown`

- Install cargo-generate:
`cargo install cargo-generate`

## Counter Contract

### Generate contract from template

```sh
# Generate new contract from template
# Project Name: counter-contract
# minimal: true
cargo generate CosmWasm/cw-template
```

### Define messages

```rust
// File: src/msg.rs
use cosmwasm_schema::{cw_serde, QueryResponses};

#[cw_serde]
pub enum InstantiateMsg {
Zero {},
Set {value: u8},
}

#[cw_serde]
pub enum ExecuteMsg {
Inc {},
Dec {},
Set {value: u8},
}

#[cw_serde]
#[derive(QueryResponses)]
pub enum QueryMsg {
#[returns(CounterResponse)]
Value {},
}

#[cw_serde]
pub struct CounterResponse {
pub value: u8,
}
```

### Implement contract entrypoints

```rust
// File: contract.rs
#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;
use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult, to_json_binary};
use crate::error::ContractError;
use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg, CounterResponse};
use cw_storage_plus::Item;

const COUNTER: Item<u8> = Item::new("value");

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
deps: DepsMut,
_env: Env,
_info: MessageInfo,
msg: InstantiateMsg,
) -> Result<Response, ContractError> {
COUNTER.save(
deps.storage,
&match msg {
InstantiateMsg::Zero {} => 0,
InstantiateMsg::Set {value} => value,
},
)?;
Ok(Response::default())
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn execute(
deps: DepsMut,
_env: Env,
_info: MessageInfo,
msg: ExecuteMsg,
) -> Result<Response, ContractError> {
COUNTER.update::<_, ContractError>(deps.storage, |old_value| {
Ok(match msg {
ExecuteMsg::Inc {} => old_value.saturating_add(1),
ExecuteMsg::Dec {} => old_value.saturating_sub(1),
ExecuteMsg::Set {value} => value,
})
})?;
Ok(Response::default())
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
match msg {
QueryMsg::Value {} => Ok(to_json_binary(&CounterResponse {
value: COUNTER.may_load(deps.storage)?.unwrap(),
})?),
}
}
```

## Build contract

For local testing:
```sh
cargo build --target wasm32-unknown-unknown --release --lib
# The artifact will be generated in the ./target/wasm32-unknown-unknown/release/ directory.
```

For testnet/mainnet use the CosmWasm optimizer:
```sh
docker run --rm -v "$(pwd)":/code --mount type=volume,source="$(basename "$(pwd)")_cache",target=/target --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry cosmwasm/optimizer:0.16.0

# The artifact will be generated in the ./artifacts directory.
```

## Neutron testnet

### Setup client

1. Clone the repo from here: https://github.com/neutron-org/neutron
2. Checkout the right version: `git checkout v5.0.2`
3. cd to it and run `make install`
4. make sure neutrond binary is available by running `neutrond version`

### Configure default values for neutron testnet
1. `neutrond config chain-id pion-1`
2. `neutrond config keyring-backend test`
3. `neutrond config node https://rpc-palvus.pion-1.ntrn.tech:443`

### Create an account
1. Add a new key: `neutrond keys add cw-wallet`
2. visit https://discord.neutron.org
3. find `testnet-faucet` channel in the `GENERAL` section
4. type: `$request <addr>`

### Upload contract to the network
```sh
cd artifacts
neutrond tx wasm store "./counter_contract.wasm" --from cw-wallet --gas 2500000 --gas-prices 0.025untrn -y
```

### Instantiate the contract
```sh
neutrond tx wasm instantiate <code_id> '{"zero":{}}' --from cw-wallet --admin cw-wallet --label counter --gas 250000 --gas-prices 0.025untrn -y
```

### Query contract state
All
```sh
neutrond q wasm contract-state all <contract_address>
```

Raw
```sh
neutrond q wasm contract-state raw <contract_address> <key>
```

Smart
```sh
neutrond q wasm contract-state smart <contract_address> '{"value":{}}'
```

### Execute msg

Increment counter by 1
```sh
neutrond tx wasm execute <contract_address> '{"inc":{}}' --from cw-wallet --gas 250000 --gas-prices 0.025untrn -y
```

Decrement counter by 1
```sh
neutrond tx wasm execute <contract_address> '{"dec":{}}' --from cw-wallet --gas 250000 --gas-prices 0.025untrn -y
```

Set counter to 10
```sh
neutrond tx wasm execute <contract_address> '{"set":{"value": 10}}' --from cw-wallet --gas 250000 --gas-prices 0.025untrn -y
```

## References:

- Cosmwasm documentation: https://docs.cosmwasm.com/
- Neutron Nebular workshop: https://github.com/sotnikov-s/nnw-helper/
5 changes: 5 additions & 0 deletions counter-contract/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[alias]
wasm = "build --release --lib --target wasm32-unknown-unknown"
unit-test = "test --lib"
schema = "run --bin schema"
integration-test = "test --lib integration_tests"
61 changes: 61 additions & 0 deletions counter-contract/.circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
version: 2.1

executors:
builder:
docker:
- image: buildpack-deps:trusty

jobs:
docker-image:
executor: builder
steps:
- checkout
- setup_remote_docker:
docker_layer_caching: true
- run:
name: Build Docker artifact
command: docker build --pull -t "cosmwasm/cw-gitpod-base:${CIRCLE_SHA1}" .
- run:
name: Push application Docker image to docker hub
command: |
if [ "${CIRCLE_BRANCH}" = "master" ]; then
docker tag "cosmwasm/cw-gitpod-base:${CIRCLE_SHA1}" cosmwasm/cw-gitpod-base:latest
docker login --password-stdin -u "$DOCKER_USER" \<<<"$DOCKER_PASS"
docker push cosmwasm/cw-gitpod-base:latest
docker logout
fi
docker-tagged:
executor: builder
steps:
- checkout
- setup_remote_docker:
docker_layer_caching: true
- run:
name: Push application Docker image to docker hub
command: |
docker tag "cosmwasm/cw-gitpod-base:${CIRCLE_SHA1}" "cosmwasm/cw-gitpod-base:${CIRCLE_TAG}"
docker login --password-stdin -u "$DOCKER_USER" \<<<"$DOCKER_PASS"
docker push
docker logout
workflows:
version: 2
test-suite:
jobs:
# this is now a slow process... let's only run on master
- docker-image:
filters:
branches:
only:
- master
- docker-tagged:
filters:
tags:
only:
- /^v.*/
branches:
ignore:
- /.*/
requires:
- docker-image
11 changes: 11 additions & 0 deletions counter-contract/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
root = true

[*]
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.rs]
indent_size = 4
75 changes: 75 additions & 0 deletions counter-contract/.github/workflows/Basic.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Based on https://github.com/actions-rs/example/blob/master/.github/workflows/quickstart.yml

on: [push, pull_request]

name: Basic

jobs:

test:
name: Test Suite
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2

- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: 1.60.0
target: wasm32-unknown-unknown
override: true

- name: Run unit tests
uses: actions-rs/cargo@v1
with:
command: unit-test
args: --locked
env:
RUST_BACKTRACE: 1

- name: Compile WASM contract
uses: actions-rs/cargo@v1
with:
command: wasm
args: --locked
env:
RUSTFLAGS: "-C link-arg=-s"

lints:
name: Lints
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2

- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: 1.60.0
override: true
components: rustfmt, clippy

- name: Run cargo fmt
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check

- name: Run cargo clippy
uses: actions-rs/cargo@v1
with:
command: clippy
args: -- -D warnings

- name: Generate Schema
uses: actions-rs/cargo@v1
with:
command: schema
args: --locked

- name: Schema Changes
# fails if any changes not committed
run: git diff --exit-code schema
35 changes: 35 additions & 0 deletions counter-contract/.github/workflows/Release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: release wasm

on:
release:
types: [created]

jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2
- name: Install cargo-run-script
uses: actions-rs/cargo@v1
with:
command: install
args: cargo-run-script
- name: Run cargo optimize
uses: actions-rs/cargo@v1
with:
command: run-script
args: optimize
- name: Get release ID
id: get_release
uses: bruceadams/[email protected]
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Upload optimized wasm
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ./artifacts/*.wasm
tag: ${{ github.ref }}
overwrite: true
file_glob: true
Loading

0 comments on commit d1a6285

Please sign in to comment.