From a6b8e35b8471fba740a86906915b06bb3666d252 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Thu, 22 Jul 2021 13:43:59 +0200 Subject: [PATCH 1/3] Format CLI examples --- packages/cli/examples/delegate.ts | 10 +++++++- packages/cli/examples/multisig_address.ts | 30 +++++++++++------------ packages/cli/package.json | 1 + 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/packages/cli/examples/delegate.ts b/packages/cli/examples/delegate.ts index f84314bff6..72496c28a9 100644 --- a/packages/cli/examples/delegate.ts +++ b/packages/cli/examples/delegate.ts @@ -1,4 +1,12 @@ -import { coin, coins, makeSignDoc, makeStdTx, CosmosClient, MsgDelegate, Secp256k1HdWallet } from "@cosmjs/launchpad"; +import { + coin, + coins, + makeSignDoc, + makeStdTx, + CosmosClient, + MsgDelegate, + Secp256k1HdWallet, +} from "@cosmjs/launchpad"; const wallet = await Secp256k1HdWallet.fromMnemonic( "enlist hip relief stomach skate base shallow young switch frequent cry park", diff --git a/packages/cli/examples/multisig_address.ts b/packages/cli/examples/multisig_address.ts index 94c37c1a6a..763ebacae4 100644 --- a/packages/cli/examples/multisig_address.ts +++ b/packages/cli/examples/multisig_address.ts @@ -2,28 +2,28 @@ import { MultisigThresholdPubkey, pubkeyToAddress } from "@cosmjs/amino"; // https://github.com/cosmos/cosmjs/issues/673#issuecomment-779847238 const multisigPubkey: MultisigThresholdPubkey = { - "type": "tendermint/PubKeyMultisigThreshold", - "value": { - "threshold": "3", - "pubkeys": [ + type: "tendermint/PubKeyMultisigThreshold", + value: { + threshold: "3", + pubkeys: [ { - "type": "tendermint/PubKeySecp256k1", - "value": "A4KZH7VSRwW/6RTExROivRYKsQP63LnGcBlXFo+eKGpQ" + type: "tendermint/PubKeySecp256k1", + value: "A4KZH7VSRwW/6RTExROivRYKsQP63LnGcBlXFo+eKGpQ", }, { - "type": "tendermint/PubKeySecp256k1", - "value": "A8/Cq4VigOnDgl6RSdcx97fjrdCo/qwAX6C34n7ZDZLs" + type: "tendermint/PubKeySecp256k1", + value: "A8/Cq4VigOnDgl6RSdcx97fjrdCo/qwAX6C34n7ZDZLs", }, { - "type": "tendermint/PubKeySecp256k1", - "value": "ApKgZuwy03xgdRnXqG6yEHATomsWDOPacy7nbpsuUCSS" + type: "tendermint/PubKeySecp256k1", + value: "ApKgZuwy03xgdRnXqG6yEHATomsWDOPacy7nbpsuUCSS", }, { - "type": "tendermint/PubKeySecp256k1", - "value": "Aptm8E3WSSFS0RTAIUW+bLi/slYnTEE+h4qPTG28CHfq" - } - ] - } + type: "tendermint/PubKeySecp256k1", + value: "Aptm8E3WSSFS0RTAIUW+bLi/slYnTEE+h4qPTG28CHfq", + }, + ], + }, }; const address = pubkeyToAddress(multisigPubkey, "cosmos"); diff --git a/packages/cli/package.json b/packages/cli/package.json index 39c9de42e9..31a1e6b9af 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -16,6 +16,7 @@ }, "scripts": { "format": "prettier --write --loglevel warn \"./src/**/*.ts\"", + "format-examples": "prettier --write --loglevel warn \"./examples/**/*.ts\"", "format-text": "prettier --write \"./*.md\"", "lint": "eslint --max-warnings 0 \"./**/*.ts\" \"./*.js\"", "lint-fix": "eslint --fix --max-warnings 0 \"./**/*.ts\" \"./*.js\"", From 23c3706ff0d31beac73892525c14ca78aabc59e5 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Thu, 22 Jul 2021 14:01:00 +0200 Subject: [PATCH 2/3] Add CosmWasm CLI example --- .circleci/config.yml | 1 + packages/cli/examples/cosmwasm.ts | 66 +++++++++++++++++++++++++++++++ packages/cli/run_examples.sh | 3 ++ 3 files changed, 70 insertions(+) create mode 100755 packages/cli/examples/cosmwasm.ts diff --git a/.circleci/config.yml b/.circleci/config.yml index d0b0ff1909..d8f5c15855 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -159,6 +159,7 @@ jobs: environment: SKIP_BUILD: 1 command: | + yarn node ./bin/cosmwasm-cli --init examples/cosmwasm.ts --code "process.exit(0)" yarn node ./bin/cosmwasm-cli --init examples/coralnet.ts --code "process.exit(0)" yarn node ./bin/cosmwasm-cli --init examples/delegate.ts --code "process.exit(0)" yarn node ./bin/cosmwasm-cli --init examples/faucet_addresses.ts --code "process.exit(0)" diff --git a/packages/cli/examples/cosmwasm.ts b/packages/cli/examples/cosmwasm.ts new file mode 100755 index 0000000000..05549a6f9b --- /dev/null +++ b/packages/cli/examples/cosmwasm.ts @@ -0,0 +1,66 @@ +import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate"; +import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing"; +import { calculateFee, GasPrice } from "@cosmjs/stargate"; +import * as fs from "fs"; + +const rpcEndpoint = "http://localhost:26659"; + +// Example user from scripts/wasmd/README.md +const alice = { + mnemonic: "enlist hip relief stomach skate base shallow young switch frequent cry park", + address0: "wasm14qemq0vw6y3gc3u3e0aty2e764u4gs5lndxgyk", + address1: "wasm1hhg2rlu9jscacku2wwckws7932qqqu8xm5ca8y", + address2: "wasm1xv9tklw7d82sezh9haa573wufgy59vmwnxhnsl", + address3: "wasm17yg9mssjenmc3jkqth6ulcwj9cxujrxxg9nmzk", + address4: "wasm1f7j7ryulwjfe9ljplvhtcaxa6wqgula3nh873j", +}; + +async function main(hackatomWasmPath: string) { + const gasPrice = GasPrice.fromString("0.025ucosm"); + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: "wasm" }); + const client = await SigningCosmWasmClient.connectWithSigner(rpcEndpoint, wallet); + + // Upload contract + const wasm = fs.readFileSync(hackatomWasmPath); + const uploadFee = calculateFee(1_500_000, gasPrice); + const codeMeta = { + source: "https://crates.io/api/v1/crates/hackatom/not-yet-released/download", + builder: "cosmwasm/rust-optimizer:0.10.8", + }; + const uploadReceipt = await client.upload( + alice.address0, + wasm, + uploadFee, + codeMeta, + "Upload hackatom contract", + ); + console.info("Upload succeeded. Receipt:", uploadReceipt); + + // Instantiate + const instantiateFee = calculateFee(500_000, gasPrice); + // This contract specific message is passed to the contract + const msg = { + beneficiary: alice.address1, + verifier: alice.address0, + }; + const { contractAddress } = await client.instantiate( + alice.address0, + uploadReceipt.codeId, + msg, + "My instance", + instantiateFee, + { memo: `Create a hackatom instance` }, + ); + console.info(`Contract instantiated at: `, contractAddress); + + // Execute contract + const executeFee = calculateFee(300_000, gasPrice); + const result = await client.execute(alice.address0, contractAddress, { release: {} }, executeFee); + const wasmEvent = result.logs[0].events.find((e) => e.type === "wasm"); + console.info("The `wasm` event emitted by the contract execution:", wasmEvent); +} + +const repoRoot = process.cwd() + "/../.."; // This assumes you are in `packages/cli` +const hackatom = `${repoRoot}/scripts/wasmd/contracts/hackatom.wasm`; +await main(hackatom); +console.info("The show is over."); diff --git a/packages/cli/run_examples.sh b/packages/cli/run_examples.sh index 4216086d6b..489d53405b 100755 --- a/packages/cli/run_examples.sh +++ b/packages/cli/run_examples.sh @@ -2,6 +2,9 @@ set -o errexit -o nounset -o pipefail command -v shellcheck >/dev/null && shellcheck "$0" +if [ -n "${SIMAPP_ENABLED:-}" ]; then + yarn node ./bin/cosmwasm-cli --init examples/cosmwasm.ts --code "process.exit(0)" +fi yarn node ./bin/cosmwasm-cli --init examples/coralnet.ts --code "process.exit(0)" if [ -n "${LAUNCHPAD_ENABLED:-}" ]; then yarn node ./bin/cosmwasm-cli --init examples/delegate.ts --code "process.exit(0)" From 36c5cc3615c3935475ff6116965ae4371d7294bc Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Thu, 22 Jul 2021 14:03:49 +0200 Subject: [PATCH 3/3] Remove unmaintained coralnet.ts and helpers.ts --- .circleci/config.yml | 2 - packages/cli/examples/coralnet.ts | 32 ------------ packages/cli/examples/helpers.ts | 84 ------------------------------- packages/cli/run_examples.sh | 2 - 4 files changed, 120 deletions(-) delete mode 100644 packages/cli/examples/coralnet.ts delete mode 100644 packages/cli/examples/helpers.ts diff --git a/.circleci/config.yml b/.circleci/config.yml index d8f5c15855..bc5a4c09a6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -160,11 +160,9 @@ jobs: SKIP_BUILD: 1 command: | yarn node ./bin/cosmwasm-cli --init examples/cosmwasm.ts --code "process.exit(0)" - yarn node ./bin/cosmwasm-cli --init examples/coralnet.ts --code "process.exit(0)" yarn node ./bin/cosmwasm-cli --init examples/delegate.ts --code "process.exit(0)" yarn node ./bin/cosmwasm-cli --init examples/faucet_addresses.ts --code "process.exit(0)" yarn node ./bin/cosmwasm-cli --init examples/generate_address.ts --code "process.exit(0)" - yarn node ./bin/cosmwasm-cli --init examples/helpers.ts --code "process.exit(0)" yarn node ./bin/cosmwasm-cli --init examples/local_faucet.ts --code "process.exit(0)" yarn node ./bin/cosmwasm-cli --init examples/mask.ts --code "process.exit(0)" - run: diff --git a/packages/cli/examples/coralnet.ts b/packages/cli/examples/coralnet.ts deleted file mode 100644 index 9aaa73de3b..0000000000 --- a/packages/cli/examples/coralnet.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { HdPath } from "@cosmjs/crypto"; -import { CosmWasmFeeTable, SigningCosmWasmClient } from "@cosmjs/cosmwasm-launchpad"; -import { GasPrice, GasLimits, makeCosmoshubPath, Secp256k1HdWallet } from "@cosmjs/launchpad"; - -interface Options { - readonly httpUrl: string; - readonly bech32prefix: string; - readonly hdPaths: readonly HdPath[]; - readonly gasPrice: GasPrice; - readonly gasLimits: Partial>; // only set the ones you want to override -} - -const coralnetOptions: Options = { - httpUrl: "https://lcd.coralnet.cosmwasm.com", - gasPrice: GasPrice.fromString("0.025ushell"), - bech32prefix: "coral", - hdPaths: [makeCosmoshubPath(0)], - gasLimits: { - upload: 1500000, - }, -}; - -const wallet = await Secp256k1HdWallet.generate(12, coralnetOptions); -const [{ address }] = await wallet.getAccounts(); - -const client = new SigningCosmWasmClient( - coralnetOptions.httpUrl, - address, - wallet, - coralnetOptions.gasPrice, - coralnetOptions.gasLimits, -); diff --git a/packages/cli/examples/helpers.ts b/packages/cli/examples/helpers.ts deleted file mode 100644 index 29652aadee..0000000000 --- a/packages/cli/examples/helpers.ts +++ /dev/null @@ -1,84 +0,0 @@ -import axios from "axios"; -import * as fs from "fs"; - -import { Bip39, Random } from "@cosmjs/crypto"; -import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-launchpad"; -import { logs, GasPrice, Secp256k1HdWallet } from "@cosmjs/launchpad"; - -interface Options { - httpUrl: string; - networkId: string; - feeToken: string; - gasPrice: number; - bech32prefix: string; -} - -const defaultOptions: Options = { - httpUrl: "https://lcd.demo-10.cosmwasm.com", - networkId: "testing", - feeToken: "ucosm", - gasPrice: 0.025, - bech32prefix: "cosmos", -}; - -const defaultFaucetUrl = "https://faucet.demo-10.cosmwasm.com/credit"; - -const connect = async ( - mnemonic: string, - opts: Partial, -): Promise<{ - client: SigningCosmWasmClient; - address: string; -}> => { - const options: Options = { - bech32prefix: opts.bech32prefix ?? defaultOptions.bech32prefix, - feeToken: opts.feeToken ?? defaultOptions.feeToken, - gasPrice: opts.gasPrice ?? defaultOptions.gasPrice, - httpUrl: opts.httpUrl ?? defaultOptions.httpUrl, - networkId: opts.networkId ?? defaultOptions.networkId, - }; - const gasPrice = GasPrice.fromString(`${options.gasPrice}${options.feeToken}`); - const wallet = await Secp256k1HdWallet.fromMnemonic(mnemonic); - const [{ address }] = await wallet.getAccounts(); - - const client = new SigningCosmWasmClient(options.httpUrl, address, wallet, gasPrice); - return { client, address }; -}; - -// loadOrCreateMnemonic will try to load a mnemonic from the file. -// If missing, it will generate a random one and save to the file. -// -// This is not secure, but does allow simple developer access to persist a -// mnemonic between sessions -const loadOrCreateMnemonic = (filename: string): string => { - try { - const mnemonic = fs.readFileSync(filename, "utf8"); - return mnemonic.trim(); - } catch (err) { - const mnemonic = Bip39.encode(Random.getBytes(16)).toString(); - fs.writeFileSync(filename, mnemonic, "utf8"); - return mnemonic; - } -}; - -const randomAddress = async (prefix: string): Promise => { - const mnemonic = Bip39.encode(Random.getBytes(16)).toString(); - return mnemonicToAddress(prefix, mnemonic); -}; - -const mnemonicToAddress = async (prefix: string, mnemonic: string): Promise => { - const wallet = await Secp256k1HdWallet.fromMnemonic(mnemonic); - const [{ address }] = await wallet.getAccounts(); - return address; -}; - -const downloadWasm = async (url: string): Promise => { - const r = await axios.get(url, { responseType: "arraybuffer" }); - if (r.status !== 200) { - throw new Error(`Download error: ${r.status}`); - } - return r.data; -}; - -const getAttibute = (logs: readonly logs.Log[], key: string): string | undefined => - logs[0].events[0].attributes.find((x) => x.key == key)?.value; diff --git a/packages/cli/run_examples.sh b/packages/cli/run_examples.sh index 489d53405b..ae5ba58c58 100755 --- a/packages/cli/run_examples.sh +++ b/packages/cli/run_examples.sh @@ -5,13 +5,11 @@ command -v shellcheck >/dev/null && shellcheck "$0" if [ -n "${SIMAPP_ENABLED:-}" ]; then yarn node ./bin/cosmwasm-cli --init examples/cosmwasm.ts --code "process.exit(0)" fi -yarn node ./bin/cosmwasm-cli --init examples/coralnet.ts --code "process.exit(0)" if [ -n "${LAUNCHPAD_ENABLED:-}" ]; then yarn node ./bin/cosmwasm-cli --init examples/delegate.ts --code "process.exit(0)" fi yarn node ./bin/cosmwasm-cli --init examples/faucet_addresses.ts --code "process.exit(0)" yarn node ./bin/cosmwasm-cli --init examples/generate_address.ts --code "process.exit(0)" -yarn node ./bin/cosmwasm-cli --init examples/helpers.ts --code "process.exit(0)" yarn node ./bin/cosmwasm-cli --init examples/local_faucet.ts --code "process.exit(0)" yarn node ./bin/cosmwasm-cli --init examples/mask.ts --code "process.exit(0)" yarn node ./bin/cosmwasm-cli --init examples/multisig_address.ts --code "process.exit(0)"