CosmWasmClient Part 1: Reading

Simon Warta
CosmWasm
Published in
4 min readMar 6, 2020

In our Introduction to CosmWasm JS we talked about the concept of the library but did not yet see any code. In Adding CosmWasm to the Neuma multichain wallet we used any early version of CosmWasmClient under the hood. Today we’ll cover everything you need to know about this class.

Photo by Rémi Walle on Unsplash

Setting up the REPL

Everything we are doing here can be executed from any Node.js script, web app or browser extension. But for the demo, we’ll use a REPL (read–eval–print loop) as our playground. You can install the REPL to your local environment, but the quickest way to start the REPL is:

npx @cosmwasm/cli

which will welcome you with a screen like this:

@cosmwasm/cli session started

This is a REPL that works very similar to what you get by just typing node. Core differences are integrated TypeScript support and a number of automatic imports specific to CosmWasm. The amount of imports probably looks overwhelming but don’t worry. The REPL is designed to do all kinds of development tasks and most of the imports you’ll never need to use directly. For now, we just look into one class from @cosmwasm/sdk.

CosmWasmClient

CosmWasmClient is the high level entry point to connect to a blockchain with the CosmWasm module integrated, like e.g. the CosmWasm demonet. And it goes like this:

>> const client = new CosmWasmClient("https://lcd.demo-071.cosmwasm.com/")
undefined
>> await client.getChainId()
'testing'
>> await client.getHeight()
35266
>> await client.getBlock()
{
id: 'FBEA10E503395FE950FE6E685880DD58BC1BE01B2FA2C02E0CDF7CA53B57A1AB',
header: {
version: { block: '10', app: '0' },
time: '2020-03-06T09:34:06.932352209Z',
height: 35268,
chainId: 'testing'
},
txs: []
}

With those four commands you instantiated a client for a given endpoint, queried the chain ID, the height and the latest block. When called with a height argument, you get a specific block.

>> await client.getBlock(2811)
{
id: 'FD648FD18A2E9394097FE89343C9F1AA01380A34B569177789B608AC743146BF',
header: {
version: { block: '10', app: '0' },
time: '2020-03-04T12:14:03.58338804Z',
height: 2811,
chainId: 'testing'
},
txs: [
Uint8Array [
230, 1, 40, 40, 22, 169, 10, 79, 122, 94, 123, 224,
10, 20, 195, 135, 14, 74, 97, 17, 122, 250, 130, 153,
31, 64, 47, 167, 122, 109, 145, 249, 232, 111, 18, 20,
100, 179, 132, 115, 145, 240, 118, 218, 123, 209, 137, 92,
54, 133, 79, 59, 90, 34, 110, 220, 26, 29, 123, 34,
114, 101, 103, 105, 115, 116, 101, 114, 34, 58, 123, 34,
110, 97, 109, 101, 34, 58, 34, 104, 101, 108, 108, 111,
34, 125, 125, 18, 19, 10, 13, 10, 5, 117, 99, 111,
115, 109, 18, 4,
... 132 more items
]
]
}

This block includes a transaction, which is returned in binary format — hard to inspect. Let’s try transaction search for the same block height:

>> await client.searchTx({ height: 2811 })
[
{
height: 2811,
hash: 'C77D63EAD29935C1EBB9CF6F38C28DAA28C9CCCBABDD3000D7049B46C8BA4238',
rawLog: '[{"msg_index":0,"log":"","events":[{"type":"message","attributes":[{"key":"action","value":"execute"},{"key":"module","value":"wasm"},{"key":"signer","value":"cosmos1cwrsujnpz9a04q5eraqzlfm6dkgln6r05pyfmx"},{"key":"contract_address","value":"cosmos1vjecguu37pmd577339wrdp208ddzymkudc46zj"}]}]}]',
logs: [ [Object] ],
tx: { type: 'cosmos-sdk/StdTx', value: [Object] },
timestamp: '2020-03-04T12:14:03Z'
}
]

Better. We see the transaction in the tx property, but it’s value is not printed. Let’s dig in:

