This is a bunch of scripts for trying out CosmWasm contracts on a (local) blockchain node.
They work with CosmWasm v0.14.x. To set up a local node, you'll first need to check out the Nym validator source code, build it, and install it into your Go bin directory. Let's put it on your Desktop and install it:
cd ~/Desktop
git clone git@github.com:nymtech/nymd.git
cd nymd
git checkout v0.14.1
go build -o nymd -mod=readonly -tags "netgo,ledger" -ldflags '-X github.com/cosmos/cosmos-sdk/version.Name=nymd -X github.com/cosmos/cosmos-sdk/version.AppName=nymd -X github.com/CosmWasm/wasmd/app.NodeDir=.nymd -X github.com/cosmos/cosmos-sdk/version.Version=0.14.1 -X github.com/cosmos/cosmos-sdk/version.Commit=1920f80d181adbeaedac1eeea1c1c6e1704d3e49 -X github.com/CosmWasm/wasmd/app.Bech32Prefix=nym -X "github.com/cosmos/cosmos-sdk/version.BuildTags=netgo,ledger"' -trimpath ./cmd/wasmd
mv nymd $GOBIN
That will build and install the nymd binary in Go's bin directory; assuming that's in your $PATH, the commands below will work.
There's an examples folder inside the validator client, which will set up Cosmos-based accounts, then initialize and start a local Cosmos blockchain for development purposes. First, from the top-level nym directory:
cd clients/validator/examples
(Re)generate accounts by running the following. NOTE: it's destructive, it'll wipe your previous wasm accounts!
./reset_accounts.sh
Init the blockchain running with:
./init.sh
Start it with:
./start.sh
Congratulations! You now have a running CosmWasm blockchain that you can upload contract code into.
Using it in TypeScript
From the clients/validators/examples directory:
cd nym-driver-example
npm install
npx nodemon --exec ts-node ./index.ts --watch . --ext .ts
That will give you a running daemon that watches for changes in TypeScript files. It will execute a series of actions in the blockchain and explain what it's doing in the console, so you can see how things work.
Running ts-node on the index file would do basically the same thing, without a watcher.
Hitting the CosmWasm REST API directly:
Let's assume for the moment that the contract address you want to work on is nym10pyejy66429refv3g35g2t7am0was7ya69su6d.
Basic information about the contract can be retrieved from the Cosmos REST API's cosmwasm module.
The following routes are available:
http://localhost:1317/wasm/contract/nym10pyejy66429refv3g35g2t7am0was7ya69su6d http://localhost:1317/wasm/contract/nym10pyejy66429refv3g35g2t7am0was7ya69su6d/state http://localhost:1317/wasm/contract/nym10pyejy66429refv3g35g2t7am0was7ya69su6d/history
Querying active contracts
There are also two query routes, one for smart queries and one for raw queries based on a key:
http://localhost:1317/wasm/contract/nym10pyejy66429refv3g35g2t7am0was7ya69su6d/smart/{query} http://localhost:1317/wasm/contract/nym10pyejy66429refv3g35g2t7am0was7ya69su6d/raw/{key}
Let's try using a smart query to retrieve our topology. We know the above URL structure for a smart query. What do we put in the {query} parameter?
Our contract has a GetTopology {} query struct (which is annotated as snake_case in the contract code, and takes an empty struct as a value), so we can construct the following smart query param:
{ "get_topology": {} }
HOWEVER
We can't just send this:
http://localhost:1317/wasm/contract/nym10pyejy66429refv3g35g2t7am0was7ya69su6d/smart/{ "get_topology": {} }
Instead, we need to encode the param { "get_topology": {} } as Base64, and tell the REST API that this is how it's encoded by adding a query string encoding parameter, e.g. ?encoding=base64.
{ "get_topology": {} } in Base64 is eyAiZ2V0X3RvcG9sb2d5Ijoge30gfQ==. You can get this without making a driver program by going here:
https://onlineasciitools.com/convert-ascii-to-base64
(and in case you ever want to go the other way and decode some Base64 to verify what you've entered, go here: https://onlineasciitools.com/convert-base64-to-ascii)
The final query we end up with is:
This works if the topology is small.
It fails past a certain number of nodes (I'm not sure yet how many).
Note that output is once again in Base64, if you want to decode the output you'll need to do it.
I got back:
{"height":"14036","result":{"smart":"eyJtaXhfbm9kZV9ib25kcyI6W3siYW1vdW50IjpbeyJkZW5vbSI6InVueW0iLCJhbW91bnQiOiIxMDAwMDAwMDAwIn1dLCJvd25lciI6Im55bTFkcWRyZGplOTdmMjZ4aG5xbjk3c2FyMndyNWdqOWQ5NDZ2a3NqayIsIm1peF9ub2RlIjp7Imhvc3QiOiIxOTIuMTY4LjEuMSIsImxheWVyIjoxLCJsb2NhdGlvbiI6InRoZSBpbnRlcm5ldCIsInNwaGlueF9rZXkiOiJteXNwaGlueGtleSIsInZlcnNpb24iOiIwLjkuMiJ9fSx7ImFtb3VudCI6W3siZGVub20iOiJ1bnltIiwiYW1vdW50IjoiMTAwMDAwMDAwMCJ9XSwib3duZXIiOiJueW0xa2tqYTQ5N2NwYzc5ZGwyNDJ3bjdxbHBhOWU4cGxuNGw2dnpyeGMiLCJtaXhfbm9kZSI6eyJob3N0IjoiMTkyLjE2OC4xLjEiLCJsYXllciI6MSwibG9jYXRpb24iOiJ0aGUgaW50ZXJuZXQiLCJzcGhpbnhfa2V5IjoibXlzcGhpbnhrZXkiLCJ2ZXJzaW9uIjoiMC45LjIifX0seyJhbW91bnQiOlt7ImRlbm9tIjoidW55bSIsImFtb3VudCI6IjEwMDAwMDAwMDAifV0sIm93bmVyIjoibnltMWxxaGtwbDlzcHJ3c3A2M2RjNDZldTlrdm11Y2Nna243MzBqOXRsIiwibWl4X25vZGUiOnsiaG9zdCI6IjE5Mi4xNjguMS4xIiwibGF5ZXIiOjEsImxvY2F0aW9uIjoidGhlIGludGVybmV0Iiwic3BoaW54X2tleSI6Im15c3BoaW54a2V5IiwidmVyc2lvbiI6IjAuOS4yIn19LHsiYW1vdW50IjpbeyJkZW5vbSI6InVueW0iLCJhbW91bnQiOiIxMDAwMDAwMDAwIn1dLCJvd25lciI6Im55bTFueTlzY3J6OTJuYWM1bGEzcTc3bXRuZWd6Z2V6YzY1cnZrcGdhYSIsIm1peF9ub2RlIjp7Imhvc3QiOiIxOTIuMTY4LjEuMSIsImxheWVyIjoxLCJsb2NhdGlvbiI6InRoZSBpbnRlcm5ldCIsInNwaGlueF9rZXkiOiJteXNwaGlueGtleSIsInZlcnNpb24iOiIwLjkuMiJ9fV19"}}```
Decoding the big Base64 response string from `smart` gives:
{"mix_node_bonds":[{"amount":[{"denom":"unym","amount":"1000000000"}],"owner":"nym1dqdrdje97f26xhnqn97sar2wr5gj9d946vksjk","mix_node":{"host":"192.168.1.1","layer":1,"location":"the internet","sphinx_key":"mysphinxkey","version":"0.9.2"}},{"amount":[{"denom":"unym","amount":"1000000000"}],"owner":"nym1kkja497cpc79dl242wn7qlpa9e8pln4l6vzrxc","mix_node":{"host":"192.168.1.1","layer":1,"location":"the internet","sphinx_key":"mysphinxkey","version":"0.9.2"}},{"amount":[{"denom":"unym","amount":"1000000000"}],"owner":"nym1lqhkpl9sprwsp63dc46eu9kvmuccgkn730j9tl","mix_node":{"host":"192.168.1.1","layer":1,"location":"the internet","sphinx_key":"mysphinxkey","version":"0.9.2"}},{"amount":[{"denom":"unym","amount":"1000000000"}],"owner":"nym1ny9scrz92nac5la3q77mtnegzgezc65rvkpgaa","mix_node":{"host":"192.168.1.1","layer":1,"location":"the internet","sphinx_key":"mysphinxkey","version":"0.9.2"}}]}
Pretty cool!
{"mix_node_bonds":[{"amount":[{"denom":"unym","amount":"1000000000"}],"owner":"nym1054nh6a049r2nd73zjyfya6svrrwtwuwplr782","mix_node":{"host":"192.168.1.1","layer":1,"location":"the internet","sphinx_key":"mysphinxkey","version":"0.9.2"}},{"amount":[{"denom":"unym","amount":"1000000000"}],"owner":"nym1332slmq7uqvwrmxvt73zltz0tpdr0pmpge7jnu","mix_node":{"host":"192.168.1.1","layer":1,"location":"the internet","sphinx_key":"mysphinxkey","version":"0.9.2"}},{"amount":[{"denom":"unym","amount":"1000000000"}],"owner":"nym1a4utjp6ysqygt0hdstv9697a5y0ujsg9vvg7m4","mix_node":{"host":"192.168.1.1","layer":1,"location":"the internet","sphinx_key":"mysphinxkey","version":"0.9.2"}},{"amount":[{"denom":"unym","amount":"1000000000"}],"owner":"nym1dqdrdje97f26xhnqn97sar2wr5gj9d946vksjk","mix_node":{"host":"192.168.1.1","layer":1,"location":"the internet","sphinx_key":"mysphinxkey","version":"0.9.2"}},{"amount":[{"denom":"unym","amount":"1000000000"}],"owner":"nym1gem5crjkput2lg7wzpr3jdpver0spazf34fggu","mix_node":{"host":"192.168.1.1","layer":1,"location":"the internet","sphinx_key":"mysphinxkey","version":"0.9.2"}},{"amount":[{"denom":"unym","amount":"1000000000"}],"owner":"nym1kkja497cpc79dl242wn7qlpa9e8pln4l6vzrxc","mix_node":{"host":"192.168.1.1","layer":1,"location":"the internet","sphinx_key":"mysphinxkey","version":"0.9.2"}},{"amount":[{"denom":"unym","amount":"1000000000"}],"owner":"nym1l8yf0qaq39d5xvcmpyx0mhxckn77x8gz4phmjz","mix_node":{"host":"192.168.1.1","layer":1,"location":"the internet","sphinx_key":"mysphinxkey","version":"0.9.2"}},{"amount":[{"denom":"unym","amount":"1000000000"}],"owner":"nym1lctclx3jnskam7llxqdyw0mmfk24znn9lelram","mix_node":{"host":"192.168.1.1","layer":1,"location":"the internet","sphinx_key":"mysphinxkey","version":"0.9.2"}},{"amount":[{"denom":"unym","amount":"1000000000"}],"owner":"nym1lqhkpl9sprwsp63dc46eu9kvmuccgkn730j9tl","mix_node":{"host":"192.168.1.1","layer":1,"location":"the internet","sphinx_key":"mysphinxkey","version":"0.9.2"}},{"amount":[{"denom":"unym","amount":"1000000000"}],"owner":"nym1m2nl7z7adm8ualkkhmpv24fx5ny8c69c38fkjl","mix_node":{"host":"192.168.1.1","layer":1,"location":"the internet","sphinx_key":"mysphinxkey","version":"0.9.2"}},{"amount":[{"denom":"unym","amount":"1000000000"}],"owner":"nym1ny9scrz92nac5la3q77mtnegzgezc65rvkpgaa","mix_node":{"host":"192.168.1.1","layer":1,"location":"the internet","sphinx_key":"mysphinxkey","version":"0.9.2"}},{"amount":[{"denom":"unym","amount":"1000000000"}],"owner":"nym1q5jzekzm8p925hvmwpz0jasd3nzy4tz8h8l32m","mix_node":{"host":"192.168.1.1","layer":1,"location":"the internet","sphinx_key":"mysphinxkey","version":"0.9.2"}},{"amount":[{"denom":"unym","amount":"1000000000"}],"owner":"nym1tauxc4ezv55metq05706actwkptdhsh7qenej7","mix_node":{"host":"192.168.1.1","layer":1,"location":"the internet","sphinx_key":"mysphinxkey","version":"0.9.2"}},{"amount":[{"denom":"unym","amount":"1000000000"}],"owner":"nym1v7a3udzuq7tw3mt926rjtv6yc8pjr2pnmep450","mix_node":{"host":"192.168.1.1","layer":1,"location":"the internet","sphinx_key":"mysphinxkey","version":"0.9.2"}},{"amount":[{"denom":"unym","amount":"1000000000"}],"owner":"nym1vfmv8repca7tl39teqevrg4x0a6ed83t35g7vc","mix_node":{"host":"192.168.1.1","layer":1,"location":"the internet","sphinx_key":"mysphinxkey","version":"0.9.2"}},{"amount":[{"denom":"unym","amount":"1000000000"}],"owner":"nym1xjgyc24v7y7w3gk2kekdngj6zu4dm6ghsc32tu","mix_node":{"host":"192.168.1.1","layer":1,"location":"the internet","sphinx_key":"mysphinxkey","version":"0.9.2"}},{"amount":[{"denom":"unym","amount":"1000000000"}],"owner":"nym1y8dgzduv3lrepvaft44ek6mynjr2fytacs52wh","mix_node":{"host":"192.168.1.1","layer":1,"location":"the internet","sphinx_key":"mysphinxkey","version":"0.9.2"}},{"amount":[{"denom":"unym","amount":"1000000000"}],"owner":"nym1zrlutwux422ks3k06khd3ljtuhfvf9jwzpqgm9","mix_node":{"host":"192.168.1.1","layer":1,"location":"the internet","sphinx_key":"mysphinxkey","version":"0.9.2"}},{"amount":[{"denom":"unym","amount":"1000000000"}],"owner":"nym1zw9pdjtpdljhsjmghnz0dp3memcjgapmc3pmvh","mix_node":{"host":"192.168.1.1","layer":1,"location":"the internet","sphinx_key":"mysphinxkey","version":"0.9.2"}}]}```