diff --git a/README.md b/README.md index 07674129..435af3ec 100644 --- a/README.md +++ b/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 | [![npm version](https://img.shields.io/npm/v/@cosmjs/sdk38.svg)](https://www.npmjs.com/package/@cosmjs/sdk38) | +| [@cosmjs/faucet](packages/faucet) | A faucet application for node.js | [![npm version](https://img.shields.io/npm/v/@cosmjs/faucet.svg)](https://www.npmjs.com/package/@cosmjs/faucet) | +| [@cosmjs/cosmwasm](packages/cosmwasm) | Client for chains with the CosmWasm module enabled | [![npm version](https://img.shields.io/npm/v/@cosmjs/cosmwasm.svg)](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) | [![npm version](https://img.shields.io/npm/v/@cosmjs/crypto.svg)](https://www.npmjs.com/package/@cosmjs/crypto) | +| [@cosmjs/encoding](packages/encoding) | Encoding helpers for blockchain projects | [![npm version](https://img.shields.io/npm/v/@cosmjs/encoding.svg)](https://www.npmjs.com/package/@cosmjs/encoding) | +| [@cosmjs/math](packages/math) | Safe integers; decimals for handling financial amounts | [![npm version](https://img.shields.io/npm/v/@cosmjs/math.svg)](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): + +![CosmJS dependency tree](docs/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 diff --git a/docs/cosmjs-tree.png b/docs/cosmjs-tree.png new file mode 100644 index 00000000..6a388c40 Binary files /dev/null and b/docs/cosmjs-tree.png differ diff --git a/package.json b/package.json index 0370801b..4fd98df1 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/packages/cli/MASK.md b/packages/cli/MASK.md index f63d9772..68cd6b73 100644 --- a/packages/cli/MASK.md +++ b/packages/cli/MASK.md @@ -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 ``` -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`. diff --git a/packages/cli/README.md b/packages/cli/README.md index abefb9ab..98c086c2 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -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)). diff --git a/packages/crypto/README.md b/packages/crypto/README.md index a8da6d18..a80b663c 100644 --- a/packages/crypto/README.md +++ b/packages/crypto/README.md @@ -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)). diff --git a/packages/encoding/README.md b/packages/encoding/README.md index 785c41a1..fa61dbea 100644 --- a/packages/encoding/README.md +++ b/packages/encoding/README.md @@ -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)). diff --git a/packages/math/README.md b/packages/math/README.md index 665f0a39..15b6bdfa 100644 --- a/packages/math/README.md +++ b/packages/math/README.md @@ -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)). diff --git a/packages/utils/README.md b/packages/utils/README.md index 0ca47c2a..41317715 100644 --- a/packages/utils/README.md +++ b/packages/utils/README.md @@ -2,12 +2,11 @@ [![npm version](https://img.shields.io/npm/v/@cosmjs/utils.svg)](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)).