>> const results = await client.searchTx({ height: 2811 })
undefined
>> results[0].tx.value
{
msg: [ { type: 'wasm/execute', value: [Object] } ],
fee: { amount: [ [Object] ], gas: '200000' },
signatures: [
{
pub_key: [Object],
signature: 'bjR5M7VFsfrj10pbfIsgYrUXs+20eEdFWpFIhvGwKqhyG+6A9I+u/Bm6O3tjcHLtteEHGRBJ4Cn3N3ZgYWMfJA=='
}
],
memo: 'Buying my name'
}
>> results[0].tx.value.msg[0]
{
type: 'wasm/execute',
value: {
sender: 'cosmos1cwrsujnpz9a04q5eraqzlfm6dkgln6r05pyfmx',
contract: 'cosmos1vjecguu37pmd577339wrdp208ddzymkudc46zj',
msg: { register: [Object] },
sent_funds: []
}
}

The message of type wasm/execute is a Cosmos SDK message containing a smart contract address and a message that was sent to the contract, which is:

>> results[0].tx.value.msg[0].value.msg
{ register: { name: 'hello' } }

Codes, Contracts and Queries

We can get a list of all codes (i.e. WebAssembly bytecodes), all instantiations of a given code and all information for a contract instance:

>> await client.getCodes()
[
{
id: 1,
creator: 'cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6',
checksum: 'aff8c8873d79d2153a8b9066a0683fec3c903669267eb806ffa831dcd4b3daae',
source: 'https://crates.io/api/v1/crates/cw-erc20/0.2.0/download',
builder: 'confio/cosmwasm-opt:0.7.0'
},
{
id: 2,
creator: 'cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6',
checksum: 'd5dde423d321f7d3793a9b1667d06ac86c7f57dfbd2534a9c790963e1c2955ed',
source: 'https://crates.io/api/v1/crates/cw-nameservice/0.2.0/download',
builder: 'confio/cosmwasm-opt:0.7.0'
}
]
>> await client.getContracts(2)
[
{
address: 'cosmos1vjecguu37pmd577339wrdp208ddzymkudc46zj',
codeId: 2,
creator: 'cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6',
label: 'Free'
},
{
address: 'cosmos1ym5m5dw7pttft5w430nxx6uat8f84ck4algmhg',
codeId: 2,
creator: 'cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6',
label: 'Luxury'
}
]
>> await client.getAccount("cosmos1ym5m5dw7pttft5w430nxx6uat8f84ck4algmhg")
{
address: 'cosmos1ym5m5dw7pttft5w430nxx6uat8f84ck4algmhg',
balance: [ { denom: 'ucosm', amount: '8000000' } ],
pubkey: undefined,
accountNumber: 14,
sequence: 0
}

What we are seeing in the last call is a contract that owns 8 COSM tokens. The nameservice contract (Code #2) has a smart query for resolving names (that is specified in a scary looking JSON schema), which can be executed like this:

>> await client.queryContractSmart("cosmos1ym5m5dw7pttft5w430nxx6uat8f84ck4algmhg", { "resolverecord": { "name": "hello" }})
Uint8Array [
123, 34, 97, 100, 100, 114, 101, 115, 115, 34,
58, 34, 99, 111, 115, 109, 111, 115, 49, 55,
113, 103, 100, 120, 121, 116, 103, 121, 103, 122,
53, 52, 101, 116, 112, 113, 52, 110, 107, 109,
112, 116, 102, 108, 53, 99, 51, 114, 108, 56,
122, 113, 119, 57, 99, 97, 117, 34, 125
]

For this contract, the resulting binary data is some JSON, which we can look into:

>> const data = await client.queryContractSmart("cosmos1ym5m5dw7pttft5w430nxx6uat8f84ck4algmhg", { "resolverecord": { "name": "hello" }})
undefined
>> JSON.parse(fromUtf8(data))
{ address: 'cosmos17qgdxytgygz54etpq4nkmptfl5c3rl8zqw9cau' }

We’ve seen how to use CosmWasmClient to interact with a blockchain in read only mode. Stay tuned to learn how CosmWasmClient can be used to upload, instantiate and execute smart contracts.

Updated 2020–04–17: change demonet URL from https://lcd.demo-07.cosmwasm.com/ to https://lcd.demo-071.cosmwasm.com/

--

--

Simon Warta
CosmWasm

Building CosmWasm and CosmJS at Confio | Ex IOV | Co-Founder of Kullo | Board member prolina Foundation