Merge pull request #226 from CosmWasm/improve-readme
Improve main README
This commit is contained in:
commit
b88646392c
62
README.md
62
README.md
@ -1,12 +1,67 @@
|
||||
# CosmJS
|
||||
|
||||
This is a JavaScript/TypeScript client-side binding to [wasmd](https://github.com/cosmwasm/wasmd), a sample blockchain for the [cosmwasm](https://github.com/confio/cosmwasm) smart contracting platform.
|
||||
CosmJS is the Swiss Army knife to power JavaScript based client solutions
|
||||
ranging from Web apps/explorers over browser extensions to server-side clients
|
||||
like faucets/scrapers in the Cosmos ecosystem.
|
||||
|
||||
"Cosm" is short for Cosmos and "JS" is short for _runs everywhere_ – we actually
|
||||
develop in TypeScript.
|
||||
|
||||
## Packages
|
||||
|
||||
CosmJS is a library that consists of many smaller npm packages within the
|
||||
[@cosmjs namespace](https://www.npmjs.com/org/cosmjs), a so called monorepo.
|
||||
Here are some of them to get an idea:
|
||||
|
||||
| Package | Description | Latest |
|
||||
| ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
||||
| [@cosmjs/sdk38](packages/sdk38) | A client library for the Cosmos SDK 0.38 | [](https://www.npmjs.com/package/@cosmjs/sdk38) |
|
||||
| [@cosmjs/faucet](packages/faucet) | A faucet application for node.js | [](https://www.npmjs.com/package/@cosmjs/faucet) |
|
||||
| [@cosmjs/cosmwasm](packages/cosmwasm) | Client for chains with the CosmWasm module enabled | [](https://www.npmjs.com/package/@cosmjs/cosmwasm) |
|
||||
| [@cosmjs/crypto](packages/crypto) | Cryptography for blockchain projects, e.g. hashing (SHA-2, Keccak256, Ripemd160), signing (secp256k1, ed25519), HD key derivation (BIPO39, SLIP-0010), KDFs and symmetric encryption for key storage (PBKDF2, Argon2, XChaCha20Poly1305) | [](https://www.npmjs.com/package/@cosmjs/crypto) |
|
||||
| [@cosmjs/encoding](packages/encoding) | Encoding helpers for blockchain projects | [](https://www.npmjs.com/package/@cosmjs/encoding) |
|
||||
| [@cosmjs/math](packages/math) | Safe integers; decimals for handling financial amounts | [](https://www.npmjs.com/package/@cosmjs/math) |
|
||||
|
||||
### Modularity
|
||||
|
||||
We're pretty proud of the modularity and a clean dependency tree in this
|
||||
monorepo. This ensures software quality on our side and lets users pick exactly
|
||||
what they need. Here you see how everything fits together (every item is a npm
|
||||
package; right depends on left):
|
||||
|
||||

|
||||
|
||||
<!--
|
||||
Build with depsight (https://github.com/webmaster128/depsight), using:
|
||||
|
||||
from_npm ~/cosmjs | depsight --exclude cosmjs-monorepo-root --format svg --output - | inkscape --pipe --export-width 3000 --export-filename cosmjs-tree.png
|
||||
|
||||
optipng cosmjs-tree.png
|
||||
-->
|
||||
|
||||
### Supported JS environments
|
||||
|
||||
Currently the codebase supports the following runtime environments:
|
||||
|
||||
1. Node.js 10+
|
||||
2. Modern browsers (Chromium/Firefox/Safari, no Internet Explorer or
|
||||
[Edge Spartan](https://en.wikipedia.org/wiki/Microsoft_Edge#Development))
|
||||
3. Browser extensions (Chromium/Firefox)
|
||||
|
||||
Our current JavaScript target standard is ES2017, giving us native async/await
|
||||
support. We use WebAssembly to implement certain cryptographic functions.
|
||||
|
||||
We're happy to adjust this list according to users' needs as long as you don't
|
||||
ask for Internet Explorer support. If your environment does not support Wasm, we
|
||||
can work on a solution with swapable implementations.
|
||||
|
||||
## Development
|
||||
|
||||
Requires Node 10+. For best results, use yarn. The basic commands are:
|
||||
|
||||
```sh
|
||||
yarn install
|
||||
|
||||
# compile the code
|
||||
yarn build
|
||||
# run unit tests
|
||||
@ -18,7 +73,10 @@ yarn format && yarn lint
|
||||
|
||||
### Integration tests
|
||||
|
||||
To run the entire test suite, you need to run a local blockchain to test against. This should work on any Linux/OSX system with docker installed.
|
||||
To run the entire test suite, you need to run a local blockchain to test
|
||||
against. We use [wasmd](https://github.com/CosmWasm/wasmd) for both CosmWasm
|
||||
tests and as a generic Cosmos SDK 0.38 blockchain. This should work on any
|
||||
Linux/OSX system with docker installed:
|
||||
|
||||
```sh
|
||||
./scripts/wasmd/start.sh
|
||||
|
||||
BIN
docs/cosmjs-tree.png
Normal file
BIN
docs/cosmjs-tree.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 266 KiB |
@ -25,7 +25,7 @@
|
||||
],
|
||||
"scripts": {
|
||||
"format": "lerna run format",
|
||||
"format-text": "prettier --write --prose-wrap always --print-width 80 \"./*.md\" \"./docs/**/*.md\" \"./scripts/**/*.{json,md}\" && lerna run format-text",
|
||||
"format-text": "prettier --write --prose-wrap always --print-width 80 \"./*.md\" && lerna run format-text",
|
||||
"lint": "lerna run lint",
|
||||
"lint-fix": "lerna run lint-fix",
|
||||
"test": "lerna run test",
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
# Using the Mask
|
||||
|
||||
This assumes you have already run through the sample in the [README](./README.md).
|
||||
And have an initialized account. You can use any connect method (sharing with cli,
|
||||
customize blockchain) if you want. We will show uploading mask and using it
|
||||
on the Demo Net.
|
||||
This assumes you have already run through the sample in the
|
||||
[README](./README.md). And have an initialized account. You can use any connect
|
||||
method (sharing with cli, customize blockchain) if you want. We will show
|
||||
uploading mask and using it on the Demo Net.
|
||||
|
||||
Start with `./bin/cosmwasm-cli --init examples/helpers.ts examples/mask.ts`
|
||||
(note the addition of `examples/mask.ts`)
|
||||
@ -21,10 +21,12 @@ address;
|
||||
client.getAccount();
|
||||
```
|
||||
|
||||
We will use [mask v0.1.0](https://github.com/CosmWasm/cosmwasm-examples/tree/mask-0.1.0/mask),
|
||||
the hash is [defined here](https://github.com/CosmWasm/cosmwasm-examples/blob/mask-0.1.0/mask/hash.txt):
|
||||
`1f50bbff503fd9c7bfe713bbf42b309cf88ef299fa76e0242051c9a7e25649a3`. The following will check if
|
||||
it is already uploaded:
|
||||
We will use
|
||||
[mask v0.1.0](https://github.com/CosmWasm/cosmwasm-examples/tree/mask-0.1.0/mask),
|
||||
the hash is
|
||||
[defined here](https://github.com/CosmWasm/cosmwasm-examples/blob/mask-0.1.0/mask/hash.txt):
|
||||
`1f50bbff503fd9c7bfe713bbf42b309cf88ef299fa76e0242051c9a7e25649a3`. The
|
||||
following will check if it is already uploaded:
|
||||
|
||||
```ts
|
||||
const hash = "1f50bbff503fd9c7bfe713bbf42b309cf88ef299fa76e0242051c9a7e25649a3";
|
||||
@ -35,7 +37,8 @@ If it is not uploaded, we will upload it:
|
||||
|
||||
```ts
|
||||
// Either download the code
|
||||
const wasmUrl = "https://github.com/CosmWasm/cosmwasm-examples/blob/mask-0.1.0/mask/contract.wasm?raw=true";
|
||||
const wasmUrl =
|
||||
"https://github.com/CosmWasm/cosmwasm-examples/blob/mask-0.1.0/mask/contract.wasm?raw=true";
|
||||
const wasm = await downloadWasm(wasmUrl);
|
||||
|
||||
// Or load from local file
|
||||
@ -64,11 +67,13 @@ const mask = maskResp.contractAddress;
|
||||
|
||||
// You can also find the contractAddress later (in a future session), like:
|
||||
const contracts = await client.getContracts(codeId);
|
||||
const mask = contracts.filter((x) => x.label == "My Mask").map((x) => x.address)[0];
|
||||
const mask = contracts
|
||||
.filter((x) => x.label == "My Mask")
|
||||
.map((x) => x.address)[0];
|
||||
```
|
||||
|
||||
Now, let's use the mask. To do so, we need to load it up with some tokens
|
||||
(both native and ERC20 - from the contract you deployed last time).
|
||||
Now, let's use the mask. To do so, we need to load it up with some tokens (both
|
||||
native and ERC20 - from the contract you deployed last time).
|
||||
|
||||
```ts
|
||||
client.sendTokens(mask, [{ amount: "500000", denom: "ucosm" }]);
|
||||
@ -98,7 +103,9 @@ client.getAccount(rand);
|
||||
client.getAccount(mask);
|
||||
|
||||
const callSend: HandleMsg = {
|
||||
reflectmsg: { msgs: [sendMsg(mask, rand, [{ amount: "80000", denom: "ucosm" }])] },
|
||||
reflectmsg: {
|
||||
msgs: [sendMsg(mask, rand, [{ amount: "80000", denom: "ucosm" }])],
|
||||
},
|
||||
};
|
||||
client.execute(mask, callSend);
|
||||
client.getAccount(rand);
|
||||
@ -114,7 +121,11 @@ smartQuery(client, foo, { balance: { address: rand } });
|
||||
smartQuery(client, foo, { balance: { address: mask } });
|
||||
|
||||
const callContract: HandleMsg = {
|
||||
reflectmsg: { msgs: [contractMsg(foo, { transfer: { amount: "80000", recipient: rand } })] },
|
||||
reflectmsg: {
|
||||
msgs: [
|
||||
contractMsg(foo, { transfer: { amount: "80000", recipient: rand } }),
|
||||
],
|
||||
},
|
||||
};
|
||||
client.execute(mask, callContract);
|
||||
smartQuery(client, foo, { balance: { address: rand } });
|
||||
@ -123,10 +134,11 @@ smartQuery(client, foo, { balance: { address: mask } });
|
||||
|
||||
### Staking via OpaqueMsg
|
||||
|
||||
And now... let's use `OpaqueMsg` to call into native blockchain messages.
|
||||
Here we will trigger a staking command. This is an "opaque" command, so neither cosmwams-js
|
||||
nor the cosmwasm contract understands it. It is passed verbatim from the client to
|
||||
the wasmd blockchain (reflected by mask, so using the mask address).
|
||||
And now... let's use `OpaqueMsg` to call into native blockchain messages. Here
|
||||
we will trigger a staking command. This is an "opaque" command, so neither
|
||||
cosmwams-js nor the cosmwasm contract understands it. It is passed verbatim from
|
||||
the client to the wasmd blockchain (reflected by mask, so using the mask
|
||||
address).
|
||||
|
||||
To view this properly, we will have to use the cli tooling:
|
||||
|
||||
@ -141,8 +153,8 @@ wasmcli query staking delegations-to cosmosvaloper1e8gslcu2u2p5zp9rgj8alz4q3lt6h
|
||||
wasmcli tx staking delegate cosmosvaloper1e8gslcu2u2p5zp9rgj8alz4q3lt6hvywqppf23 300000ustake --generate-only --chain-id testing
|
||||
```
|
||||
|
||||
To create such a message, we need to produce the amino json encoding of a staking message.
|
||||
That does involve a bit of investigation, but looks like:
|
||||
To create such a message, we need to produce the amino json encoding of a
|
||||
staking message. That does involve a bit of investigation, but looks like:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -158,7 +170,8 @@ That does involve a bit of investigation, but looks like:
|
||||
}
|
||||
```
|
||||
|
||||
Run the following (taking the operator address for the validator from the cli output)
|
||||
Run the following (taking the operator address for the validator from the cli
|
||||
output)
|
||||
|
||||
```ts
|
||||
mask
|
||||
@ -199,17 +212,20 @@ wasmcli query staking delegations-to cosmosvaloper1e8gslcu2u2p5zp9rgj8alz4q3lt6h
|
||||
wasmcli query staking delegations <mask address>
|
||||
```
|
||||
|
||||
The opaqueMsg style is a bit more tricky as it places the burden of transaction construction upon the
|
||||
user (you). However, it does allow you to call into any native module in the blockchain.
|
||||
We plan to add custom types for some popular native messages to make this binding simpler,
|
||||
and also allow these to be triggered by internal contract logic (they cannot form opaque messages,
|
||||
but rather just relay opaque messages formed by the clients).
|
||||
The opaqueMsg style is a bit more tricky as it places the burden of transaction
|
||||
construction upon the user (you). However, it does allow you to call into any
|
||||
native module in the blockchain. We plan to add custom types for some popular
|
||||
native messages to make this binding simpler, and also allow these to be
|
||||
triggered by internal contract logic (they cannot form opaque messages, but
|
||||
rather just relay opaque messages formed by the clients).
|
||||
|
||||
## Transfering Owner
|
||||
|
||||
Happy hacking using the mask contract. And to make this a bit more interesting, note that you can transfer
|
||||
control of this mask. By transfering ownership, we transfer control of our `ucosm` native , our `FOO` erc20 token,
|
||||
and our open staking position in one fell swoop, without the other modules/contracts being aware of the change.
|
||||
Happy hacking using the mask contract. And to make this a bit more interesting,
|
||||
note that you can transfer control of this mask. By transfering ownership, we
|
||||
transfer control of our `ucosm` native , our `FOO` erc20 token, and our open
|
||||
staking position in one fell swoop, without the other modules/contracts being
|
||||
aware of the change.
|
||||
|
||||
```ts
|
||||
const aliceMnem = loadOrCreateMnemonic("other.key");
|
||||
@ -231,13 +247,18 @@ client.execute(mask, transferMsg);
|
||||
smartQuery(client, mask, query);
|
||||
```
|
||||
|
||||
From now own, alice can control the mask, not me.... And she can extract the erc20 tokens or anything else the mask controls
|
||||
From now own, alice can control the mask, not me.... And she can extract the
|
||||
erc20 tokens or anything else the mask controls
|
||||
|
||||
```ts
|
||||
smartQuery(client, foo, { balance: { address: alice } });
|
||||
|
||||
const withdraw: HandleMsg = {
|
||||
reflectmsg: { msgs: [contractMsg(foo, { transfer: { amount: "80000", recipient: alice } })] },
|
||||
reflectmsg: {
|
||||
msgs: [
|
||||
contractMsg(foo, { transfer: { amount: "80000", recipient: alice } }),
|
||||
],
|
||||
},
|
||||
};
|
||||
// this will error (me)
|
||||
client.execute(mask, withdraw);
|
||||
@ -246,7 +267,8 @@ aliceClient.execute(mask, withdraw);
|
||||
smartQuery(client, foo, { balance: { address: alice } });
|
||||
```
|
||||
|
||||
Please explore the use-cases of the Mask. More than a production-ready contract (which it may be),
|
||||
it is designed to be a tool for devs to explore the potential of composition and re-dispatching messages.
|
||||
See what you can do here, then use this knowledge to build your own contract that calls other contracts.
|
||||
This is working today, you just have to return the right messages from `handle`.
|
||||
Please explore the use-cases of the Mask. More than a production-ready contract
|
||||
(which it may be), it is designed to be a tool for devs to explore the potential
|
||||
of composition and re-dispatching messages. See what you can do here, then use
|
||||
this knowledge to build your own contract that calls other contracts. This is
|
||||
working today, you just have to return the right messages from `handle`.
|
||||
|
||||
@ -45,7 +45,9 @@ $ cosmwasm-cli
|
||||
|
||||
```ts
|
||||
// Get account information
|
||||
const { account_number, sequence } = (await client.authAccounts(faucetAddress)).result.value;
|
||||
const { account_number, sequence } = (
|
||||
await client.authAccounts(faucetAddress)
|
||||
).result.value;
|
||||
|
||||
// Craft a send transaction
|
||||
const emptyAddress = Bech32.encode("cosmos", Random.getBytes(20));
|
||||
@ -84,13 +86,15 @@ const postResult = await client.postTx(signedTx);
|
||||
|
||||
## Extended helpers
|
||||
|
||||
The above code shows you the use of the API and various objects and is a great way to learn
|
||||
how to embed cosmjs into your project. However, if you just want a cli to perform some
|
||||
quick queries on a chain, you can use an extended set of helpers:
|
||||
The above code shows you the use of the API and various objects and is a great
|
||||
way to learn how to embed cosmjs into your project. However, if you just want a
|
||||
cli to perform some quick queries on a chain, you can use an extended set of
|
||||
helpers:
|
||||
|
||||
Start with `./bin/cosmwasm-cli --init examples/helpers.ts`
|
||||
|
||||
(This points to the Demonet at https://lcd.demo-08.cosmwasm.com for ease of use. Other networks, look below)
|
||||
(This points to the Demonet at https://lcd.demo-08.cosmwasm.com for ease of use.
|
||||
Other networks, look below)
|
||||
|
||||
Setup Account:
|
||||
|
||||
@ -143,9 +147,10 @@ const fooAddr = foo.contractAddress;
|
||||
// we can also find this another way...
|
||||
const fooAddr2 = await client
|
||||
.getContracts(1)
|
||||
.then((contracts) => contracts.filter((x) => x.label == "FOO").map((x) => x.address)[0])[
|
||||
(fooAddr, fooAddr2)
|
||||
];
|
||||
.then(
|
||||
(contracts) =>
|
||||
contracts.filter((x) => x.label == "FOO").map((x) => x.address)[0],
|
||||
)[(fooAddr, fooAddr2)];
|
||||
|
||||
// now we have some cash
|
||||
smartQuery(client, fooAddr, { balance: { address } });
|
||||
@ -166,17 +171,19 @@ Or just send tokens:
|
||||
```ts
|
||||
client.getAccount(rcpt);
|
||||
|
||||
const sent = await client.sendTokens(rcpt, [{ amount: "1234", denom: "ucosm" }]);
|
||||
const sent = await client.sendTokens(rcpt, [
|
||||
{ amount: "1234", denom: "ucosm" },
|
||||
]);
|
||||
sent;
|
||||
foo.logs[0].events[0];
|
||||
```
|
||||
|
||||
### Use Custom Network
|
||||
|
||||
All the network info can be configured inside the last argument to connect.
|
||||
To see how to connect to the Regen Testnet, try this. (Note you need to use `.editor`
|
||||
in the repl to allow multi-line commands. Alternative is to place entire `regenOptions`
|
||||
on one line.
|
||||
All the network info can be configured inside the last argument to connect. To
|
||||
see how to connect to the Regen Testnet, try this. (Note you need to use
|
||||
`.editor` in the repl to allow multi-line commands. Alternative is to place
|
||||
entire `regenOptions` on one line.
|
||||
|
||||
Run `./bin/cosmwasm-cli --init examples/helpers.ts`
|
||||
|
||||
@ -202,24 +209,28 @@ client.getAccount("xrn:1pdfr7xuckj6lhdphdde6peres9ufwgpsv87mag")
|
||||
client.getAccount()
|
||||
```
|
||||
|
||||
Hit the faucet with your address (in browser): https://regen.vitwit.com/faucet then continue in node
|
||||
Hit the faucet with your address (in browser): https://regen.vitwit.com/faucet
|
||||
then continue in node
|
||||
|
||||
```ts
|
||||
// should have tokens now
|
||||
client.getAccount();
|
||||
```
|
||||
|
||||
At this point you can continue all the other behaviors from above, looking at codes, etc.
|
||||
Do note that the ERC contract is code `5` on this network (instead of `1` above).
|
||||
At this point you can continue all the other behaviors from above, looking at
|
||||
codes, etc. Do note that the ERC contract is code `5` on this network (instead
|
||||
of `1` above).
|
||||
|
||||
### Importing keys from `wasmcli`
|
||||
|
||||
If you are using the go commands and have tokens there, you may want to reuse the same account.
|
||||
(If you don't know what this is, just skip this section). You can reuse the mnemonic between the
|
||||
Go tooling and the Node.js tooling, but this violates all security protocols - only use this for
|
||||
testnets. In the future we will offer proper encrypted key management for cosmjs.
|
||||
If you are using the go commands and have tokens there, you may want to reuse
|
||||
the same account. (If you don't know what this is, just skip this section). You
|
||||
can reuse the mnemonic between the Go tooling and the Node.js tooling, but this
|
||||
violates all security protocols - only use this for testnets. In the future we
|
||||
will offer proper encrypted key management for cosmjs.
|
||||
|
||||
(You can replace `wasmcli` with `xrncli` and use `regenOptions` if you wish to use that testnet)
|
||||
(You can replace `wasmcli` with `xrncli` and use `regenOptions` if you wish to
|
||||
use that testnet)
|
||||
|
||||
Create a new key - note mnemonic and address
|
||||
|
||||
@ -257,16 +268,16 @@ const { address, client } = await connect(mnemonic, regenOptions);
|
||||
address;
|
||||
```
|
||||
|
||||
Once you have access to the same key as in the cli, you can use those tokens to play with contracts.
|
||||
Once you have access to the same key as in the cli, you can use those tokens to
|
||||
play with contracts.
|
||||
|
||||
## Diving into Contracts
|
||||
|
||||
Check out the [mask documentation](./MASK.md) to view how to use some custom helpers to upload code and use non-trivial contracts
|
||||
with proper types.
|
||||
Check out the [mask documentation](./MASK.md) to view how to use some custom
|
||||
helpers to upload code and use non-trivial contracts with proper types.
|
||||
|
||||
## License
|
||||
|
||||
This package is part of the cosmjs repository, licensed under the Apache
|
||||
License 2.0 (see
|
||||
[NOTICE](https://github.com/CosmWasm/cosmjs/blob/master/NOTICE) and
|
||||
This package is part of the cosmjs repository, licensed under the Apache License
|
||||
2.0 (see [NOTICE](https://github.com/CosmWasm/cosmjs/blob/master/NOTICE) and
|
||||
[LICENSE](https://github.com/CosmWasm/cosmjs/blob/master/LICENSE)).
|
||||
|
||||
@ -10,7 +10,6 @@ imported outside of CosmJS based applications.
|
||||
|
||||
## License
|
||||
|
||||
This package is part of the cosmjs repository, licensed under the Apache
|
||||
License 2.0 (see
|
||||
[NOTICE](https://github.com/CosmWasm/cosmjs/blob/master/NOTICE) and
|
||||
This package is part of the cosmjs repository, licensed under the Apache License
|
||||
2.0 (see [NOTICE](https://github.com/CosmWasm/cosmjs/blob/master/NOTICE) and
|
||||
[LICENSE](https://github.com/CosmWasm/cosmjs/blob/master/LICENSE)).
|
||||
|
||||
@ -18,7 +18,6 @@ on invalid input.
|
||||
|
||||
## License
|
||||
|
||||
This package is part of the cosmjs repository, licensed under the Apache
|
||||
License 2.0 (see
|
||||
[NOTICE](https://github.com/CosmWasm/cosmjs/blob/master/NOTICE) and
|
||||
This package is part of the cosmjs repository, licensed under the Apache License
|
||||
2.0 (see [NOTICE](https://github.com/CosmWasm/cosmjs/blob/master/NOTICE) and
|
||||
[LICENSE](https://github.com/CosmWasm/cosmjs/blob/master/LICENSE)).
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
|
||||
## License
|
||||
|
||||
This package is part of the cosmjs repository, licensed under the Apache
|
||||
License 2.0 (see
|
||||
[NOTICE](https://github.com/CosmWasm/cosmjs/blob/master/NOTICE) and
|
||||
This package is part of the cosmjs repository, licensed under the Apache License
|
||||
2.0 (see [NOTICE](https://github.com/CosmWasm/cosmjs/blob/master/NOTICE) and
|
||||
[LICENSE](https://github.com/CosmWasm/cosmjs/blob/master/LICENSE)).
|
||||
|
||||
@ -2,12 +2,11 @@
|
||||
|
||||
[](https://www.npmjs.com/package/@cosmjs/utils)
|
||||
|
||||
Utility functions independent of blockchain applications. Primarily used for testing
|
||||
but stuff like `sleep` can also be useful at runtime.
|
||||
Utility functions independent of blockchain applications. Primarily used for
|
||||
testing but stuff like `sleep` can also be useful at runtime.
|
||||
|
||||
## License
|
||||
|
||||
This package is part of the cosmjs repository, licensed under the Apache
|
||||
License 2.0 (see
|
||||
[NOTICE](https://github.com/CosmWasm/cosmjs/blob/master/NOTICE) and
|
||||
This package is part of the cosmjs repository, licensed under the Apache License
|
||||
2.0 (see [NOTICE](https://github.com/CosmWasm/cosmjs/blob/master/NOTICE) and
|
||||
[LICENSE](https://github.com/CosmWasm/cosmjs/blob/master/LICENSE)).
|
||||
|
||||
Loading…
Reference in New Issue
Block a user