From 64739533ea736e54c798466ffdd24e4ea61c4b54 Mon Sep 17 00:00:00 2001 From: "Felix C. Morency" <1102868+fmorency@users.noreply.github.com> Date: Mon, 27 Oct 2025 15:36:27 -0400 Subject: [PATCH 1/8] test: converter e2e --- .gitignore | 1 + .gitmodules | 6 +++ Cargo.toml | 1 + Makefile | 48 +++++++++++++++++ e2e/.env | 35 ++++++++++++ e2e/docker-compose.yml | 23 ++++++++ e2e/scripts/init_manifest_ledger.sh | 49 +++++++++++++++++ e2e/test_helper/bats-assert | 1 + e2e/test_helper/bats-support | 1 + e2e/tests/converter.bats | 84 +++++++++++++++++++++++++++++ rust-toolchain.toml | 4 ++ 11 files changed, 253 insertions(+) create mode 100644 .gitmodules create mode 100644 Makefile create mode 100644 e2e/.env create mode 100644 e2e/docker-compose.yml create mode 100755 e2e/scripts/init_manifest_ledger.sh create mode 160000 e2e/test_helper/bats-assert create mode 160000 e2e/test_helper/bats-support create mode 100644 e2e/tests/converter.bats create mode 100644 rust-toolchain.toml diff --git a/.gitignore b/.gitignore index c403c34..b0d8521 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target .idea/ +artifacts/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..41ce0c5 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "e2e/test_helper/bats-support"] + path = e2e/test_helper/bats-support + url = https://github.com/bats-core/bats-support +[submodule "e2e/test_helper/bats-assert"] + path = e2e/test_helper/bats-assert + url = https://github.com/bats-core/bats-assert diff --git a/Cargo.toml b/Cargo.toml index f8c2669..a538776 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ resolver = "2" [workspace.package] version = "0.1.0" +rust-version = "1.86.0" [workspace.dependencies] bech32 = "0.11" diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..07ff012 --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +MAKEFLAGS += --no-print-directory + +e2e-chain-up: + @echo "--> Starting e2e test blockchain environment" + @docker compose -f e2e/docker-compose.yml up -d --wait + +e2e-chain-down: + @echo "--> Stopping e2e test blockchain environment" + @docker compose -f e2e/docker-compose.yml down -v + +.PHONY: e2e-chain-up e2e-chain-down + +#### Build #### + +build: + @echo "--> Building contracts" + @cargo wasm + +build-opt: + @echo "--> Checking for protoc installation" + @$(MAKE) check-protoc + @echo "--> Checking for wasm-opt installation" + @$(MAKE) check-wasm-opt + @echo "--> Checking for cosmwasm-check installation" + @$(MAKE) check-cosmwasm-check + @echo "--> Building optimized contracts" + @RUSTFLAGS="-C link-arg=-s" cargo wasm --locked + @echo "--> Optimizing wasm binaries" + @mkdir -p ./artifacts/ + @for f in target/wasm32-unknown-unknown/release/*.wasm; do wasm-opt -Os "$$f" -o "artifacts/$$(basename "$$f")"; done + @echo "--> Optimized wasm binaries are in the ./artifacts/ directory" + @echo "--> Running cosmwasm-check on optimized binaries" + @for f in artifacts/*.wasm; do cosmwasm-check "$$f"; done + +clean: + @echo "--> Cleaning build artifacts" + @cargo clean + +check-protoc: + @command -v protoc >/dev/null 2>&1 || { echo "protoc not found; install with: sudo apt install protobuf-compiler (or your distro's package)"; exit 1; } + +check-wasm-opt: + @command -v wasm-opt >/dev/null 2>&1 || { echo "wasm-opt not found; install with: sudo apt install binaryen (or your distro's package)"; exit 1; } + +check-cosmwasm-check: + @command -v cosmwasm-check >/dev/null 2>&1 || { echo "cosmwasm-check not found; install with: cargo install cosmwasm-check"; exit 1; } + +.PHONY: build clean build-opt check-protoc check-wasm-opt check-cosmwasm-check \ No newline at end of file diff --git a/e2e/.env b/e2e/.env new file mode 100644 index 0000000..2a49bd6 --- /dev/null +++ b/e2e/.env @@ -0,0 +1,35 @@ +KEY="user1" +KEY2="user2" +ADDR1="manifest1hj5fveer5cjtn4wd6wstzugjfdxzl0xp8ws9ct" +ADDR2="manifest1efd63aw40lxf3n4mhf7dzhjkr453axurm6rp3z" +VESTING_ADDR="manifest1yyuzq9665yjmmhnmfn7zsajnyz9lcdelggf6ke" +CHAIN_ID="test-1" +MONIKER="zebradonkey" +KEYRING="test" +HOME_DIR="/persistent/.manifest" +BINARY="/usr/bin/manifestd" +MNEMO1="decorate bright ozone fork gallery riot bus exhaust worth way bone indoor calm squirrel merry zero scheme cotton until shop any excess stage laundry" +MNEMO2="wealth flavor believe regret funny network recall kiss grape useless pepper cram hint member few certain unveil rather brick bargain curious require crowd raise" +BANK_ADDR=manifest1hj5fveer5cjtn4wd6wstzugjfdxzl0xp8ws9ct +GAS_STATION_ADDR=manifest1efd63aw40lxf3n4mhf7dzhjkr453axurm6rp3z +RPC="26657" +REST="1317" +PROFF="6060" +P2P="26656" +GRPC="9090" +GRPC_WEB="9091" +ROSETTA="8080" +TIMEOUT_COMMIT="3s" +VOTING_TIMEOUT="10s" +DENOM=umfx +BOND_DENOM=upoa +POA_ADMIN_ADDRESS="manifest1afk9zr2hn2jsac63h4hm60vl9z3e5u69gndzf7c99cqge3vzwjzsfmy9qj" +USER_GROUP_ADDRESS="manifest1dlszg2sst9r69my4f84l3mj66zxcf3umcgujys30t84srg95dgvsmxrlcr" +COMMON_MANIFESTD_ARGS="--gas-prices 0.0011${DENOM} --gas-adjustment 1.8 --gas auto --home ${HOME_DIR} --keyring-backend $KEYRING --chain-id $CHAIN_ID --yes --node http://manifest-ledger:$RPC" +GROUP_MEMBERS={"members":[{"address":"${ADDR1}","weight":"1","metadata":"user1"},{"address":"${ADDR2}","weight":"1","metadata":"user2"}]} +DECISION_POLICY={"@type":"/cosmos.group.v1.ThresholdDecisionPolicy","threshold":"1","windows":{"voting_period":"10s","min_execution_period":"0s"}} +TX_COUNT_DIR=/tx-count +TX_COUNT_FILE=tx-count.txt +TX_COUNT_PATH="${TX_COUNT_DIR}/${TX_COUNT_FILE}" +POSTGREST_HOST=postgrest +CONVERT_WASM_ADDRESS="manifest14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4zfs7u" diff --git a/e2e/docker-compose.yml b/e2e/docker-compose.yml new file mode 100644 index 0000000..94c1169 --- /dev/null +++ b/e2e/docker-compose.yml @@ -0,0 +1,23 @@ +services: + manifest-ledger: + image: ghcr.io/manifest-network/manifest-ledger:1.0.11 + volumes: + - manifest-ledger-bin:/usr/bin + - manifest-ledger-data:/persistent + - ./scripts/init_manifest_ledger.sh:/usr/local/bin/init_manifest_ledger.sh:ro + - ../:/workspace:ro + ports: + - "9090:9090" + - "26657:26657" + entrypoint: ["/bin/bash", "-c"] + env_file: ./.env + command: /usr/local/bin/init_manifest_ledger.sh + healthcheck: + test: manifestd status | grep '"earliest_block_height":"1"' + interval: 10s + timeout: 5s + retries: 5 + +volumes: + manifest-ledger-bin: + manifest-ledger-data: diff --git a/e2e/scripts/init_manifest_ledger.sh b/e2e/scripts/init_manifest_ledger.sh new file mode 100755 index 0000000..7804b8e --- /dev/null +++ b/e2e/scripts/init_manifest_ledger.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# This script initializes the manifest ledger genesis file and starts a ledger node + +set -e + +update_test_genesis () { + cat $HOME_DIR/config/genesis.json | jq "$1" > $HOME_DIR/config/tmp_genesis.json && mv $HOME_DIR/config/tmp_genesis.json $HOME_DIR/config/genesis.json +} + +echo "$MNEMO1" | $BINARY keys add "$KEY" --home="$HOME_DIR" --keyring-backend "$KEYRING" --recover +echo "$MNEMO2" | $BINARY keys add "$KEY2" --home="$HOME_DIR" --keyring-backend "$KEYRING" --recover +$BINARY init $MONIKER --home=$HOME_DIR --chain-id $CHAIN_ID +update_test_genesis '.consensus["params"]["block"]["max_gas"]="1000000000"' +update_test_genesis '.app_state["bank"]["denom_metadata"]=[{"base":"umfx","denom_units":[{"aliases":[],"denom":"umfx","exponent":0},{"aliases":[],"denom":"MFX","exponent":6}],"description":"MFX","display":"MFX","name":"MFX","symbol":"MFX","uri":"","uri_hash":""}]' +update_test_genesis '.app_state["gov"]["params"]["min_deposit"]=[{"denom":"'$DENOM'","amount":"1000000"}]' +update_test_genesis '.app_state["gov"]["params"]["voting_period"]="15s"' +update_test_genesis '.app_state["gov"]["params"]["expedited_voting_period"]="10s"' +update_test_genesis '.app_state["staking"]["params"]["bond_denom"]="'${BOND_DENOM}'"' +update_test_genesis '.app_state["staking"]["params"]["min_commission_rate"]="0.000000000000000000"' +update_test_genesis '.app_state["mint"]["params"]["mint_denom"]="'$DENOM'"' +update_test_genesis '.app_state["mint"]["params"]["blocks_per_year"]="6311520"' +update_test_genesis '.app_state["tokenfactory"]["params"]["denom_creation_fee"]=[]' +update_test_genesis '.app_state["tokenfactory"]["params"]["denom_creation_gas_consume"]=0' +update_test_genesis '.app_state["feegrant"]["allowances"]=[{"granter":"'${GAS_STATION_ADDR}'","grantee":"'${BANK_ADDR}'","allowance":{"@type":"/cosmos.feegrant.v1beta1.AllowedMsgAllowance","allowance":{"@type":"/cosmos.feegrant.v1beta1.BasicAllowance","spend_limit":[],"expiration":null},"allowed_messages":["/cosmos.bank.v1beta1.MsgSend"]}}]' +update_test_genesis '.app_state["group"]["group_seq"]="1"' +update_test_genesis '.app_state["group"]["groups"]=[{"id":"1","admin":"'${POA_ADMIN_ADDRESS}'","metadata":"AQ==","version":"2","total_weight":"2","created_at":"2024-05-16T15:10:54.372190727Z"}]' +update_test_genesis '.app_state["group"]["group_members"]=[{"group_id":"1","member":{"address":"'${ADDR1}'","weight":"1","metadata":"user1","added_at":"2024-05-16T15:10:54.372190727Z"}},{"group_id":"1","member":{"address":"'${ADDR2}'","weight":"1","metadata":"user2","added_at":"2024-05-16T15:10:54.372190727Z"}}]' +update_test_genesis '.app_state["group"]["group_policy_seq"]="1"' +update_test_genesis '.app_state["group"]["group_policies"]=[{"address":"'${POA_ADMIN_ADDRESS}'","group_id":"1","admin":"'${POA_ADMIN_ADDRESS}'","metadata":"AQ==","version":"2","decision_policy":{"@type":"/cosmos.group.v1.ThresholdDecisionPolicy","threshold":"1","windows":{"voting_period":"'${VOTING_TIMEOUT}'","min_execution_period":"0s"}},"created_at":"2024-05-16T15:10:54.372190727Z"}]' +update_test_genesis '.app_state["tokenfactory"]["factory_denoms"]=[{"denom":"factory/manifest1afk9zr2hn2jsac63h4hm60vl9z3e5u69gndzf7c99cqge3vzwjzsfmy9qj/upwr","authority_metadata":{"admin":"manifest1afk9zr2hn2jsac63h4hm60vl9z3e5u69gndzf7c99cqge3vzwjzsfmy9qj"}}]' +update_test_genesis '.app_state["bank"]["denom_metadata"] |= . + [{"description":"PWR","denom_units":[{"denom":"factory/manifest1afk9zr2hn2jsac63h4hm60vl9z3e5u69gndzf7c99cqge3vzwjzsfmy9qj/upwr","exponent":0,"aliases":["PWR"]},{"denom":"PWR","exponent":6,"aliases":["factory/manifest1afk9zr2hn2jsac63h4hm60vl9z3e5u69gndzf7c99cqge3vzwjzsfmy9qj/upwr"]}],"base":"factory/manifest1afk9zr2hn2jsac63h4hm60vl9z3e5u69gndzf7c99cqge3vzwjzsfmy9qj/upwr","display":"PWR","name":"POWER","symbol":"PWR","uri":"","uri_hash":""}]' +update_test_genesis '.app_state["wasm"]["params"]["code_upload_access"]["permission"]="Everybody"' +update_test_genesis '.app_state["wasm"]["params"]["instantiate_default_permission"]="Everybody"' +$BINARY genesis add-genesis-account $KEY 100000000000000000${BOND_DENOM},100000000000000000000000000000${DENOM} --keyring-backend $KEYRING --home=$HOME_DIR +$BINARY genesis add-genesis-account $KEY2 100000000000000000${DENOM} --keyring-backend $KEYRING --home=$HOME_DIR +$BINARY genesis gentx $KEY 1000000${BOND_DENOM} --keyring-backend $KEYRING --home=$HOME_DIR --chain-id $CHAIN_ID --commission-rate=0.0 --commission-max-rate=1.0 --commission-max-change-rate=0.1 +$BINARY genesis collect-gentxs --home=$HOME_DIR +$BINARY genesis validate-genesis --home=$HOME_DIR +sed -i 's/laddr = "tcp:\/\/127.0.0.1:26657"/laddr = "tcp:\/\/0.0.0.0:'$RPC'"/g' $HOME_DIR/config/config.toml +sed -i 's/cors_allowed_origins = \[\]/cors_allowed_origins = \["\*"\]/g' $HOME_DIR/config/config.toml +sed -i 's/address = "tcp:\/\/localhost:1317"/address = "tcp:\/\/0.0.0.0:'$REST'"/g' $HOME_DIR/config/app.toml +sed -i 's/enable = false/enable = true/g' $HOME_DIR/config/app.toml +sed -i 's/pprof_laddr = "localhost:6060"/pprof_laddr = "localhost:'$PROFF'"/g' $HOME_DIR/config/config.toml +sed -i 's/laddr = "tcp:\/\/0.0.0.0:26656"/laddr = "tcp:\/\/0.0.0.0:'$P2P'"/g' $HOME_DIR/config/config.toml +sed -i 's/address = "localhost:9090"/address = "0.0.0.0:'$GRPC'"/g' $HOME_DIR/config/app.toml +sed -i 's/address = "localhost:9091"/address = "0.0.0.0:'$GRPC_WEB'"/g' $HOME_DIR/config/app.toml +sed -i 's/address = ":8080"/address = "0.0.0.0:'$ROSETTA'"/g' $HOME_DIR/config/app.toml +sed -i 's/timeout_commit = "5s"/timeout_commit = "'$TIMEOUT_COMMIT'"/g' $HOME_DIR/config/config.toml +POA_ADMIN_ADDRESS=${POA_ADMIN_ADDRESS} $BINARY start --home=${HOME_DIR} --pruning=nothing --minimum-gas-prices=0.0011${DENOM} --rpc.laddr="tcp://0.0.0.0:$RPC" diff --git a/e2e/test_helper/bats-assert b/e2e/test_helper/bats-assert new file mode 160000 index 0000000..f1e9280 --- /dev/null +++ b/e2e/test_helper/bats-assert @@ -0,0 +1 @@ +Subproject commit f1e9280eaae8f86cbe278a687e6ba755bc802c1a diff --git a/e2e/test_helper/bats-support b/e2e/test_helper/bats-support new file mode 160000 index 0000000..004e707 --- /dev/null +++ b/e2e/test_helper/bats-support @@ -0,0 +1 @@ +Subproject commit 004e707638eedd62e0481e8cdc9223ad471f12ee diff --git a/e2e/tests/converter.bats b/e2e/tests/converter.bats new file mode 100644 index 0000000..643a051 --- /dev/null +++ b/e2e/tests/converter.bats @@ -0,0 +1,84 @@ +#!/usr/bin/env bats + +load '../test_helper/bats-support/load' +load '../test_helper/bats-assert/load' + +setup() { + export CHAIN_ID="test-1" + export RPC="http://localhost:26657" + export VALIDATOR_KEY="user1" + export CONTAINER_NAME="e2e-manifest-ledger-1" + export WASM_FILE="artifacts/converter.wasm" + + # Build optimized contract + run make build-opt + assert_success + assert [ -f "$WASM_FILE" ] + + # Start chain + run make e2e-chain-up + assert_success + + # Wait for chain to be ready + sleep 5 +} + +teardown() { + if [ "$BATS_TEST_COMPLETED" = "1" ]; then + make e2e-chain-down + fi +} + +@test "upload converter contract to chain" { + # Upload contract + run docker exec "$CONTAINER_NAME" manifestd tx wasm store \ + "/workspace/$WASM_FILE" \ + --from "$VALIDATOR_KEY" \ + --home "/persistent/.manifest" \ + --keyring-backend "test" \ + --gas auto \ + --gas-adjustment 1.4 \ + --gas-prices "0.0011umfx" \ + --chain-id "$CHAIN_ID" \ + --node "$RPC" \ + --yes \ + --output json + + assert_success + + JSON_OUTPUT=$(echo "$output" | tail -n +3) + + # Extract transaction hash + TX_HASH=$(echo "$JSON_OUTPUT" | jq -r '.txhash') + assert [ -n "$TX_HASH" ] + + # Check for error code + ERR_CODE=$(echo "$JSON_OUTPUT" | jq -r '.code') + assert [ "$ERR_CODE" -eq 0 ] + + echo "# Transaction submitted with hash: $TX_HASH" >&3 + + sleep 3 + + # Query transaction to get code ID + run docker exec "$CONTAINER_NAME" manifestd query tx "$TX_HASH" \ + --node "$RPC" \ + --output json + + assert_success + + CODE_ID=$(echo "$output" | tail -n +2 | jq -r '.events[] | select(.type=="store_code") | .attributes[] | select(.key=="code_id") | .value') + assert [ "$CODE_ID" -gt 0 ] + + echo "# Contract uploaded successfully with code ID: $CODE_ID" >&3 + + # Verify code exists + run docker exec "$CONTAINER_NAME" manifestd query wasm code-info "$CODE_ID" \ + --node "$RPC" \ + --output json + + assert_success + + CREATOR=$(echo "$output" | tail -n +2 | jq -r '.code_info.creator') + assert [ -n "$CREATOR" ] +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..f77ddfc --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "1.86.0" +components = ["rustfmt", "clippy"] +targets = ["wasm32-unknown-unknown"] \ No newline at end of file From be35ee8abf2b3236bd06d5c178e00ca998a78703 Mon Sep 17 00:00:00 2001 From: "Felix C. Morency" <1102868+fmorency@users.noreply.github.com> Date: Tue, 28 Oct 2025 15:28:04 -0400 Subject: [PATCH 2/8] test: e2e --- e2e/.env | 2 +- e2e/scripts/init_manifest_ledger.sh | 2 +- e2e/tests/converter.bats | 206 ++++++++++++++++++++++++++-- 3 files changed, 197 insertions(+), 13 deletions(-) diff --git a/e2e/.env b/e2e/.env index 2a49bd6..56a581d 100644 --- a/e2e/.env +++ b/e2e/.env @@ -23,7 +23,7 @@ TIMEOUT_COMMIT="3s" VOTING_TIMEOUT="10s" DENOM=umfx BOND_DENOM=upoa -POA_ADMIN_ADDRESS="manifest1afk9zr2hn2jsac63h4hm60vl9z3e5u69gndzf7c99cqge3vzwjzsfmy9qj" +POA_ADMIN_ADDRESS="manifest1hj5fveer5cjtn4wd6wstzugjfdxzl0xp8ws9ct" USER_GROUP_ADDRESS="manifest1dlszg2sst9r69my4f84l3mj66zxcf3umcgujys30t84srg95dgvsmxrlcr" COMMON_MANIFESTD_ARGS="--gas-prices 0.0011${DENOM} --gas-adjustment 1.8 --gas auto --home ${HOME_DIR} --keyring-backend $KEYRING --chain-id $CHAIN_ID --yes --node http://manifest-ledger:$RPC" GROUP_MEMBERS={"members":[{"address":"${ADDR1}","weight":"1","metadata":"user1"},{"address":"${ADDR2}","weight":"1","metadata":"user2"}]} diff --git a/e2e/scripts/init_manifest_ledger.sh b/e2e/scripts/init_manifest_ledger.sh index 7804b8e..6a8e9d7 100755 --- a/e2e/scripts/init_manifest_ledger.sh +++ b/e2e/scripts/init_manifest_ledger.sh @@ -27,7 +27,7 @@ update_test_genesis '.app_state["group"]["groups"]=[{"id":"1","admin":"'${POA_AD update_test_genesis '.app_state["group"]["group_members"]=[{"group_id":"1","member":{"address":"'${ADDR1}'","weight":"1","metadata":"user1","added_at":"2024-05-16T15:10:54.372190727Z"}},{"group_id":"1","member":{"address":"'${ADDR2}'","weight":"1","metadata":"user2","added_at":"2024-05-16T15:10:54.372190727Z"}}]' update_test_genesis '.app_state["group"]["group_policy_seq"]="1"' update_test_genesis '.app_state["group"]["group_policies"]=[{"address":"'${POA_ADMIN_ADDRESS}'","group_id":"1","admin":"'${POA_ADMIN_ADDRESS}'","metadata":"AQ==","version":"2","decision_policy":{"@type":"/cosmos.group.v1.ThresholdDecisionPolicy","threshold":"1","windows":{"voting_period":"'${VOTING_TIMEOUT}'","min_execution_period":"0s"}},"created_at":"2024-05-16T15:10:54.372190727Z"}]' -update_test_genesis '.app_state["tokenfactory"]["factory_denoms"]=[{"denom":"factory/manifest1afk9zr2hn2jsac63h4hm60vl9z3e5u69gndzf7c99cqge3vzwjzsfmy9qj/upwr","authority_metadata":{"admin":"manifest1afk9zr2hn2jsac63h4hm60vl9z3e5u69gndzf7c99cqge3vzwjzsfmy9qj"}}]' +update_test_genesis '.app_state["tokenfactory"]["factory_denoms"]=[{"denom":"factory/manifest1afk9zr2hn2jsac63h4hm60vl9z3e5u69gndzf7c99cqge3vzwjzsfmy9qj/upwr","authority_metadata":{"admin":"manifest1hj5fveer5cjtn4wd6wstzugjfdxzl0xp8ws9ct"}}]' update_test_genesis '.app_state["bank"]["denom_metadata"] |= . + [{"description":"PWR","denom_units":[{"denom":"factory/manifest1afk9zr2hn2jsac63h4hm60vl9z3e5u69gndzf7c99cqge3vzwjzsfmy9qj/upwr","exponent":0,"aliases":["PWR"]},{"denom":"PWR","exponent":6,"aliases":["factory/manifest1afk9zr2hn2jsac63h4hm60vl9z3e5u69gndzf7c99cqge3vzwjzsfmy9qj/upwr"]}],"base":"factory/manifest1afk9zr2hn2jsac63h4hm60vl9z3e5u69gndzf7c99cqge3vzwjzsfmy9qj/upwr","display":"PWR","name":"POWER","symbol":"PWR","uri":"","uri_hash":""}]' update_test_genesis '.app_state["wasm"]["params"]["code_upload_access"]["permission"]="Everybody"' update_test_genesis '.app_state["wasm"]["params"]["instantiate_default_permission"]="Everybody"' diff --git a/e2e/tests/converter.bats b/e2e/tests/converter.bats index 643a051..dd9a906 100644 --- a/e2e/tests/converter.bats +++ b/e2e/tests/converter.bats @@ -6,9 +6,15 @@ load '../test_helper/bats-assert/load' setup() { export CHAIN_ID="test-1" export RPC="http://localhost:26657" - export VALIDATOR_KEY="user1" export CONTAINER_NAME="e2e-manifest-ledger-1" export WASM_FILE="artifacts/converter.wasm" + export USER_ADDR="manifest1hj5fveer5cjtn4wd6wstzugjfdxzl0xp8ws9ct" + export USER2_ADDR="manifest1efd63aw40lxf3n4mhf7dzhjkr453axurm6rp3z" + export POA_ADMIN_ADDR=$USER_ADDR + export RATE="2" + export SOURCE_DENOM="umfx" + export TARGET_DENOM="factory/manifest1afk9zr2hn2jsac63h4hm60vl9z3e5u69gndzf7c99cqge3vzwjzsfmy9qj/upwr" + export GAS_PRICES="0.0011umfx" # Build optimized contract run make build-opt @@ -29,16 +35,19 @@ teardown() { fi } -@test "upload converter contract to chain" { - # Upload contract +@test "convert" { + ##### + ##### STORE CONTRACT + ##### + echo "# --> Storing contract on-chain" >&3 run docker exec "$CONTAINER_NAME" manifestd tx wasm store \ "/workspace/$WASM_FILE" \ - --from "$VALIDATOR_KEY" \ + --from "$USER_ADDR" \ --home "/persistent/.manifest" \ --keyring-backend "test" \ --gas auto \ --gas-adjustment 1.4 \ - --gas-prices "0.0011umfx" \ + --gas-prices "$GAS_PRICES" \ --chain-id "$CHAIN_ID" \ --node "$RPC" \ --yes \ @@ -47,16 +56,12 @@ teardown() { assert_success JSON_OUTPUT=$(echo "$output" | tail -n +3) - - # Extract transaction hash TX_HASH=$(echo "$JSON_OUTPUT" | jq -r '.txhash') assert [ -n "$TX_HASH" ] - - # Check for error code ERR_CODE=$(echo "$JSON_OUTPUT" | jq -r '.code') assert [ "$ERR_CODE" -eq 0 ] - echo "# Transaction submitted with hash: $TX_HASH" >&3 + echo "# --> Transaction submitted with hash: $TX_HASH" >&3 sleep 3 @@ -70,7 +75,7 @@ teardown() { CODE_ID=$(echo "$output" | tail -n +2 | jq -r '.events[] | select(.type=="store_code") | .attributes[] | select(.key=="code_id") | .value') assert [ "$CODE_ID" -gt 0 ] - echo "# Contract uploaded successfully with code ID: $CODE_ID" >&3 + echo "# --> Contract uploaded successfully with code ID: $CODE_ID" >&3 # Verify code exists run docker exec "$CONTAINER_NAME" manifestd query wasm code-info "$CODE_ID" \ @@ -81,4 +86,183 @@ teardown() { CREATOR=$(echo "$output" | tail -n +2 | jq -r '.code_info.creator') assert [ -n "$CREATOR" ] + + ##### + ##### INSTANTIATE CONTRACT + ##### + INIT_MSG='{"admin":"'$USER_ADDR'","poa_admin":"'$POA_ADMIN_ADDR'","rate":"'$RATE'","source_denom":"'$SOURCE_DENOM'","target_denom":"'$TARGET_DENOM'","paused":false}' + + echo "# --> Instantiating contract" >&3 + run docker exec "$CONTAINER_NAME" manifestd tx wasm instantiate "$CODE_ID" \ + "$INIT_MSG" \ + --from "$USER_ADDR" \ + --home "/persistent/.manifest" \ + --keyring-backend "test" \ + --label "converter-test" \ + --gas auto \ + --gas-adjustment 1.4 \ + --gas-prices "$GAS_PRICES" \ + --chain-id "$CHAIN_ID" \ + --node "$RPC" \ + --yes \ + --admin "$USER_ADDR" \ + --output json + + assert_success + + JSON_OUTPUT=$(echo "$output" | tail -n +3) + TX_HASH=$(echo "$JSON_OUTPUT" | jq -r '.txhash') + assert [ -n "$TX_HASH" ] + ERR_CODE=$(echo "$JSON_OUTPUT" | jq -r '.code') + assert [ "$ERR_CODE" -eq 0 ] + + echo "# --> Transaction submitted with hash: $TX_HASH" >&3 + + sleep 3 + + # Query transaction to get code ID + run docker exec "$CONTAINER_NAME" manifestd query tx "$TX_HASH" \ + --node "$RPC" \ + --output json + + assert_success + + CONTRACT_ADDR=$(echo "$output" | tail -n +2 | jq -r '.events[] | select(.type=="wasm") | .attributes[] | select(.key=="_contract_address") | .value') + assert [ -n "$CONTRACT_ADDR" ] + + ##### + ##### GRANT AUTHZ PWR MINTING CAPABILITIES TO CONTRACT + ##### + echo "# --> Setting PWR minting permissions to contract" >&3 + run docker exec "$CONTAINER_NAME" manifestd tx authz grant $CONTRACT_ADDR generic \ + --msg-type "/osmosis.tokenfactory.v1beta1.MsgMint" \ + --from "$USER_ADDR" \ + --home "/persistent/.manifest" \ + --keyring-backend "test" \ + --gas auto \ + --gas-adjustment 1.8 \ + --gas-prices "$GAS_PRICES" \ + --chain-id "$CHAIN_ID" \ + --node "$RPC" \ + --yes \ + --output json + + assert_success + + JSON_OUTPUT=$(echo "$output" | tail -n +3) + TX_HASH=$(echo "$JSON_OUTPUT" | jq -r '.txhash') + assert [ -n "$TX_HASH" ] + ERR_CODE=$(echo "$JSON_OUTPUT" | jq -r '.code') + assert [ "$ERR_CODE" -eq 0 ] + + echo "# --> Transaction submitted with hash: $TX_HASH" >&3 + + sleep 3 + + # Query transaction to get code ID + run docker exec "$CONTAINER_NAME" manifestd query tx "$TX_HASH" \ + --node "$RPC" \ + --output json + + assert_success + + JSON_OUTPUT=$(echo "$output" | tail -n +2) + ERR_CODE=$(echo "$JSON_OUTPUT" | jq -r '.code') + assert [ "$ERR_CODE" -eq 0 ] + + ##### + ##### GRANT AUTHZ MFX BURNING CAPABILITIES TO CONTRACT + ##### + echo "# --> Setting MFX burning permissions to contract" >&3 + run docker exec "$CONTAINER_NAME" manifestd tx authz grant $CONTRACT_ADDR generic \ + --msg-type "/liftedinit.manifest.v1.MsgBurnHeldBalance" \ + --from "$USER_ADDR" \ + --home "/persistent/.manifest" \ + --keyring-backend "test" \ + --gas auto \ + --gas-adjustment 1.8 \ + --gas-prices "$GAS_PRICES" \ + --chain-id "$CHAIN_ID" \ + --node "$RPC" \ + --yes \ + --output json + + assert_success + + JSON_OUTPUT=$(echo "$output" | tail -n +3) + TX_HASH=$(echo "$JSON_OUTPUT" | jq -r '.txhash') + assert [ -n "$TX_HASH" ] + ERR_CODE=$(echo "$JSON_OUTPUT" | jq -r '.code') + assert [ "$ERR_CODE" -eq 0 ] + + echo "# --> Transaction submitted with hash: $TX_HASH" >&3 + + sleep 3 + + # Query transaction to get code ID + run docker exec "$CONTAINER_NAME" manifestd query tx "$TX_HASH" \ + --node "$RPC" \ + --output json + + assert_success + + JSON_OUTPUT=$(echo "$output" | tail -n +2) + ERR_CODE=$(echo "$JSON_OUTPUT" | jq -r '.code') + assert [ "$ERR_CODE" -eq 0 ] + + ##### + ##### CONVERT MXF TO PWR + ##### + CONVERT_MSG='{"convert":{}}' + echo "# --> Converting 1 MFX to $RATE PWR" >&3 + run docker exec "$CONTAINER_NAME" manifestd tx wasm execute "$CONTRACT_ADDR" \ + "$CONVERT_MSG" \ + --from "$USER2_ADDR" \ + --home "/persistent/.manifest" \ + --keyring-backend "test" \ + --amount "1000000$SOURCE_DENOM" \ + --gas auto \ + --gas-adjustment 1.4 \ + --gas-prices "$GAS_PRICES" \ + --chain-id "$CHAIN_ID" \ + --node "$RPC" \ + --yes \ + --output json + + assert_success + + JSON_OUTPUT=$(echo "$output" | tail -n +3) + TX_HASH=$(echo "$JSON_OUTPUT" | jq -r '.txhash') + assert [ -n "$TX_HASH" ] + ERR_CODE=$(echo "$JSON_OUTPUT" | jq -r '.code') + assert [ "$ERR_CODE" -eq 0 ] + + echo "# --> Transaction submitted with hash: $TX_HASH" >&3 + + sleep 3 + + # Query transaction to get code ID + run docker exec "$CONTAINER_NAME" manifestd query tx "$TX_HASH" \ + --node "$RPC" \ + --output json + + assert_success + + JSON_OUTPUT=$(echo "$output" | tail -n +2) + ERR_CODE=$(echo "$JSON_OUTPUT" | jq -r '.code') + assert [ "$ERR_CODE" -eq 0 ] + + run docker exec "$CONTAINER_NAME" manifestd query bank balances "$USER2_ADDR" \ + --node "$RPC" \ + --output json + + assert_success + + JSON_OUTPUT=$(echo "$output" | tail -n +2) + PWR_BALANCE=$(echo "$JSON_OUTPUT" | jq -r '.balances[] | select(.denom=="'"$TARGET_DENOM"'") | .amount') + assert [ "$PWR_BALANCE" -eq 2000000 ] + + echo "# --> Conversion successful, received $RATE PWR" >&3 + + # TODO: Change config, Update Admin } From 13f792a8fdb3156852bf9344ad826c021fe74426 Mon Sep 17 00:00:00 2001 From: "Felix C. Morency" <1102868+fmorency@users.noreply.github.com> Date: Wed, 29 Oct 2025 10:29:53 -0400 Subject: [PATCH 3/8] fix: migrate message --- contracts/converter/src/msg.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contracts/converter/src/msg.rs b/contracts/converter/src/msg.rs index 3e626f9..b7bed9f 100644 --- a/contracts/converter/src/msg.rs +++ b/contracts/converter/src/msg.rs @@ -25,7 +25,9 @@ pub enum QueryMsg { } #[cw_serde] -pub enum MigrateMsg {} +pub enum MigrateMsg { + Migrate {}, +} // TODO: Write a macro to generate this struct from the Config struct #[cw_serde] From 34177f0782eec47fe3f8a9ad57dd2617b0a9c891 Mon Sep 17 00:00:00 2001 From: "Felix C. Morency" <1102868+fmorency@users.noreply.github.com> Date: Wed, 29 Oct 2025 10:30:12 -0400 Subject: [PATCH 4/8] chore: . --- e2e/test_helper/common.sh | 87 +++++++++++ e2e/tests/converter.bats | 299 +++++++------------------------------- 2 files changed, 140 insertions(+), 246 deletions(-) create mode 100644 e2e/test_helper/common.sh diff --git a/e2e/test_helper/common.sh b/e2e/test_helper/common.sh new file mode 100644 index 0000000..2f90b0f --- /dev/null +++ b/e2e/test_helper/common.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash + +run_tx() { + local desc=$1 + shift + echo "# --> $desc" >&3 + run docker exec "$CONTAINER_NAME" manifestd tx "$@" \ + --home "/persistent/.manifest" \ + --keyring-backend "test" \ + --gas auto \ + --gas-adjustment 1.8 \ + --gas-prices "$GAS_PRICES" \ + --chain-id "$CHAIN_ID" \ + --node "$RPC" \ + --yes \ + --output json + + assert_success + local json_output=$(echo "$output" | tail -n +3) + TX_HASH=$(echo "$json_output" | jq -r '.txhash') + ERR_CODE=$(echo "$json_output" | jq -r '.code') + assert [ -n "$TX_HASH" ] + assert [ "$ERR_CODE" -eq 0 ] + echo "# --> Transaction submitted with hash: $TX_HASH" >&3 + sleep 3 + + run docker exec "$CONTAINER_NAME" manifestd query tx "$TX_HASH" \ + --node "$RPC" \ + --output json + assert_success + ERR_CODE=$(echo "$output" | tail -n +2 | jq -r '.code') + if [ "$ERR_CODE" != "0" ]; then + echo "# ⚠️ Tx returned error code $ERR_CODE" >&3 + echo "$output" >&3 + fi +} + +query_json() { + local desc=$1 + shift + echo "# --> $desc" >&3 + run docker exec "$CONTAINER_NAME" manifestd query "$@" \ + --node "$RPC" --output json + assert_success + echo "$output" | tail -n +2 +} + +store_contract() { + run_tx "Storing contract on-chain" wasm store "/workspace/$WASM_FILE" --from "$USER_ADDR" + CODE_ID=$(docker exec "$CONTAINER_NAME" manifestd query tx "$TX_HASH" --node "$RPC" --output json | \ + jq -r '.events[] | select(.type=="store_code") | .attributes[] | select(.key=="code_id") | .value') + assert [ "$CODE_ID" -gt 0 ] + echo "# --> Contract uploaded with code ID: $CODE_ID" >&3 +} + +instantiate_contract() { + local init_msg=$1 + run_tx "Instantiating contract" wasm instantiate "$CODE_ID" "$init_msg" \ + --from "$USER_ADDR" --label "converter-test" --admin "$USER_ADDR" + CONTRACT_ADDR=$(docker exec "$CONTAINER_NAME" manifestd query tx "$TX_HASH" --node "$RPC" --output json | \ + jq -r '.events[] | select(.type=="wasm") | .attributes[] | select(.key=="_contract_address") | .value') + assert [ -n "$CONTRACT_ADDR" ] + echo "# --> Contract instantiated at: $CONTRACT_ADDR" >&3 +} + +grant_authz() { + local msg_type=$1 + run_tx "Granting authz for $msg_type" authz grant "$CONTRACT_ADDR" generic \ + --msg-type "$msg_type" --from "$USER_ADDR" +} + +execute_contract() { + local msg=$1 + local from=$2 + local amount=${3:-} # optional third argument + + echo "# --> Executing contract message" >&3 + + if [ -n "$amount" ]; then + run_tx "Executing contract (with funds)" wasm execute "$CONTRACT_ADDR" "$msg" \ + --from "$from" \ + --amount "$amount" + else + run_tx "Executing contract" wasm execute "$CONTRACT_ADDR" "$msg" \ + --from "$from" + fi +} diff --git a/e2e/tests/converter.bats b/e2e/tests/converter.bats index dd9a906..381d4d9 100644 --- a/e2e/tests/converter.bats +++ b/e2e/tests/converter.bats @@ -2,267 +2,74 @@ load '../test_helper/bats-support/load' load '../test_helper/bats-assert/load' +load '../test_helper/common.sh' setup() { - export CHAIN_ID="test-1" - export RPC="http://localhost:26657" - export CONTAINER_NAME="e2e-manifest-ledger-1" - export WASM_FILE="artifacts/converter.wasm" - export USER_ADDR="manifest1hj5fveer5cjtn4wd6wstzugjfdxzl0xp8ws9ct" - export USER2_ADDR="manifest1efd63aw40lxf3n4mhf7dzhjkr453axurm6rp3z" - export POA_ADMIN_ADDR=$USER_ADDR - export RATE="2" - export SOURCE_DENOM="umfx" - export TARGET_DENOM="factory/manifest1afk9zr2hn2jsac63h4hm60vl9z3e5u69gndzf7c99cqge3vzwjzsfmy9qj/upwr" - export GAS_PRICES="0.0011umfx" - - # Build optimized contract - run make build-opt - assert_success - assert [ -f "$WASM_FILE" ] - - # Start chain - run make e2e-chain-up - assert_success - - # Wait for chain to be ready - sleep 5 + export CHAIN_ID="test-1" + export RPC="http://localhost:26657" + export CONTAINER_NAME="e2e-manifest-ledger-1" + export WASM_FILE="artifacts/converter.wasm" + export USER_ADDR="manifest1hj5fveer5cjtn4wd6wstzugjfdxzl0xp8ws9ct" + export USER2_ADDR="manifest1efd63aw40lxf3n4mhf7dzhjkr453axurm6rp3z" + export POA_ADMIN_ADDR=$USER_ADDR + export RATE="2" + export SOURCE_DENOM="umfx" + export TARGET_DENOM="factory/manifest1afk9zr2hn2jsac63h4hm60vl9z3e5u69gndzf7c99cqge3vzwjzsfmy9qj/upwr" + export GAS_PRICES="0.0011umfx" + + run make build-opt + assert_success + assert [ -f "$WASM_FILE" ] + + run make e2e-chain-up + assert_success + sleep 5 } teardown() { - if [ "$BATS_TEST_COMPLETED" = "1" ]; then - make e2e-chain-down - fi + [ "$BATS_TEST_COMPLETED" = "1" ] && make e2e-chain-down } -@test "convert" { - ##### - ##### STORE CONTRACT - ##### - echo "# --> Storing contract on-chain" >&3 - run docker exec "$CONTAINER_NAME" manifestd tx wasm store \ - "/workspace/$WASM_FILE" \ - --from "$USER_ADDR" \ - --home "/persistent/.manifest" \ - --keyring-backend "test" \ - --gas auto \ - --gas-adjustment 1.4 \ - --gas-prices "$GAS_PRICES" \ - --chain-id "$CHAIN_ID" \ - --node "$RPC" \ - --yes \ - --output json - - assert_success - - JSON_OUTPUT=$(echo "$output" | tail -n +3) - TX_HASH=$(echo "$JSON_OUTPUT" | jq -r '.txhash') - assert [ -n "$TX_HASH" ] - ERR_CODE=$(echo "$JSON_OUTPUT" | jq -r '.code') - assert [ "$ERR_CODE" -eq 0 ] - - echo "# --> Transaction submitted with hash: $TX_HASH" >&3 - - sleep 3 - - # Query transaction to get code ID - run docker exec "$CONTAINER_NAME" manifestd query tx "$TX_HASH" \ - --node "$RPC" \ - --output json - - assert_success - - CODE_ID=$(echo "$output" | tail -n +2 | jq -r '.events[] | select(.type=="store_code") | .attributes[] | select(.key=="code_id") | .value') - assert [ "$CODE_ID" -gt 0 ] - - echo "# --> Contract uploaded successfully with code ID: $CODE_ID" >&3 - - # Verify code exists - run docker exec "$CONTAINER_NAME" manifestd query wasm code-info "$CODE_ID" \ - --node "$RPC" \ - --output json - - assert_success - - CREATOR=$(echo "$output" | tail -n +2 | jq -r '.code_info.creator') - assert [ -n "$CREATOR" ] - - ##### - ##### INSTANTIATE CONTRACT - ##### - INIT_MSG='{"admin":"'$USER_ADDR'","poa_admin":"'$POA_ADMIN_ADDR'","rate":"'$RATE'","source_denom":"'$SOURCE_DENOM'","target_denom":"'$TARGET_DENOM'","paused":false}' - - echo "# --> Instantiating contract" >&3 - run docker exec "$CONTAINER_NAME" manifestd tx wasm instantiate "$CODE_ID" \ - "$INIT_MSG" \ - --from "$USER_ADDR" \ - --home "/persistent/.manifest" \ - --keyring-backend "test" \ - --label "converter-test" \ - --gas auto \ - --gas-adjustment 1.4 \ - --gas-prices "$GAS_PRICES" \ - --chain-id "$CHAIN_ID" \ - --node "$RPC" \ - --yes \ - --admin "$USER_ADDR" \ - --output json - - assert_success - - JSON_OUTPUT=$(echo "$output" | tail -n +3) - TX_HASH=$(echo "$JSON_OUTPUT" | jq -r '.txhash') - assert [ -n "$TX_HASH" ] - ERR_CODE=$(echo "$JSON_OUTPUT" | jq -r '.code') - assert [ "$ERR_CODE" -eq 0 ] - - echo "# --> Transaction submitted with hash: $TX_HASH" >&3 - - sleep 3 - - # Query transaction to get code ID - run docker exec "$CONTAINER_NAME" manifestd query tx "$TX_HASH" \ - --node "$RPC" \ - --output json - - assert_success - - CONTRACT_ADDR=$(echo "$output" | tail -n +2 | jq -r '.events[] | select(.type=="wasm") | .attributes[] | select(.key=="_contract_address") | .value') - assert [ -n "$CONTRACT_ADDR" ] - - ##### - ##### GRANT AUTHZ PWR MINTING CAPABILITIES TO CONTRACT - ##### - echo "# --> Setting PWR minting permissions to contract" >&3 - run docker exec "$CONTAINER_NAME" manifestd tx authz grant $CONTRACT_ADDR generic \ - --msg-type "/osmosis.tokenfactory.v1beta1.MsgMint" \ - --from "$USER_ADDR" \ - --home "/persistent/.manifest" \ - --keyring-backend "test" \ - --gas auto \ - --gas-adjustment 1.8 \ - --gas-prices "$GAS_PRICES" \ - --chain-id "$CHAIN_ID" \ - --node "$RPC" \ - --yes \ - --output json - - assert_success - - JSON_OUTPUT=$(echo "$output" | tail -n +3) - TX_HASH=$(echo "$JSON_OUTPUT" | jq -r '.txhash') - assert [ -n "$TX_HASH" ] - ERR_CODE=$(echo "$JSON_OUTPUT" | jq -r '.code') - assert [ "$ERR_CODE" -eq 0 ] - - echo "# --> Transaction submitted with hash: $TX_HASH" >&3 - - sleep 3 - - # Query transaction to get code ID - run docker exec "$CONTAINER_NAME" manifestd query tx "$TX_HASH" \ - --node "$RPC" \ - --output json - - assert_success - - JSON_OUTPUT=$(echo "$output" | tail -n +2) - ERR_CODE=$(echo "$JSON_OUTPUT" | jq -r '.code') - assert [ "$ERR_CODE" -eq 0 ] - - ##### - ##### GRANT AUTHZ MFX BURNING CAPABILITIES TO CONTRACT - ##### - echo "# --> Setting MFX burning permissions to contract" >&3 - run docker exec "$CONTAINER_NAME" manifestd tx authz grant $CONTRACT_ADDR generic \ - --msg-type "/liftedinit.manifest.v1.MsgBurnHeldBalance" \ - --from "$USER_ADDR" \ - --home "/persistent/.manifest" \ - --keyring-backend "test" \ - --gas auto \ - --gas-adjustment 1.8 \ - --gas-prices "$GAS_PRICES" \ - --chain-id "$CHAIN_ID" \ - --node "$RPC" \ - --yes \ - --output json - - assert_success - - JSON_OUTPUT=$(echo "$output" | tail -n +3) - TX_HASH=$(echo "$JSON_OUTPUT" | jq -r '.txhash') - assert [ -n "$TX_HASH" ] - ERR_CODE=$(echo "$JSON_OUTPUT" | jq -r '.code') - assert [ "$ERR_CODE" -eq 0 ] - - echo "# --> Transaction submitted with hash: $TX_HASH" >&3 - - sleep 3 - - # Query transaction to get code ID - run docker exec "$CONTAINER_NAME" manifestd query tx "$TX_HASH" \ - --node "$RPC" \ - --output json - - assert_success - - JSON_OUTPUT=$(echo "$output" | tail -n +2) - ERR_CODE=$(echo "$JSON_OUTPUT" | jq -r '.code') - assert [ "$ERR_CODE" -eq 0 ] - - ##### - ##### CONVERT MXF TO PWR - ##### - CONVERT_MSG='{"convert":{}}' - echo "# --> Converting 1 MFX to $RATE PWR" >&3 - run docker exec "$CONTAINER_NAME" manifestd tx wasm execute "$CONTRACT_ADDR" \ - "$CONVERT_MSG" \ - --from "$USER2_ADDR" \ - --home "/persistent/.manifest" \ - --keyring-backend "test" \ - --amount "1000000$SOURCE_DENOM" \ - --gas auto \ - --gas-adjustment 1.4 \ - --gas-prices "$GAS_PRICES" \ - --chain-id "$CHAIN_ID" \ - --node "$RPC" \ - --yes \ - --output json - - assert_success - - JSON_OUTPUT=$(echo "$output" | tail -n +3) - TX_HASH=$(echo "$JSON_OUTPUT" | jq -r '.txhash') - assert [ -n "$TX_HASH" ] - ERR_CODE=$(echo "$JSON_OUTPUT" | jq -r '.code') - assert [ "$ERR_CODE" -eq 0 ] +@test "converter end-to-end" { + store_contract - echo "# --> Transaction submitted with hash: $TX_HASH" >&3 + INIT_MSG=$(jq -n --arg admin "$USER_ADDR" --arg poa "$POA_ADMIN_ADDR" \ + --arg rate "$RATE" --arg src "$SOURCE_DENOM" --arg tgt "$TARGET_DENOM" \ + '{"admin":$admin,"poa_admin":$poa,"rate":$rate,"source_denom":$src,"target_denom":$tgt,"paused":false}') + instantiate_contract "$INIT_MSG" - sleep 3 + grant_authz "/osmosis.tokenfactory.v1beta1.MsgMint" + grant_authz "/liftedinit.manifest.v1.MsgBurnHeldBalance" - # Query transaction to get code ID - run docker exec "$CONTAINER_NAME" manifestd query tx "$TX_HASH" \ - --node "$RPC" \ - --output json + SOURCE_SUPPLY_BEFORE=$(query_json "Querying MFX total supply before conversion" bank total-supply-of "$SOURCE_DENOM" | jq -r '.amount.amount') + TARGET_SUPPLY_BEFORE=$(query_json "Querying PWR total supply before conversion" bank total-supply-of "$TARGET_DENOM" | jq -r '.amount.amount') - assert_success + execute_contract '{"convert":{}}' "$USER2_ADDR" "1000000$SOURCE_DENOM" - JSON_OUTPUT=$(echo "$output" | tail -n +2) - ERR_CODE=$(echo "$JSON_OUTPUT" | jq -r '.code') - assert [ "$ERR_CODE" -eq 0 ] + PWR_BALANCE=$(query_json "Querying user2 PWR balance" bank balances "$USER2_ADDR" | jq -r '.balances[] | select(.denom=="'"$TARGET_DENOM"'") | .amount') + assert [ "$PWR_BALANCE" == "2000000" ] - run docker exec "$CONTAINER_NAME" manifestd query bank balances "$USER2_ADDR" \ - --node "$RPC" \ - --output json + execute_contract '{"update_admin":{"admin":"'"$USER2_ADDR"'"}}' "$USER_ADDR" + execute_contract '{"update_config":{"config":{"rate":"3"}}}' "$USER2_ADDR" - assert_success + execute_contract '{"convert":{}}' "$USER2_ADDR" "1000000$SOURCE_DENOM" + PWR_BALANCE=$(query_json "Querying updated PWR balance" bank balances "$USER2_ADDR" | jq -r '.balances[] | select(.denom=="'"$TARGET_DENOM"'") | .amount') + assert [ "$PWR_BALANCE" == "5000000" ] - JSON_OUTPUT=$(echo "$output" | tail -n +2) - PWR_BALANCE=$(echo "$JSON_OUTPUT" | jq -r '.balances[] | select(.denom=="'"$TARGET_DENOM"'") | .amount') - assert [ "$PWR_BALANCE" -eq 2000000 ] + execute_contract '{"update_config":{"config":{"paused":true}}}' "$USER2_ADDR" + run docker exec "$CONTAINER_NAME" manifestd tx wasm execute "$CONTRACT_ADDR" '{"convert":{}}' \ + --from "$USER2_ADDR" --home "/persistent/.manifest" --keyring-backend "test" \ + --amount "1000000$SOURCE_DENOM" --gas auto --gas-prices "$GAS_PRICES" \ + --chain-id "$CHAIN_ID" --node "$RPC" --yes --output json + assert_failure - echo "# --> Conversion successful, received $RATE PWR" >&3 + execute_contract '{"update_config":{"config":{"paused":false}}}' "$USER2_ADDR" + execute_contract '{"convert":{}}' "$USER2_ADDR" "1000000$SOURCE_DENOM" + PWR_BALANCE=$(query_json "Querying PWR balance after unpause" bank balances "$USER2_ADDR" | jq -r '.balances[] | select(.denom=="'"$TARGET_DENOM"'") | .amount') + assert [ "$PWR_BALANCE" == "8000000" ] - # TODO: Change config, Update Admin + run_tx "Migrating contract" wasm migrate "$CONTRACT_ADDR" "$CODE_ID" '{"migrate":{}}' --from "$USER_ADDR" + NOTE=$(docker exec "$CONTAINER_NAME" manifestd query tx "$TX_HASH" --node "$RPC" --output json | \ + jq -r '.events[] | select(.type=="wasm") | .attributes[] | select(.key=="note") | .value') + assert [ "$NOTE" == "already at latest version" ] } From d583da71631b63e1807d8d89ffd520408774addf Mon Sep 17 00:00:00 2001 From: "Felix C. Morency" <1102868+fmorency@users.noreply.github.com> Date: Wed, 29 Oct 2025 10:31:32 -0400 Subject: [PATCH 5/8] ci: simplify --- .github/workflows/ci.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0c46a4b..a1b97cb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,13 +73,7 @@ jobs: - name: Install wasm-opt run: cargo install wasm-opt --locked - name: WASM release build - run: RUSTFLAGS="-C link-arg=-s" cargo wasm --locked - - name: Optimize WASM artifacts - run: | - mkdir artifacts - for f in target/wasm32-unknown-unknown/release/*.wasm; do - wasm-opt -Os "$f" -o "artifacts/$(basename "$f")" - done + run: make build-opt - name: Generate checksums run: | cd artifacts From 49d2cfd39545c3646d129e9251b639aed1b0e1f2 Mon Sep 17 00:00:00 2001 From: "Felix C. Morency" <1102868+fmorency@users.noreply.github.com> Date: Wed, 29 Oct 2025 10:38:30 -0400 Subject: [PATCH 6/8] ci: e2e and fix coverage --- .github/workflows/ci.yml | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a1b97cb..111a580 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -102,12 +102,32 @@ jobs: sudo apt-get install -y protobuf-compiler protoc --version - name: Install cargo-tarpaulin - run: cargo +1.82.0 install cargo-tarpaulin + run: cargo +1.90.0 install cargo-tarpaulin - name: Run coverage - run: cargo +1.82.0 tarpaulin --workspace --all-features --all-targets --locked --out Xml --output-dir coverage + run: cargo +1.90.0 tarpaulin --workspace --all-features --all-targets --locked --out Xml --output-dir coverage - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} files: coverage/cobertura.xml fail_ci_if_error: true + + e2e: + name: E2E + runs-on: ubuntu-latest + needs: fmt_lint + steps: + - uses: actions/checkout@v4 + - name: Set up Docker Compose + uses: docker/setup-buildx-action@v2 + - name: Install test deps + run: | + sudo apt-get update + sudo apt-get install -y bats jq + bats --version + jq --version + - name: E2E test + run: bats e2e/tests/converter.bats + - name: Cleanup + if: always() + run: docker-compose -f e2e/docker-compose.yml down -v From f34163553a075deb4e92b4565999e3563492cbde Mon Sep 17 00:00:00 2001 From: "Felix C. Morency" <1102868+fmorency@users.noreply.github.com> Date: Wed, 29 Oct 2025 10:40:04 -0400 Subject: [PATCH 7/8] ci: install deps --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 111a580..558a5cf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,6 +72,8 @@ jobs: protoc --version - name: Install wasm-opt run: cargo install wasm-opt --locked + - name: Install cosmwasm-check + run: cargo install cosmwasm-check --locked - name: WASM release build run: make build-opt - name: Generate checksums From 02fd6a0c76da74950f251b061804d21008fefd7e Mon Sep 17 00:00:00 2001 From: "Felix C. Morency" <1102868+fmorency@users.noreply.github.com> Date: Wed, 29 Oct 2025 10:45:45 -0400 Subject: [PATCH 8/8] ci: . --- .github/workflows/ci.yml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 558a5cf..611bf4e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -120,6 +120,8 @@ jobs: needs: fmt_lint steps: - uses: actions/checkout@v4 + with: + submodules: recursive - name: Set up Docker Compose uses: docker/setup-buildx-action@v2 - name: Install test deps @@ -128,8 +130,22 @@ jobs: sudo apt-get install -y bats jq bats --version jq --version + - name: Install toolchain + uses: dtolnay/rust-toolchain@stable + with: + toolchain: ${{ env.RUST_VERSION }} + targets: wasm32-unknown-unknown + - name: Install protoc + run: | + sudo apt-get update + sudo apt-get install -y protobuf-compiler + protoc --version + - name: Install wasm-opt + run: cargo install wasm-opt --locked + - name: Install cosmwasm-check + run: cargo install cosmwasm-check --locked - name: E2E test run: bats e2e/tests/converter.bats - name: Cleanup if: always() - run: docker-compose -f e2e/docker-compose.yml down -v + run: docker compose -f e2e/docker-compose.yml down -v