From e118a9f821c21e01af386ef0ebba51dba5dcce9b Mon Sep 17 00:00:00 2001 From: Milan Steiner Date: Mon, 14 Feb 2022 09:40:37 +0100 Subject: [PATCH 1/4] Adding errors to unsupported TypeUrls --- packages/stargate/src/aminotypes.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/stargate/src/aminotypes.ts b/packages/stargate/src/aminotypes.ts index cf7a545147..54117e569d 100644 --- a/packages/stargate/src/aminotypes.ts +++ b/packages/stargate/src/aminotypes.ts @@ -526,6 +526,15 @@ export interface AminoTypesOptions { export class AminoTypes { private readonly register: Record; + // Those message types cannot be signed using the Amino JSON + private readonly unsupportedTypes: string[] = [ + "cosmos.authz.v1beta1.MsgGrant", + "cosmos.authz.v1beta1.MsgExec", + "cosmos.authz.v1beta1.MsgRevoke", + "cosmos.feegrant.v1beta1.MsgGrantAllowance", + "cosmos.feegrant.v1beta1.MsgRevokeAllowance", + ]; + public constructor({ prefix, additions = {} }: AminoTypesOptions) { const additionalAminoTypes = Object.values(additions); const filteredDefaultTypes = Object.entries(createDefaultTypes(prefix)).reduce( @@ -539,6 +548,12 @@ export class AminoTypes { } public toAmino({ typeUrl, value }: EncodeObject): AminoMsg { + if (this.unsupportedTypes.includes(typeUrl)) { + throw new Error( + `The message type '${typeUrl}' cannot be signed using the Amino JSON sign mode because this is not implemented on-chain.`, + ); + } + const converter = this.register[typeUrl]; if (!converter) { throw new Error( From e1ca45e7bbff67709b476b35caec71f562f276c2 Mon Sep 17 00:00:00 2001 From: Milan Steiner Date: Wed, 16 Feb 2022 16:54:37 +0100 Subject: [PATCH 2/4] Don't use hardcoded error messages --- packages/stargate/src/aminotypes.spec.ts | 11 ++++++ packages/stargate/src/aminotypes.ts | 45 +++++++++++++++--------- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/packages/stargate/src/aminotypes.spec.ts b/packages/stargate/src/aminotypes.spec.ts index 158f31e43d..14529fe83c 100644 --- a/packages/stargate/src/aminotypes.spec.ts +++ b/packages/stargate/src/aminotypes.spec.ts @@ -1006,6 +1006,17 @@ describe("AminoTypes", () => { expect(msg).toEqual(expected); }); + it("throws for types which are not on chain yet", () => { + expect(() => { + new AminoTypes({ prefix: "cosmos" }).toAmino({ + typeUrl: "/cosmos.feegrant.v1beta1.MsgRevokeAllowance", + value: 0, + }); + }).toThrowError( + /The message type '\/cosmos.feegrant.v1beta1.MsgRevokeAllowance' cannot be signed using the Amino JSON sign mode because this is not implemented on-chain./i, + ); + }); + it("throws for unknown type url", () => { expect(() => new AminoTypes({ prefix: "cosmos" }).fromAmino({ diff --git a/packages/stargate/src/aminotypes.ts b/packages/stargate/src/aminotypes.ts index 54117e569d..cfefd7c625 100644 --- a/packages/stargate/src/aminotypes.ts +++ b/packages/stargate/src/aminotypes.ts @@ -63,10 +63,14 @@ function omitDefault(input: T): T | undefined throw new Error(`Got unsupported type '${typeof input}'`); } -function createDefaultTypes(prefix: string): Record { +function createDefaultTypes(prefix: string): Record { return { - // bank + // authz + "/cosmos.authz.v1beta1.MsgGrant": "not_implemented_on_chain", + "/cosmos.authz.v1beta1.MsgExec": "not_implemented_on_chain", + "/cosmos.authz.v1beta1.MsgRevoke": "not_implemented_on_chain", + // bank "/cosmos.bank.v1beta1.MsgSend": { aminoType: "cosmos-sdk/MsgSend", toAmino: ({ fromAddress, toAddress, amount }: MsgSend): AminoMsgSend["value"] => ({ @@ -508,6 +512,8 @@ function createDefaultTypes(prefix: string): Record { timeoutTimestamp: Long.fromString(timeout_timestamp || "0", true), }), }, + "/cosmos.feegrant.v1beta1.MsgGrantAllowance": "not_implemented_on_chain", + "/cosmos.feegrant.v1beta1.MsgRevokeAllowance": "not_implemented_on_chain", }; } @@ -519,27 +525,29 @@ export interface AminoTypesOptions { readonly additions?: Record; } +function isAminoConverter( + converter: [string, AminoConverter | "not_implemented_on_chain"], +): converter is [string, AminoConverter] { + return typeof converter !== "string"; +} + /** * A map from Stargate message types as used in the messages's `Any` type * to Amino types. */ export class AminoTypes { - private readonly register: Record; - - // Those message types cannot be signed using the Amino JSON - private readonly unsupportedTypes: string[] = [ - "cosmos.authz.v1beta1.MsgGrant", - "cosmos.authz.v1beta1.MsgExec", - "cosmos.authz.v1beta1.MsgRevoke", - "cosmos.feegrant.v1beta1.MsgGrantAllowance", - "cosmos.feegrant.v1beta1.MsgRevokeAllowance", - ]; + private readonly register: Record; public constructor({ prefix, additions = {} }: AminoTypesOptions) { const additionalAminoTypes = Object.values(additions); const filteredDefaultTypes = Object.entries(createDefaultTypes(prefix)).reduce( (acc, [key, value]) => - additionalAminoTypes.find(({ aminoType }) => value.aminoType === aminoType) + additionalAminoTypes.find(({ aminoType }) => { + if (value !== "not_implemented_on_chain") { + return value.aminoType === aminoType; + } + return false; + }) ? acc : { ...acc, [key]: value }, {}, @@ -548,13 +556,12 @@ export class AminoTypes { } public toAmino({ typeUrl, value }: EncodeObject): AminoMsg { - if (this.unsupportedTypes.includes(typeUrl)) { + const converter = this.register[typeUrl]; + if (converter === "not_implemented_on_chain") { throw new Error( `The message type '${typeUrl}' cannot be signed using the Amino JSON sign mode because this is not implemented on-chain.`, ); } - - const converter = this.register[typeUrl]; if (!converter) { throw new Error( `Type URL '${typeUrl}' does not exist in the Amino message type register. ` + @@ -569,7 +576,10 @@ export class AminoTypes { } public fromAmino({ type, value }: AminoMsg): EncodeObject { - const result = Object.entries(this.register).find(([_typeUrl, { aminoType }]) => aminoType === type); + const result = Object.entries(this.register) + .filter(isAminoConverter) + .find((x) => x[1].aminoType === type); + if (!result) { throw new Error( `Amino type identifier '${type}' does not exist in the Amino message type register. ` + @@ -578,6 +588,7 @@ export class AminoTypes { ); } const [typeUrl, converter] = result; + return { typeUrl: typeUrl, value: converter.fromAmino(value), From d0aec9b4987aa923638a475aa39663cb8819c8a8 Mon Sep 17 00:00:00 2001 From: Milan Steiner Date: Wed, 16 Feb 2022 16:58:26 +0100 Subject: [PATCH 3/4] Fix typo --- packages/stargate/src/aminotypes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/stargate/src/aminotypes.ts b/packages/stargate/src/aminotypes.ts index cfefd7c625..673f387ad8 100644 --- a/packages/stargate/src/aminotypes.ts +++ b/packages/stargate/src/aminotypes.ts @@ -528,7 +528,7 @@ export interface AminoTypesOptions { function isAminoConverter( converter: [string, AminoConverter | "not_implemented_on_chain"], ): converter is [string, AminoConverter] { - return typeof converter !== "string"; + return typeof converter[1] !== "string"; } /** From f712b9e0d1fde50f8e32e2af2c0a2efa2ac74aa9 Mon Sep 17 00:00:00 2001 From: Milan Steiner Date: Mon, 21 Feb 2022 10:44:34 +0100 Subject: [PATCH 4/4] Revert Yarn cache changes --- .circleci/config.yml | 49 +- .pnp.cjs | 252 +---- .yarnrc.yml | 2 - CHANGELOG.md | 28 + README.md | 1 - package.json | 1 - packages/amino/README.md | 3 +- packages/amino/package.json | 2 +- packages/cli/README.md | 38 +- packages/cli/examples/delegate.ts | 59 +- packages/cli/examples/local_faucet.ts | 14 +- packages/cli/package.json | 1 - packages/cli/run_examples.sh | 2 +- .../src/signingcosmwasmclient.spec.ts | 51 +- .../src/signingcosmwasmclient.ts | 38 + .../cosmwasm-stargate/src/testutils.spec.ts | 14 +- packages/crypto/src/secp256k1.spec.ts | 24 + packages/crypto/src/secp256k1.ts | 46 +- packages/faucet-client/README.md | 2 +- .../faucet-client/src/faucetclient.spec.ts | 2 +- packages/faucet/README.md | 2 +- packages/faucet/package.json | 1 - packages/faucet/src/actions/generate.ts | 2 +- packages/faucet/src/actions/help.ts | 2 +- packages/faucet/src/actions/start.ts | 12 +- packages/faucet/src/api/webserver.ts | 14 +- packages/faucet/src/constants.ts | 8 +- packages/faucet/src/debugging.ts | 2 +- packages/faucet/src/faucet.spec.ts | 242 +---- packages/faucet/src/faucet.ts | 37 +- packages/faucet/src/profile.ts | 30 +- packages/faucet/src/tokenmanager.ts | 2 +- packages/faucet/src/types.ts | 8 +- packages/launchpad/.eslintignore | 1 - packages/launchpad/.eslintrc.js | 94 -- packages/launchpad/.gitignore | 3 - packages/launchpad/.nycrc.yml | 1 - packages/launchpad/README.md | 521 ----------- packages/launchpad/jasmine-testrunner.js | 38 - packages/launchpad/karma.conf.js | 54 -- packages/launchpad/package.json | 88 -- .../src/cosmosclient.searchtx.spec.ts | 304 ------ packages/launchpad/src/cosmosclient.spec.ts | 243 ----- packages/launchpad/src/cosmosclient.ts | 347 ------- packages/launchpad/src/fee.spec.ts | 55 -- packages/launchpad/src/fee.ts | 78 -- packages/launchpad/src/index.ts | 163 ---- packages/launchpad/src/lcdapi/auth.spec.ts | 67 -- packages/launchpad/src/lcdapi/auth.ts | 78 -- packages/launchpad/src/lcdapi/bank.spec.ts | 45 - packages/launchpad/src/lcdapi/bank.ts | 25 - packages/launchpad/src/lcdapi/base.ts | 146 --- .../launchpad/src/lcdapi/distribution.spec.ts | 188 ---- packages/launchpad/src/lcdapi/distribution.ts | 100 -- packages/launchpad/src/lcdapi/gov.spec.ts | 302 ------ packages/launchpad/src/lcdapi/gov.ts | 151 --- packages/launchpad/src/lcdapi/index.ts | 84 -- .../launchpad/src/lcdapi/lcdclient.spec.ts | 872 ------------------ packages/launchpad/src/lcdapi/lcdclient.ts | 314 ------- packages/launchpad/src/lcdapi/mint.spec.ts | 59 -- packages/launchpad/src/lcdapi/mint.ts | 42 - .../launchpad/src/lcdapi/slashing.spec.ts | 49 - packages/launchpad/src/lcdapi/slashing.ts | 47 - packages/launchpad/src/lcdapi/staking.spec.ts | 477 ---------- packages/launchpad/src/lcdapi/staking.ts | 251 ----- packages/launchpad/src/lcdapi/supply.spec.ts | 40 - packages/launchpad/src/lcdapi/supply.ts | 34 - packages/launchpad/src/lcdapi/utils.spec.ts | 95 -- packages/launchpad/src/lcdapi/utils.ts | 36 - packages/launchpad/src/logs.spec.ts | 165 ---- packages/launchpad/src/logs.ts | 82 -- packages/launchpad/src/msgs.ts | 335 ------- packages/launchpad/src/sequence.spec.ts | 41 - packages/launchpad/src/sequence.ts | 40 - .../launchpad/src/signingcosmosclient.spec.ts | 274 ------ packages/launchpad/src/signingcosmosclient.ts | 128 --- .../launchpad/src/testdata/cosmoshub.json | 44 - .../launchpad/src/testdata/txresponse1.json | 57 -- .../launchpad/src/testdata/txresponse2.json | 57 -- .../launchpad/src/testdata/txresponse3.json | 57 -- packages/launchpad/src/testutils.spec.ts | 94 -- packages/launchpad/src/tx.ts | 24 - packages/launchpad/tsconfig.eslint.json | 9 - packages/launchpad/tsconfig.json | 11 - packages/launchpad/typedoc.js | 11 - packages/launchpad/webpack.web.config.js | 35 - packages/ledger-amino/package.json | 1 - .../ledger-amino/src/ledgersigner.spec.ts | 24 - packages/ledger-amino/src/testutils.spec.ts | 15 - packages/proto-signing/src/coins.ts | 2 +- packages/proto-signing/src/registry.ts | 28 +- packages/proto-signing/src/signer.ts | 7 - packages/stargate/package.json | 2 +- packages/stargate/src/aminotypes.spec.ts | 88 +- packages/stargate/src/aminotypes.ts | 80 +- packages/stargate/src/fee.ts | 2 - .../stargate/src/signingstargateclient.ts | 29 +- packages/stargate/src/stargateclient.ts | 6 - packages/stargate/src/testutils.spec.ts | 2 +- .../src/tendermint34/adaptor/responses.ts | 2 +- .../src/tendermint34/responses.ts | 3 +- scripts/launchpad/README.md | 152 --- scripts/launchpad/cli.sh | 21 - scripts/launchpad/env | 5 - scripts/launchpad/generate_template.sh | 44 - scripts/launchpad/init.sh | 16 - scripts/launchpad/manual_start.sh | 41 - .../priv_validator_state.template.json | 1 - scripts/launchpad/send_first.js | 32 - scripts/launchpad/start.sh | 67 -- scripts/launchpad/stop.sh | 11 - ...k04ve8a0sugj4fe6q6zxuvmvza8r5fhf0s.address | 1 - scripts/launchpad/template/.wasmcli/keyhash | 1 - .../template/.wasmcli/validator.info | 1 - .../launchpad/template/.wasmd/config/app.toml | 36 - .../template/.wasmd/config/config.toml | 335 ------- .../template/.wasmd/config/genesis.json | 746 --------------- ...7eb061829f888de02b377eeb64009317c330d.json | 1 - .../template/.wasmd/config/node_key.json | 1 - .../.wasmd/config/priv_validator_key.json | 11 - .../.wasmd/data/priv_validator_state.json | 5 - scripts/wasmd/env | 2 +- scripts/wasmd/send_first.js | 2 +- yarn.lock | 87 +- 124 files changed, 490 insertions(+), 9367 deletions(-) delete mode 120000 packages/launchpad/.eslintignore delete mode 100644 packages/launchpad/.eslintrc.js delete mode 100644 packages/launchpad/.gitignore delete mode 120000 packages/launchpad/.nycrc.yml delete mode 100644 packages/launchpad/README.md delete mode 100644 packages/launchpad/jasmine-testrunner.js delete mode 100644 packages/launchpad/karma.conf.js delete mode 100644 packages/launchpad/package.json delete mode 100644 packages/launchpad/src/cosmosclient.searchtx.spec.ts delete mode 100644 packages/launchpad/src/cosmosclient.spec.ts delete mode 100644 packages/launchpad/src/cosmosclient.ts delete mode 100644 packages/launchpad/src/fee.spec.ts delete mode 100644 packages/launchpad/src/fee.ts delete mode 100644 packages/launchpad/src/index.ts delete mode 100644 packages/launchpad/src/lcdapi/auth.spec.ts delete mode 100644 packages/launchpad/src/lcdapi/auth.ts delete mode 100644 packages/launchpad/src/lcdapi/bank.spec.ts delete mode 100644 packages/launchpad/src/lcdapi/bank.ts delete mode 100644 packages/launchpad/src/lcdapi/base.ts delete mode 100644 packages/launchpad/src/lcdapi/distribution.spec.ts delete mode 100644 packages/launchpad/src/lcdapi/distribution.ts delete mode 100644 packages/launchpad/src/lcdapi/gov.spec.ts delete mode 100644 packages/launchpad/src/lcdapi/gov.ts delete mode 100644 packages/launchpad/src/lcdapi/index.ts delete mode 100644 packages/launchpad/src/lcdapi/lcdclient.spec.ts delete mode 100644 packages/launchpad/src/lcdapi/lcdclient.ts delete mode 100644 packages/launchpad/src/lcdapi/mint.spec.ts delete mode 100644 packages/launchpad/src/lcdapi/mint.ts delete mode 100644 packages/launchpad/src/lcdapi/slashing.spec.ts delete mode 100644 packages/launchpad/src/lcdapi/slashing.ts delete mode 100644 packages/launchpad/src/lcdapi/staking.spec.ts delete mode 100644 packages/launchpad/src/lcdapi/staking.ts delete mode 100644 packages/launchpad/src/lcdapi/supply.spec.ts delete mode 100644 packages/launchpad/src/lcdapi/supply.ts delete mode 100644 packages/launchpad/src/lcdapi/utils.spec.ts delete mode 100644 packages/launchpad/src/lcdapi/utils.ts delete mode 100644 packages/launchpad/src/logs.spec.ts delete mode 100644 packages/launchpad/src/logs.ts delete mode 100644 packages/launchpad/src/msgs.ts delete mode 100644 packages/launchpad/src/sequence.spec.ts delete mode 100644 packages/launchpad/src/sequence.ts delete mode 100644 packages/launchpad/src/signingcosmosclient.spec.ts delete mode 100644 packages/launchpad/src/signingcosmosclient.ts delete mode 100644 packages/launchpad/src/testdata/cosmoshub.json delete mode 100644 packages/launchpad/src/testdata/txresponse1.json delete mode 100644 packages/launchpad/src/testdata/txresponse2.json delete mode 100644 packages/launchpad/src/testdata/txresponse3.json delete mode 100644 packages/launchpad/src/testutils.spec.ts delete mode 100644 packages/launchpad/src/tx.ts delete mode 100644 packages/launchpad/tsconfig.eslint.json delete mode 100644 packages/launchpad/tsconfig.json delete mode 100644 packages/launchpad/typedoc.js delete mode 100644 packages/launchpad/webpack.web.config.js delete mode 100644 scripts/launchpad/README.md delete mode 100755 scripts/launchpad/cli.sh delete mode 100644 scripts/launchpad/env delete mode 100755 scripts/launchpad/generate_template.sh delete mode 100755 scripts/launchpad/init.sh delete mode 100755 scripts/launchpad/manual_start.sh delete mode 100644 scripts/launchpad/priv_validator_state.template.json delete mode 100755 scripts/launchpad/send_first.js delete mode 100755 scripts/launchpad/start.sh delete mode 100755 scripts/launchpad/stop.sh delete mode 100644 scripts/launchpad/template/.wasmcli/cosmos1yfkkk04ve8a0sugj4fe6q6zxuvmvza8r5fhf0s.address delete mode 100755 scripts/launchpad/template/.wasmcli/keyhash delete mode 100644 scripts/launchpad/template/.wasmcli/validator.info delete mode 100644 scripts/launchpad/template/.wasmd/config/app.toml delete mode 100644 scripts/launchpad/template/.wasmd/config/config.toml delete mode 100644 scripts/launchpad/template/.wasmd/config/genesis.json delete mode 100644 scripts/launchpad/template/.wasmd/config/gentx/gentx-aaf7eb061829f888de02b377eeb64009317c330d.json delete mode 100644 scripts/launchpad/template/.wasmd/config/node_key.json delete mode 100644 scripts/launchpad/template/.wasmd/config/priv_validator_key.json delete mode 100644 scripts/launchpad/template/.wasmd/data/priv_validator_state.json diff --git a/.circleci/config.yml b/.circleci/config.yml index 690be7e926..1dc802398e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -87,10 +87,6 @@ jobs: wget -O "$HOME/git-lfs.deb" https://packagecloud.io/github/git-lfs/packages/ubuntu/focal/git-lfs_2.12.1_amd64.deb/download.deb sudo dpkg -i "$HOME/git-lfs.deb" - checkout - - run: # start early for less wait time below - name: Start launchpad - command: ./scripts/launchpad/start.sh - background: true - run: # start early for less wait time below name: Start wasmd command: ./scripts/wasmd/start.sh @@ -142,9 +138,6 @@ jobs: - run: name: Install Dependencies command: yarn install --immutable --immutable-cache --check-cache - - run: - name: Initialize launchpad (deploy contracts and friends) - command: ./scripts/launchpad/init.sh - run: name: Initialize wasmd (deploy contracts and friends) command: ./scripts/wasmd/init.sh @@ -154,7 +147,6 @@ jobs: - run: name: Run tests environment: - LAUNCHPAD_ENABLED: 1 TENDERMINT_ENABLED: 1 SOCKETSERVER_ENABLED: 1 SKIP_BUILD: 1 @@ -173,14 +165,14 @@ jobs: name: Run CLI examples working_directory: packages/cli environment: + TENDERMINT_ENABLED: 1 + SOCKETSERVER_ENABLED: 1 SKIP_BUILD: 1 + WASMD_ENABLED: 1 command: | - yarn node ./bin/cosmwasm-cli --init examples/cosmwasm.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/local_faucet.ts --code "process.exit(0)" - yarn node ./bin/cosmwasm-cli --init examples/mask.ts --code "process.exit(0)" + [ "<< parameters.simapp >>" = "simapp42" ] && export SIMAPP42_ENABLED=1 SLOW_SIMAPP42_ENABLED=1 + [ "<< parameters.simapp >>" = "simapp44" ] && export SIMAPP44_ENABLED=1 SLOW_SIMAPP44_ENABLED=1 + ./run_examples.sh - run: name: Stop chains command: | @@ -189,7 +181,6 @@ jobs: ./scripts/<< parameters.simapp >>/stop.sh ./scripts/<< parameters.simapp >>/slow_stop.sh ./scripts/wasmd/stop.sh - ./scripts/launchpad/stop.sh test-node: parameters: node-version: @@ -211,10 +202,6 @@ jobs: wget -O "$HOME/git-lfs.deb" https://packagecloud.io/github/git-lfs/packages/ubuntu/focal/git-lfs_2.12.1_amd64.deb/download.deb sudo dpkg -i "$HOME/git-lfs.deb" - checkout - - run: # start early for less wait time below - name: Start launchpad - command: ./scripts/launchpad/start.sh - background: true - run: # start early for less wait time below name: Start wasmd command: ./scripts/wasmd/start.sh @@ -271,9 +258,6 @@ jobs: - run: name: Install Dependencies command: yarn install --immutable --immutable-cache --check-cache - - run: - name: Initialize launchpad (deploy contracts and friends) - command: ./scripts/launchpad/init.sh - run: name: Initialize wasmd (deploy contracts and friends) command: ./scripts/wasmd/init.sh @@ -282,7 +266,6 @@ jobs: command: ./scripts/socketserver/start.sh - run: environment: - LAUNCHPAD_ENABLED: 1 SIMAPP42_ENABLED: 1 SLOW_SIMAPP42_ENABLED: 1 TENDERMINT_ENABLED: 1 @@ -301,7 +284,6 @@ jobs: name: Run CLI examples working_directory: packages/cli environment: - LAUNCHPAD_ENABLED: 1 SIMAPP42_ENABLED: 1 SLOW_SIMAPP42_ENABLED: 1 TENDERMINT_ENABLED: 1 @@ -317,7 +299,6 @@ jobs: ./scripts/simapp42/stop.sh ./scripts/simapp42/slow_stop.sh ./scripts/wasmd/stop.sh - ./scripts/launchpad/stop.sh test-chrome: machine: # We can't use a containerized environment since it requires remote docker to start custom containers. @@ -337,10 +318,6 @@ jobs: wget -O "$HOME/git-lfs.deb" https://packagecloud.io/github/git-lfs/packages/ubuntu/focal/git-lfs_2.12.1_amd64.deb/download.deb sudo dpkg -i "$HOME/git-lfs.deb" - checkout - - run: # start early for less wait time below - name: Start launchpad - command: ./scripts/launchpad/start.sh - background: true - run: # start early for less wait time below name: Start wasmd command: ./scripts/wasmd/start.sh @@ -392,9 +369,6 @@ jobs: - run: name: Install Dependencies command: yarn install --immutable --immutable-cache --check-cache - - run: - name: Initialize launchpad (deploy contracts and friends) - command: ./scripts/launchpad/init.sh - run: name: Initialize wasmd (deploy contracts and friends) command: ./scripts/wasmd/init.sh @@ -403,7 +377,6 @@ jobs: command: ./scripts/socketserver/start.sh - run: environment: - LAUNCHPAD_ENABLED: 1 SIMAPP42_ENABLED: 1 SLOW_SIMAPP42_ENABLED: 1 TENDERMINT_ENABLED: 1 @@ -419,7 +392,6 @@ jobs: ./scripts/simapp42/stop.sh ./scripts/simapp42/slow_stop.sh ./scripts/wasmd/stop.sh - ./scripts/launchpad/stop.sh coverage: machine: # We can't use a containerized environment since it requires remote docker to start custom containers. @@ -438,10 +410,6 @@ jobs: wget -O "$HOME/git-lfs.deb" https://packagecloud.io/github/git-lfs/packages/ubuntu/focal/git-lfs_2.12.1_amd64.deb/download.deb sudo dpkg -i "$HOME/git-lfs.deb" - checkout - - run: # start early for less wait time below - name: Start launchpad - command: ./scripts/launchpad/start.sh - background: true - run: # start early for less wait time below name: Start wasmd command: ./scripts/wasmd/start.sh @@ -493,9 +461,6 @@ jobs: - run: name: Install Dependencies command: yarn install --immutable --immutable-cache --check-cache - - run: - name: Initialize launchpad (deploy contracts and friends) - command: ./scripts/launchpad/init.sh - run: name: Initialize wasmd (deploy contracts and friends) command: ./scripts/wasmd/init.sh @@ -504,7 +469,6 @@ jobs: command: ./scripts/socketserver/start.sh - run: environment: - LAUNCHPAD_ENABLED: 1 SIMAPP42_ENABLED: 1 SLOW_SIMAPP42_ENABLED: 1 TENDERMINT_ENABLED: 1 @@ -523,7 +487,6 @@ jobs: ./scripts/simapp42/stop.sh ./scripts/simapp42/slow_stop.sh ./scripts/wasmd/stop.sh - ./scripts/launchpad/stop.sh docs-build: docker: - image: circleci/node:16.13-bullseye diff --git a/.pnp.cjs b/.pnp.cjs index d462e57f9d..50181e39cd 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -54,10 +54,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "name": "@cosmjs/json-rpc", "reference": "workspace:packages/json-rpc" }, - { - "name": "@cosmjs/launchpad", - "reference": "workspace:packages/launchpad" - }, { "name": "@cosmjs/ledger-amino", "reference": "workspace:packages/ledger-amino" @@ -102,7 +98,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@cosmjs/faucet", ["workspace:packages/faucet"]], ["@cosmjs/faucet-client", ["workspace:packages/faucet-client"]], ["@cosmjs/json-rpc", ["workspace:packages/json-rpc"]], - ["@cosmjs/launchpad", ["workspace:packages/launchpad"]], ["@cosmjs/ledger-amino", ["workspace:packages/ledger-amino"]], ["@cosmjs/math", ["workspace:packages/math"]], ["@cosmjs/proto-signing", ["workspace:packages/proto-signing"]], @@ -220,7 +215,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ], [ "@confio/ics23", - "npm:0.6.5" + "npm:0.6.8" ], [ "@cosmjs/amino", @@ -254,10 +249,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "@cosmjs/json-rpc", "workspace:packages/json-rpc" ], - [ - "@cosmjs/launchpad", - "workspace:packages/launchpad" - ], [ "@cosmjs/ledger-amino", "workspace:packages/ledger-amino" @@ -1766,10 +1757,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "jest-worker", "npm:26.6.2" ], - [ - "js-sha512", - "npm:0.8.0" - ], [ "js-tokens", "npm:4.0.0" @@ -2456,7 +2443,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ], [ "simple-get", - "npm:3.1.0" + "npm:3.1.1" ], [ "slash", @@ -2856,7 +2843,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@cosmjs/cosmwasm-stargate", "workspace:packages/cosmwasm-stargate"], ["@cosmjs/crypto", "workspace:packages/crypto"], ["@cosmjs/encoding", "workspace:packages/encoding"], - ["@cosmjs/launchpad", "workspace:packages/launchpad"], ["@cosmjs/proto-signing", "workspace:packages/proto-signing"], ["@cosmjs/stargate", "workspace:packages/stargate"], ["eslint", "npm:7.26.0"], @@ -3187,14 +3173,12 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["@confio/ics23", [ - ["npm:0.6.5", { - "packageLocation": "./.yarn/cache/@confio-ics23-npm-0.6.5-21db74210e-dc658795ec.zip/node_modules/@confio/ics23/", + ["npm:0.6.8", { + "packageLocation": "./.yarn/cache/@confio-ics23-npm-0.6.8-c87607eb2c-376d72f644.zip/node_modules/@confio/ics23/", "packageDependencies": [ - ["@confio/ics23", "npm:0.6.5"], - ["js-sha512", "npm:0.8.0"], - ["protobufjs", "npm:6.10.2"], - ["ripemd160", "npm:2.0.2"], - ["sha.js", "npm:2.4.11"] + ["@confio/ics23", "npm:0.6.8"], + ["@noble/hashes", "npm:1.0.0"], + ["protobufjs", "npm:6.10.2"] ], "linkType": "HARD", }] @@ -3256,7 +3240,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@cosmjs/crypto", "workspace:packages/crypto"], ["@cosmjs/encoding", "workspace:packages/encoding"], ["@cosmjs/faucet-client", "workspace:packages/faucet-client"], - ["@cosmjs/launchpad", "workspace:packages/launchpad"], ["@cosmjs/math", "workspace:packages/math"], ["@cosmjs/proto-signing", "workspace:packages/proto-signing"], ["@cosmjs/stargate", "workspace:packages/stargate"], @@ -3465,7 +3448,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@cosmjs/faucet", "workspace:packages/faucet"], ["@cosmjs/crypto", "workspace:packages/crypto"], ["@cosmjs/encoding", "workspace:packages/encoding"], - ["@cosmjs/launchpad", "workspace:packages/launchpad"], ["@cosmjs/math", "workspace:packages/math"], ["@cosmjs/proto-signing", "workspace:packages/proto-signing"], ["@cosmjs/stargate", "workspace:packages/stargate"], @@ -3588,58 +3570,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "SOFT", }] ]], - ["@cosmjs/launchpad", [ - ["workspace:packages/launchpad", { - "packageLocation": "./packages/launchpad/", - "packageDependencies": [ - ["@cosmjs/launchpad", "workspace:packages/launchpad"], - ["@cosmjs/amino", "workspace:packages/amino"], - ["@cosmjs/crypto", "workspace:packages/crypto"], - ["@cosmjs/encoding", "workspace:packages/encoding"], - ["@cosmjs/math", "workspace:packages/math"], - ["@cosmjs/utils", "workspace:packages/utils"], - ["@istanbuljs/nyc-config-typescript", "virtual:4f1584ad4aba8733a24be7c8aebbffafef25607f2d00f4b314cf96717145c692763628a31c2b85d4686fbb091ff21ebffa3cc337399c042c19a32b9bdb786464#npm:1.0.1"], - ["@types/eslint-plugin-prettier", "npm:3.1.0"], - ["@types/jasmine", "npm:3.8.1"], - ["@types/karma-firefox-launcher", "npm:2.1.0"], - ["@types/karma-jasmine", "npm:4.0.0"], - ["@types/karma-jasmine-html-reporter", "npm:1.5.1"], - ["@types/node", "npm:15.3.1"], - ["@typescript-eslint/eslint-plugin", "virtual:4f1584ad4aba8733a24be7c8aebbffafef25607f2d00f4b314cf96717145c692763628a31c2b85d4686fbb091ff21ebffa3cc337399c042c19a32b9bdb786464#npm:4.28.4"], - ["@typescript-eslint/parser", "virtual:4f1584ad4aba8733a24be7c8aebbffafef25607f2d00f4b314cf96717145c692763628a31c2b85d4686fbb091ff21ebffa3cc337399c042c19a32b9bdb786464#npm:4.28.4"], - ["axios", "npm:0.21.4"], - ["eslint", "npm:7.26.0"], - ["eslint-config-prettier", "virtual:4f1584ad4aba8733a24be7c8aebbffafef25607f2d00f4b314cf96717145c692763628a31c2b85d4686fbb091ff21ebffa3cc337399c042c19a32b9bdb786464#npm:8.3.0"], - ["eslint-import-resolver-node", "npm:0.3.4"], - ["eslint-plugin-import", "virtual:4f1584ad4aba8733a24be7c8aebbffafef25607f2d00f4b314cf96717145c692763628a31c2b85d4686fbb091ff21ebffa3cc337399c042c19a32b9bdb786464#npm:2.23.2"], - ["eslint-plugin-prettier", "virtual:4f1584ad4aba8733a24be7c8aebbffafef25607f2d00f4b314cf96717145c692763628a31c2b85d4686fbb091ff21ebffa3cc337399c042c19a32b9bdb786464#npm:3.4.0"], - ["eslint-plugin-simple-import-sort", "virtual:4f1584ad4aba8733a24be7c8aebbffafef25607f2d00f4b314cf96717145c692763628a31c2b85d4686fbb091ff21ebffa3cc337399c042c19a32b9bdb786464#npm:7.0.0"], - ["esm", "npm:3.2.25"], - ["fast-deep-equal", "npm:3.1.3"], - ["glob", "npm:7.1.7"], - ["jasmine", "npm:3.8.0"], - ["jasmine-core", "npm:3.8.0"], - ["jasmine-spec-reporter", "npm:6.0.0"], - ["karma", "npm:6.3.2"], - ["karma-chrome-launcher", "npm:3.1.0"], - ["karma-firefox-launcher", "npm:2.1.0"], - ["karma-jasmine", "virtual:4f1584ad4aba8733a24be7c8aebbffafef25607f2d00f4b314cf96717145c692763628a31c2b85d4686fbb091ff21ebffa3cc337399c042c19a32b9bdb786464#npm:4.0.1"], - ["karma-jasmine-html-reporter", "virtual:4f1584ad4aba8733a24be7c8aebbffafef25607f2d00f4b314cf96717145c692763628a31c2b85d4686fbb091ff21ebffa3cc337399c042c19a32b9bdb786464#npm:1.6.0"], - ["nyc", "npm:15.1.0"], - ["prettier", "npm:2.4.1"], - ["readonly-date", "npm:1.0.0"], - ["ses", "npm:0.11.1"], - ["source-map-support", "npm:0.5.19"], - ["stream-browserify", "npm:3.0.0"], - ["ts-node", "virtual:4f1584ad4aba8733a24be7c8aebbffafef25607f2d00f4b314cf96717145c692763628a31c2b85d4686fbb091ff21ebffa3cc337399c042c19a32b9bdb786464#npm:8.10.2"], - ["typedoc", "virtual:4f1584ad4aba8733a24be7c8aebbffafef25607f2d00f4b314cf96717145c692763628a31c2b85d4686fbb091ff21ebffa3cc337399c042c19a32b9bdb786464#npm:0.22.11"], - ["typescript", "patch:typescript@npm%3A4.4.4#~builtin::version=4.4.4&hash=ddd1e8"], - ["webpack", "virtual:db46c448d4270fdb3b876d89bfac4ef71013dbbf936984e3bdf75d2625d01d582344f08a024c01ef1b5ce6d880baba103eab42675713e0991f42e83024f39f25#npm:5.37.1"], - ["webpack-cli", "virtual:db46c448d4270fdb3b876d89bfac4ef71013dbbf936984e3bdf75d2625d01d582344f08a024c01ef1b5ce6d880baba103eab42675713e0991f42e83024f39f25#npm:4.7.0"] - ], - "linkType": "SOFT", - }] - ]], ["@cosmjs/ledger-amino", [ ["workspace:packages/ledger-amino", { "packageLocation": "./packages/ledger-amino/", @@ -3648,7 +3578,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@cosmjs/amino", "workspace:packages/amino"], ["@cosmjs/crypto", "workspace:packages/crypto"], ["@cosmjs/encoding", "workspace:packages/encoding"], - ["@cosmjs/launchpad", "workspace:packages/launchpad"], ["@cosmjs/math", "workspace:packages/math"], ["@cosmjs/stargate", "workspace:packages/stargate"], ["@cosmjs/utils", "workspace:packages/utils"], @@ -3839,7 +3768,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageLocation": "./packages/stargate/", "packageDependencies": [ ["@cosmjs/stargate", "workspace:packages/stargate"], - ["@confio/ics23", "npm:0.6.5"], + ["@confio/ics23", "npm:0.6.8"], ["@cosmjs/amino", "workspace:packages/amino"], ["@cosmjs/crypto", "workspace:packages/crypto"], ["@cosmjs/encoding", "workspace:packages/encoding"], @@ -5434,23 +5363,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ], "linkType": "HARD", }], - ["virtual:c40ffa9da9410f1eb88a4aced56c0b7274d5471c24490a910b8d88bd5338ba8e40ff4f18351b2936308c9747c07026dcf363a139309f893ddadcb3906c5c9a66#npm:1.0.3", { - "packageLocation": "./.yarn/__virtual__/@webpack-cli-configtest-virtual-22aaa3961d/0/cache/@webpack-cli-configtest-npm-1.0.3-b6e357f778-4efcca159e.zip/node_modules/@webpack-cli/configtest/", - "packageDependencies": [ - ["@webpack-cli/configtest", "virtual:c40ffa9da9410f1eb88a4aced56c0b7274d5471c24490a910b8d88bd5338ba8e40ff4f18351b2936308c9747c07026dcf363a139309f893ddadcb3906c5c9a66#npm:1.0.3"], - ["@types/webpack", null], - ["@types/webpack-cli", null], - ["webpack", "virtual:db46c448d4270fdb3b876d89bfac4ef71013dbbf936984e3bdf75d2625d01d582344f08a024c01ef1b5ce6d880baba103eab42675713e0991f42e83024f39f25#npm:5.37.1"], - ["webpack-cli", "virtual:db46c448d4270fdb3b876d89bfac4ef71013dbbf936984e3bdf75d2625d01d582344f08a024c01ef1b5ce6d880baba103eab42675713e0991f42e83024f39f25#npm:4.7.0"] - ], - "packagePeers": [ - "@types/webpack-cli", - "@types/webpack", - "webpack-cli", - "webpack" - ], - "linkType": "HARD", - }], ["virtual:e545141db94d121e901ffbb09d6c54f53f485ecdf99f9847aaf0f186594082f8121d89d8183c7bf05b17673cbb64c358037fbd69d06a0ad71096f07b595a2385#npm:1.0.3", { "packageLocation": "./.yarn/__virtual__/@webpack-cli-configtest-virtual-b614d6a687/0/cache/@webpack-cli-configtest-npm-1.0.3-b6e357f778-4efcca159e.zip/node_modules/@webpack-cli/configtest/", "packageDependencies": [ @@ -5665,20 +5577,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ], "linkType": "HARD", }], - ["virtual:c40ffa9da9410f1eb88a4aced56c0b7274d5471c24490a910b8d88bd5338ba8e40ff4f18351b2936308c9747c07026dcf363a139309f893ddadcb3906c5c9a66#npm:1.2.4", { - "packageLocation": "./.yarn/__virtual__/@webpack-cli-info-virtual-bc51bdae82/0/cache/@webpack-cli-info-npm-1.2.4-e4a2135f37-4e27ccd04c.zip/node_modules/@webpack-cli/info/", - "packageDependencies": [ - ["@webpack-cli/info", "virtual:c40ffa9da9410f1eb88a4aced56c0b7274d5471c24490a910b8d88bd5338ba8e40ff4f18351b2936308c9747c07026dcf363a139309f893ddadcb3906c5c9a66#npm:1.2.4"], - ["@types/webpack-cli", null], - ["envinfo", "npm:7.8.1"], - ["webpack-cli", "virtual:db46c448d4270fdb3b876d89bfac4ef71013dbbf936984e3bdf75d2625d01d582344f08a024c01ef1b5ce6d880baba103eab42675713e0991f42e83024f39f25#npm:4.7.0"] - ], - "packagePeers": [ - "@types/webpack-cli", - "webpack-cli" - ], - "linkType": "HARD", - }], ["virtual:e545141db94d121e901ffbb09d6c54f53f485ecdf99f9847aaf0f186594082f8121d89d8183c7bf05b17673cbb64c358037fbd69d06a0ad71096f07b595a2385#npm:1.2.4", { "packageLocation": "./.yarn/__virtual__/@webpack-cli-info-virtual-98a9b8985b/0/cache/@webpack-cli-info-npm-1.2.4-e4a2135f37-4e27ccd04c.zip/node_modules/@webpack-cli/info/", "packageDependencies": [ @@ -5917,23 +5815,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ], "linkType": "HARD", }], - ["virtual:c40ffa9da9410f1eb88a4aced56c0b7274d5471c24490a910b8d88bd5338ba8e40ff4f18351b2936308c9747c07026dcf363a139309f893ddadcb3906c5c9a66#npm:1.4.0", { - "packageLocation": "./.yarn/__virtual__/@webpack-cli-serve-virtual-a77aea3c64/0/cache/@webpack-cli-serve-npm-1.4.0-1f566be693-0b063bed4c.zip/node_modules/@webpack-cli/serve/", - "packageDependencies": [ - ["@webpack-cli/serve", "virtual:c40ffa9da9410f1eb88a4aced56c0b7274d5471c24490a910b8d88bd5338ba8e40ff4f18351b2936308c9747c07026dcf363a139309f893ddadcb3906c5c9a66#npm:1.4.0"], - ["@types/webpack-cli", null], - ["@types/webpack-dev-server", null], - ["webpack-cli", "virtual:db46c448d4270fdb3b876d89bfac4ef71013dbbf936984e3bdf75d2625d01d582344f08a024c01ef1b5ce6d880baba103eab42675713e0991f42e83024f39f25#npm:4.7.0"], - ["webpack-dev-server", null] - ], - "packagePeers": [ - "@types/webpack-cli", - "@types/webpack-dev-server", - "webpack-cli", - "webpack-dev-server" - ], - "linkType": "HARD", - }], ["virtual:e545141db94d121e901ffbb09d6c54f53f485ecdf99f9847aaf0f186594082f8121d89d8183c7bf05b17673cbb64c358037fbd69d06a0ad71096f07b595a2385#npm:1.4.0", { "packageLocation": "./.yarn/__virtual__/@webpack-cli-serve-virtual-222b31cce8/0/cache/@webpack-cli-serve-npm-1.4.0-1f566be693-0b063bed4c.zip/node_modules/@webpack-cli/serve/", "packageDependencies": [ @@ -6999,7 +6880,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@cosmjs/cosmwasm-stargate", "workspace:packages/cosmwasm-stargate"], ["@cosmjs/crypto", "workspace:packages/crypto"], ["@cosmjs/encoding", "workspace:packages/encoding"], - ["@cosmjs/launchpad", "workspace:packages/launchpad"], ["@cosmjs/proto-signing", "workspace:packages/proto-signing"], ["@cosmjs/stargate", "workspace:packages/stargate"], ["eslint", "npm:7.26.0"], @@ -9220,15 +9100,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD", }] ]], - ["js-sha512", [ - ["npm:0.8.0", { - "packageLocation": "./.yarn/cache/js-sha512-npm-0.8.0-48a1a122ac-32ca371ebd.zip/node_modules/js-sha512/", - "packageDependencies": [ - ["js-sha512", "npm:0.8.0"] - ], - "linkType": "HARD", - }] - ]], ["js-tokens", [ ["npm:4.0.0", { "packageLocation": "./.yarn/cache/js-tokens-npm-4.0.0-0ac852e9e2-8a95213a5a.zip/node_modules/js-tokens/", @@ -10603,7 +10474,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["npmlog", "npm:4.1.2"], ["pump", "npm:3.0.0"], ["rc", "npm:1.2.8"], - ["simple-get", "npm:3.1.0"], + ["simple-get", "npm:3.1.1"], ["tar-fs", "npm:2.1.1"], ["tunnel-agent", "npm:0.6.0"], ["which-pm-runs", "npm:1.0.0"] @@ -10625,7 +10496,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["npmlog", "npm:4.1.2"], ["pump", "npm:3.0.0"], ["rc", "npm:1.2.8"], - ["simple-get", "npm:3.1.0"], + ["simple-get", "npm:3.1.1"], ["tar-fs", "npm:2.1.1"], ["tunnel-agent", "npm:0.6.0"] ], @@ -11334,10 +11205,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["simple-get", [ - ["npm:3.1.0", { - "packageLocation": "./.yarn/cache/simple-get-npm-3.1.0-8c6f03c4cd-cca91a9ab2.zip/node_modules/simple-get/", + ["npm:3.1.1", { + "packageLocation": "./.yarn/cache/simple-get-npm-3.1.1-dce5923dba-80195e70bf.zip/node_modules/simple-get/", "packageDependencies": [ - ["simple-get", "npm:3.1.0"], + ["simple-get", "npm:3.1.1"], ["decompress-response", "npm:4.2.1"], ["once", "npm:1.4.0"], ["simple-concat", "npm:1.0.1"] @@ -11913,25 +11784,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ], "linkType": "HARD", }], - ["virtual:3fc9ad73a25400af56d4125aff61a9fcb0cd6e665fdaa8ac5c8928896a4cae3b678e19c1bb722ba1f7dd8d9840cb8e3e6257c52c511a8ce7cb8e8e6dd26f35f3#npm:5.1.2", { - "packageLocation": "./.yarn/__virtual__/terser-webpack-plugin-virtual-52b28a15cd/0/cache/terser-webpack-plugin-npm-5.1.2-59f409825a-0eb0e81f52.zip/node_modules/terser-webpack-plugin/", - "packageDependencies": [ - ["terser-webpack-plugin", "virtual:3fc9ad73a25400af56d4125aff61a9fcb0cd6e665fdaa8ac5c8928896a4cae3b678e19c1bb722ba1f7dd8d9840cb8e3e6257c52c511a8ce7cb8e8e6dd26f35f3#npm:5.1.2"], - ["@types/webpack", null], - ["jest-worker", "npm:26.6.2"], - ["p-limit", "npm:3.1.0"], - ["schema-utils", "npm:3.0.0"], - ["serialize-javascript", "npm:5.0.1"], - ["source-map", "npm:0.6.1"], - ["terser", "npm:5.7.0"], - ["webpack", "virtual:db46c448d4270fdb3b876d89bfac4ef71013dbbf936984e3bdf75d2625d01d582344f08a024c01ef1b5ce6d880baba103eab42675713e0991f42e83024f39f25#npm:5.37.1"] - ], - "packagePeers": [ - "@types/webpack", - "webpack" - ], - "linkType": "HARD", - }], ["virtual:5e82fc811d8fd02f05149cd66fb79c02f16f05bfaf043b01e108813bc4e39a600f5a9f93ce3a86bd2c21b92c8082c2e5b50384c76a2fc4e252d186976e3055e2#npm:5.1.2", { "packageLocation": "./.yarn/__virtual__/terser-webpack-plugin-virtual-1be69a9933/0/cache/terser-webpack-plugin-npm-5.1.2-59f409825a-0eb0e81f52.zip/node_modules/terser-webpack-plugin/", "packageDependencies": [ @@ -13065,42 +12917,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "webpack-cli" ], "linkType": "HARD", - }], - ["virtual:db46c448d4270fdb3b876d89bfac4ef71013dbbf936984e3bdf75d2625d01d582344f08a024c01ef1b5ce6d880baba103eab42675713e0991f42e83024f39f25#npm:5.37.1", { - "packageLocation": "./.yarn/__virtual__/webpack-virtual-3fc9ad73a2/0/cache/webpack-npm-5.37.1-1e75a59f6f-572d3cd617.zip/node_modules/webpack/", - "packageDependencies": [ - ["webpack", "virtual:db46c448d4270fdb3b876d89bfac4ef71013dbbf936984e3bdf75d2625d01d582344f08a024c01ef1b5ce6d880baba103eab42675713e0991f42e83024f39f25#npm:5.37.1"], - ["@types/eslint-scope", "npm:3.7.0"], - ["@types/estree", "npm:0.0.47"], - ["@types/webpack-cli", null], - ["@webassemblyjs/ast", "npm:1.11.0"], - ["@webassemblyjs/wasm-edit", "npm:1.11.0"], - ["@webassemblyjs/wasm-parser", "npm:1.11.0"], - ["acorn", "npm:8.2.4"], - ["browserslist", "npm:4.16.6"], - ["chrome-trace-event", "npm:1.0.3"], - ["enhanced-resolve", "npm:5.8.2"], - ["es-module-lexer", "npm:0.4.1"], - ["eslint-scope", "npm:5.1.1"], - ["events", "npm:3.3.0"], - ["glob-to-regexp", "npm:0.4.1"], - ["graceful-fs", "npm:4.2.6"], - ["json-parse-better-errors", "npm:1.0.2"], - ["loader-runner", "npm:4.2.0"], - ["mime-types", "npm:2.1.30"], - ["neo-async", "npm:2.6.2"], - ["schema-utils", "npm:3.0.0"], - ["tapable", "npm:2.2.0"], - ["terser-webpack-plugin", "virtual:3fc9ad73a25400af56d4125aff61a9fcb0cd6e665fdaa8ac5c8928896a4cae3b678e19c1bb722ba1f7dd8d9840cb8e3e6257c52c511a8ce7cb8e8e6dd26f35f3#npm:5.1.2"], - ["watchpack", "npm:2.2.0"], - ["webpack-cli", "virtual:db46c448d4270fdb3b876d89bfac4ef71013dbbf936984e3bdf75d2625d01d582344f08a024c01ef1b5ce6d880baba103eab42675713e0991f42e83024f39f25#npm:4.7.0"], - ["webpack-sources", "npm:2.2.0"] - ], - "packagePeers": [ - "@types/webpack-cli", - "webpack-cli" - ], - "linkType": "HARD", }] ]], ["webpack-cli", [ @@ -13698,48 +13514,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "webpack" ], "linkType": "HARD", - }], - ["virtual:db46c448d4270fdb3b876d89bfac4ef71013dbbf936984e3bdf75d2625d01d582344f08a024c01ef1b5ce6d880baba103eab42675713e0991f42e83024f39f25#npm:4.7.0", { - "packageLocation": "./.yarn/__virtual__/webpack-cli-virtual-c40ffa9da9/0/cache/webpack-cli-npm-4.7.0-cb3d7c34ff-cecfb321b9.zip/node_modules/webpack-cli/", - "packageDependencies": [ - ["webpack-cli", "virtual:db46c448d4270fdb3b876d89bfac4ef71013dbbf936984e3bdf75d2625d01d582344f08a024c01ef1b5ce6d880baba103eab42675713e0991f42e83024f39f25#npm:4.7.0"], - ["@discoveryjs/json-ext", "npm:0.5.3"], - ["@types/webpack", null], - ["@types/webpack-bundle-analyzer", null], - ["@types/webpack-cli__generators", null], - ["@types/webpack-cli__migrate", null], - ["@types/webpack-dev-server", null], - ["@webpack-cli/configtest", "virtual:c40ffa9da9410f1eb88a4aced56c0b7274d5471c24490a910b8d88bd5338ba8e40ff4f18351b2936308c9747c07026dcf363a139309f893ddadcb3906c5c9a66#npm:1.0.3"], - ["@webpack-cli/generators", null], - ["@webpack-cli/info", "virtual:c40ffa9da9410f1eb88a4aced56c0b7274d5471c24490a910b8d88bd5338ba8e40ff4f18351b2936308c9747c07026dcf363a139309f893ddadcb3906c5c9a66#npm:1.2.4"], - ["@webpack-cli/migrate", null], - ["@webpack-cli/serve", "virtual:c40ffa9da9410f1eb88a4aced56c0b7274d5471c24490a910b8d88bd5338ba8e40ff4f18351b2936308c9747c07026dcf363a139309f893ddadcb3906c5c9a66#npm:1.4.0"], - ["colorette", "npm:1.2.2"], - ["commander", "npm:7.2.0"], - ["execa", "npm:5.0.0"], - ["fastest-levenshtein", "npm:1.0.12"], - ["import-local", "npm:3.0.2"], - ["interpret", "npm:2.2.0"], - ["rechoir", "npm:0.7.0"], - ["v8-compile-cache", "npm:2.3.0"], - ["webpack", "virtual:db46c448d4270fdb3b876d89bfac4ef71013dbbf936984e3bdf75d2625d01d582344f08a024c01ef1b5ce6d880baba103eab42675713e0991f42e83024f39f25#npm:5.37.1"], - ["webpack-bundle-analyzer", null], - ["webpack-dev-server", null], - ["webpack-merge", "npm:5.7.3"] - ], - "packagePeers": [ - "@types/webpack-bundle-analyzer", - "@types/webpack-cli__generators", - "@types/webpack-cli__migrate", - "@types/webpack-dev-server", - "@types/webpack", - "@webpack-cli/generators", - "@webpack-cli/migrate", - "webpack-bundle-analyzer", - "webpack-dev-server", - "webpack" - ], - "linkType": "HARD", }] ]], ["webpack-merge", [ diff --git a/.yarnrc.yml b/.yarnrc.yml index b01233d8ed..59f3a5e5bf 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -13,6 +13,4 @@ plugins: pnpMode: loose -preferInteractive: true - yarnPath: .yarn/releases/yarn-3.1.0.cjs diff --git a/CHANGELOG.md b/CHANGELOG.md index 46a3ff87be..7fe0189e2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,12 +9,37 @@ and this project adheres to ### Changed - all: The TypeScript compilation target is now ES2018. +- @cosmjs/crypto: Add `Secp256k1.uncompressPubkey`. +- @cosmjs/faucet: Set default value of `FAUCET_GAS_LIMIT` to 100_000 to better + support Cosmos SDK 0.45 chains. - @cosmjs/stargate: The `AminoTypes` now always requires an argument of type `AminoTypesOptions`. This is an object with a required `prefix` field. Before the prefix defaulted to "cosmos" but this is almost never the right choice for CosmJS users that need to add Amino types manually. ([#989]) +- @cosmjs/cosmwasm-stargate: `height`, `gasWanted` and `gasUsed` have been added + to all result types of `SigningCosmWasmClient` +- @cosmjs/stargate: `MsgSend` and `Coin` are now parts of + `defaultRegistryTypes`. ([#994]) +- @cosmjs/proto-signing: `Registry`'s constructor can now override default + types. ([#994]) +- @cosmjs/tendermint-rpc: The property `evidence` in the interface `Block` is + now non-optional. ([#1011]) +- @cosmjs/stargate: Added the following message types to stargate's + `defaultRegistryTypes`: ([#1026]) + - cosmos.authz.v1beta1.MsgGrant + - cosmos.authz.v1beta1.MsgExec + - cosmos.authz.v1beta1.MsgRevoke + - cosmos.feegrant.v1beta1.MsgGrantAllowance + - cosmos.feegrant.v1beta1.MsgRevokeAllowance +- @cosmjs/stargate: In `AminoTypes` the uniqueness of the Amino type identifier + is checked in `fromAmino` now instead of the constructor. This only affects + you if multiple different protobuf type URLs map to the same Amino type + identifier which should not be the case anyways. [#989]: https://github.com/cosmos/cosmjs/issues/989 +[#994]: https://github.com/cosmos/cosmjs/issues/994 +[#1011]: https://github.com/cosmos/cosmjs/issues/1011 +[#1026]: https://github.com/cosmos/cosmjs/issues/1026 ### Removed @@ -64,7 +89,10 @@ and this project adheres to @cosmjs/launchpad. They are re-exported in @cosmjs/launchpad for backwards compatibility. - @cosmjs/stargate: Add `GasPrice.toString`. +- @cosmjs/faucet: Added a new functionality to faucet: Each address is only + allowed to get credits once every 24h to prevent draining. ([#962])) +[#962]: https://github.com/cosmos/cosmjs/issues/962 [#938]: https://github.com/cosmos/cosmjs/issues/938 [#932]: https://github.com/cosmos/cosmjs/issues/932 [#878]: https://github.com/cosmos/cosmjs/issues/878 diff --git a/README.md b/README.md index 2cc73d7b6b..a7e25665c9 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,6 @@ Here are some of them to get an idea: | Package | Description | Latest | | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | [@cosmjs/stargate](packages/stargate) | A client library for the Cosmos SDK 0.40 (cosmoshub-4), 0.41 and 0.42 (Stargate) | [![npm version](https://img.shields.io/npm/v/@cosmjs/stargate.svg)](https://www.npmjs.com/package/@cosmjs/stargate) | -| [@cosmjs/launchpad](packages/launchpad) | A client library for the Cosmos SDK 0.37 (cosmoshub-3), 0.38 and 0.39 (Launchpad) | [![npm version](https://img.shields.io/npm/v/@cosmjs/launchpad.svg)](https://www.npmjs.com/package/@cosmjs/launchpad) | | [@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-stargate](packages/cosmwasm-stargate) | Client for Stargate chains with the CosmWasm module enabled | [![npm version](https://img.shields.io/npm/v/@cosmjs/cosmwasm-stargate.svg)](https://www.npmjs.com/package/@cosmjs/cosmwasm-stargate) | | [@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) | diff --git a/package.json b/package.json index 4cd1d35879..0b7126c6a6 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,6 @@ "@cosmjs/cosmwasm-stargate": "workspace:packages/cosmwasm-stargate", "@cosmjs/crypto": "workspace:packages/crypto", "@cosmjs/encoding": "workspace:packages/encoding", - "@cosmjs/launchpad": "workspace:packages/launchpad", "@cosmjs/proto-signing": "workspace:packages/proto-signing", "@cosmjs/stargate": "workspace:packages/stargate", "eslint": "^7.5", diff --git a/packages/amino/README.md b/packages/amino/README.md index 31c09c376f..c8bb428230 100644 --- a/packages/amino/README.md +++ b/packages/amino/README.md @@ -2,8 +2,7 @@ [![npm version](https://img.shields.io/npm/v/@cosmjs/amino.svg)](https://www.npmjs.com/package/@cosmjs/amino) -Helpers for Amino based signing which are shared between @cosmjs/launchpad and -@cosmjs/stargate. +Helpers for Amino for @cosmjs/stargate. ## License diff --git a/packages/amino/package.json b/packages/amino/package.json index 46cf49989b..1f847ec816 100644 --- a/packages/amino/package.json +++ b/packages/amino/package.json @@ -1,7 +1,7 @@ { "name": "@cosmjs/amino", "version": "0.27.1", - "description": "Helpers for Amino based signing which are shared between @cosmjs/launchpad and @cosmjs/stargate.", + "description": "Helpers for Amino based signing.", "contributors": [ "Simon Warta " ], diff --git a/packages/cli/README.md b/packages/cli/README.md index 274d0b6358..330988c7da 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -45,37 +45,29 @@ $ cosmwasm-cli ```ts // Get account information -const { account_number, sequence } = (await client.authAccounts(faucetAddress)) - .result.value; +const account = await client.getAccount(faucetAddress); // Craft a send transaction const emptyAddress = Bech32.encode("cosmos", Random.getBytes(20)); -const memo = "My first contract on chain"; -const sendTokensMsg: MsgSend = { - type: "cosmos-sdk/MsgSend", - value: { - from_address: faucetAddress, - to_address: emptyAddress, - amount: [ - { - denom: "ucosm", - amount: "1234567", - }, - ], - }, +const memo = "My very first tx!"; +const msgSend = { + fromAddress: faucetAddress, + toAddress: emptyAddress, + amount: coins(1234, "ucosm"), }; -const signDoc = makeSignDoc( - [sendTokensMsg], +const msgAny = { + typeUrl: "/cosmos.bank.v1beta1.MsgSend", + value: msgSend, +}; + +// Broadcast and sign the transaction +const broadcastResult = await client.signAndBroadcast( + faucetAddress, + [msgAny], defaultFee, - defaultNetworkId, memo, - account_number, - sequence, ); -const { signed, signature } = await wallet.signAmino(faucetAddress, signDoc); -const signedTx = makeStdTx(signed, signature); -const broadcastResult = await client.broadcastTx(signedTx); ``` ## Extended helpers diff --git a/packages/cli/examples/delegate.ts b/packages/cli/examples/delegate.ts index 72496c28a9..7e4737034e 100644 --- a/packages/cli/examples/delegate.ts +++ b/packages/cli/examples/delegate.ts @@ -1,45 +1,48 @@ +import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing"; import { coin, - coins, - makeSignDoc, - makeStdTx, - CosmosClient, - MsgDelegate, - Secp256k1HdWallet, -} from "@cosmjs/launchpad"; - -const wallet = await Secp256k1HdWallet.fromMnemonic( + MsgDelegateEncodeObject, + SigningStargateClient, + calculateFee, + assertIsDeliverTxSuccess, + GasPrice, +} from "@cosmjs/stargate"; + +// Wallet +const wallet = await DirectSecp256k1HdWallet.fromMnemonic( "enlist hip relief stomach skate base shallow young switch frequent cry park", ); -const [{ address: senderAddress }] = await wallet.getAccounts(); +const [{ address: signerAddress }] = await wallet.getAccounts(); +console.log("Signer address:", signerAddress); + +// Network config +const rpcEndpoint = "ws://localhost:26658"; +const gasPrice = GasPrice.fromString("0.025ucosm"); -const client = new CosmosClient("http://localhost:1317"); +// Setup client +const client = await SigningStargateClient.connectWithSigner(rpcEndpoint, wallet); -const msg: MsgDelegate = { - type: "cosmos-sdk/MsgDelegate", +// Send delegate transaction +const msg: MsgDelegateEncodeObject = { + typeUrl: "/cosmos.staking.v1beta1.MsgDelegate", value: { - delegator_address: senderAddress, - // To get the proper validator address, start the demo chain (./scripts/launchpad/start.sh), then run: - // curl http://localhost:1317/staking/validators | jq '.result[0].operator_address' - validator_address: "cosmosvaloper1yfkkk04ve8a0sugj4fe6q6zxuvmvza8r3arurr", + delegatorAddress: signerAddress, + // To get the proper validator address, start the demo chain (./scripts/simapp42/start.sh), then run: + // curl http://localhost:1318/staking/validators | jq '.result[0].operator_address' + validatorAddress: "cosmosvaloper1urk9gy7cfws0ak9x5nu7lx4un9n6gqkrp230jk", amount: coin(300000, "ustake"), }, }; -const fee = { - amount: coins(2000, "ucosm"), - gas: "180000", // 180k -}; +const fee = calculateFee(180_000, gasPrice); const memo = "Use your power wisely"; const chainId = await client.getChainId(); console.log("Connected to chain:", chainId); -const { accountNumber, sequence } = await client.getSequence(senderAddress); -console.log("Account/sequence:", accountNumber, sequence); +const result = await client.signAndBroadcast(signerAddress, [msg], fee, memo); +console.log("Broadcast result:", result); -const signDoc = makeSignDoc([msg], fee, chainId, memo, accountNumber, sequence); -const { signed, signature } = await wallet.signAmino(senderAddress, signDoc); -const signedTx = makeStdTx(signed, signature); +assertIsDeliverTxSuccess(result); +console.log("Successfully broadcasted:", result); -const result = await client.broadcastTx(signedTx); -console.log("Broadcast result:", result); +client.disconnect(); diff --git a/packages/cli/examples/local_faucet.ts b/packages/cli/examples/local_faucet.ts index afa4d9600a..dd314be36b 100644 --- a/packages/cli/examples/local_faucet.ts +++ b/packages/cli/examples/local_faucet.ts @@ -1,7 +1,11 @@ -import { LcdClient, Secp256k1HdWallet, StdFee } from "@cosmjs/launchpad"; +import { StdFee, SigningStargateClient } from "@cosmjs/stargate"; +import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing"; +import { MsgSend } from "cosmjs-types/cosmos/bank/v1beta1/tx"; +import { coins } from "@cosmjs/amino"; +import { Bech32 } from "@cosmjs/encoding"; +import { Random } from "@cosmjs/crypto"; -const defaultHttpUrl = "http://localhost:1317"; -const defaultNetworkId = "testing"; +const defaultHttpUrl = "http://localhost:26658"; const defaultFee: StdFee = { amount: [ { @@ -16,5 +20,5 @@ const faucetMnemonic = "economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone"; const faucetAddress = "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6"; -const wallet = await Secp256k1HdWallet.fromMnemonic(faucetMnemonic); -const client = new LcdClient(defaultHttpUrl); +const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucetMnemonic); +const client = await SigningStargateClient.connectWithSigner(defaultHttpUrl, wallet); diff --git a/packages/cli/package.json b/packages/cli/package.json index 1a954f2b39..c4a7dc5ee6 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -45,7 +45,6 @@ "@cosmjs/crypto": "workspace:packages/crypto", "@cosmjs/encoding": "workspace:packages/encoding", "@cosmjs/faucet-client": "workspace:packages/faucet-client", - "@cosmjs/launchpad": "workspace:packages/launchpad", "@cosmjs/math": "workspace:packages/math", "@cosmjs/proto-signing": "workspace:packages/proto-signing", "@cosmjs/stargate": "workspace:packages/stargate", diff --git a/packages/cli/run_examples.sh b/packages/cli/run_examples.sh index c8fcd5c64a..3ae5ca71e2 100755 --- a/packages/cli/run_examples.sh +++ b/packages/cli/run_examples.sh @@ -5,7 +5,7 @@ command -v shellcheck >/dev/null && shellcheck "$0" if [ -n "${WASMD_ENABLED:-}" ]; then yarn node ./bin/cosmwasm-cli --init examples/cosmwasm.ts --code "process.exit(0)" fi -if [ -n "${LAUNCHPAD_ENABLED:-}" ]; then +if [ -n "${SIMAPP42_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)" diff --git a/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts b/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts index 295399aabc..9d9ad47f88 100644 --- a/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts +++ b/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts @@ -123,7 +123,7 @@ describe("SigningCosmWasmClient", () => { const { codeId } = await client.upload(alice.address0, getHackatom().data, defaultUploadFee); const funds = [coin(1234, "ucosm"), coin(321, "ustake")]; const beneficiaryAddress = makeRandomAddress(); - const { contractAddress } = await client.instantiate( + const { contractAddress, height, gasWanted, gasUsed } = await client.instantiate( alice.address0, codeId, { @@ -139,9 +139,12 @@ describe("SigningCosmWasmClient", () => { ); const wasmClient = await makeWasmClient(wasmd.endpoint); const ucosmBalance = await wasmClient.bank.balance(contractAddress, "ucosm"); - expect(ucosmBalance).toEqual(funds[0]); const ustakeBalance = await wasmClient.bank.balance(contractAddress, "ustake"); + expect(ucosmBalance).toEqual(funds[0]); expect(ustakeBalance).toEqual(funds[1]); + expect(height).toBeGreaterThan(0); + expect(gasWanted).toBeGreaterThan(0); + expect(gasUsed).toBeGreaterThan(0); client.disconnect(); }); @@ -152,7 +155,7 @@ describe("SigningCosmWasmClient", () => { const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options); const { codeId } = await client.upload(alice.address0, getHackatom().data, defaultUploadFee); const beneficiaryAddress = makeRandomAddress(); - const { contractAddress } = await client.instantiate( + const { contractAddress, height, gasWanted, gasUsed } = await client.instantiate( alice.address0, codeId, { @@ -166,6 +169,9 @@ describe("SigningCosmWasmClient", () => { const wasmClient = await makeWasmClient(wasmd.endpoint); const { contractInfo } = await wasmClient.wasm.getContractInfo(contractAddress); assert(contractInfo); + expect(height).toBeGreaterThan(0); + expect(gasWanted).toBeGreaterThan(0); + expect(gasUsed).toBeGreaterThan(0); expect(contractInfo.admin).toEqual(unused.address); client.disconnect(); }); @@ -176,7 +182,12 @@ describe("SigningCosmWasmClient", () => { const options = { ...defaultSigningClientOptions, prefix: wasmd.prefix }; const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options); const { codeId } = await client.upload(alice.address0, getHackatom().data, defaultUploadFee); - const { contractAddress: address1 } = await client.instantiate( + const { + contractAddress: address1, + height, + gasWanted, + gasUsed, + } = await client.instantiate( alice.address0, codeId, { @@ -196,6 +207,9 @@ describe("SigningCosmWasmClient", () => { "contract 2", defaultInstantiateFee, ); + expect(height).toBeGreaterThan(0); + expect(gasWanted).toBeGreaterThan(0); + expect(gasUsed).toBeGreaterThan(0); expect(address1).not.toEqual(address2); client.disconnect(); }); @@ -262,11 +276,18 @@ describe("SigningCosmWasmClient", () => { assert(contractInfo1); expect(contractInfo1.admin).toEqual(alice.address0); - await client.updateAdmin(alice.address0, contractAddress, unused.address, defaultUpdateAdminFee); + const { height, gasUsed, gasWanted } = await client.updateAdmin( + alice.address0, + contractAddress, + unused.address, + defaultUpdateAdminFee, + ); const { contractInfo: contractInfo2 } = await wasmClient.wasm.getContractInfo(contractAddress); assert(contractInfo2); expect(contractInfo2.admin).toEqual(unused.address); - + expect(height).toBeGreaterThan(0); + expect(gasWanted).toBeGreaterThan(0); + expect(gasUsed).toBeGreaterThan(0); client.disconnect(); }); }); @@ -297,11 +318,17 @@ describe("SigningCosmWasmClient", () => { assert(contractInfo1); expect(contractInfo1.admin).toEqual(alice.address0); - await client.clearAdmin(alice.address0, contractAddress, defaultClearAdminFee); + const { height, gasUsed, gasWanted } = await client.clearAdmin( + alice.address0, + contractAddress, + defaultClearAdminFee, + ); const { contractInfo: contractInfo2 } = await wasmClient.wasm.getContractInfo(contractAddress); assert(contractInfo2); expect(contractInfo2.admin).toEqual(""); - + expect(height).toBeGreaterThan(0); + expect(gasWanted).toBeGreaterThan(0); + expect(gasUsed).toBeGreaterThan(0); client.disconnect(); }); }); @@ -334,13 +361,16 @@ describe("SigningCosmWasmClient", () => { expect(contractInfo1.admin).toEqual(alice.address0); const newVerifier = makeRandomAddress(); - await client.migrate( + const { height, gasUsed, gasWanted } = await client.migrate( alice.address0, contractAddress, codeId2, { verifier: newVerifier }, defaultMigrateFee, ); + expect(height).toBeGreaterThan(0); + expect(gasWanted).toBeGreaterThan(0); + expect(gasUsed).toBeGreaterThan(0); const { contractInfo: contractInfo2 } = await wasmClient.wasm.getContractInfo(contractAddress); assert(contractInfo2); expect({ ...contractInfo2 }).toEqual({ @@ -424,6 +454,9 @@ describe("SigningCosmWasmClient", () => { { release: {} }, defaultExecuteFee, ); + expect(result.height).toBeGreaterThan(0); + expect(result.gasWanted).toBeGreaterThan(0); + expect(result.gasUsed).toBeGreaterThan(0); const wasmEvent = result.logs[0].events.find((e) => e.type === "wasm"); assert(wasmEvent, "Event of type wasm expected"); expect(wasmEvent.attributes).toContain({ key: "action", value: "release" }); diff --git a/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts b/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts index 05a0e5434b..4ea3c3f801 100644 --- a/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts +++ b/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts @@ -69,8 +69,12 @@ export interface UploadResult { /** The ID of the code asigned by the chain */ readonly codeId: number; readonly logs: readonly logs.Log[]; + /** Block height in which the transaction is included */ + readonly height: number; /** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */ readonly transactionHash: string; + readonly gasWanted: number; + readonly gasUsed: number; } /** @@ -98,8 +102,12 @@ export interface InstantiateResult { /** The address of the newly instantiated contract */ readonly contractAddress: string; readonly logs: readonly logs.Log[]; + /** Block height in which the transaction is included */ + readonly height: number; /** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */ readonly transactionHash: string; + readonly gasWanted: number; + readonly gasUsed: number; } /** @@ -107,20 +115,32 @@ export interface InstantiateResult { */ export interface ChangeAdminResult { readonly logs: readonly logs.Log[]; + /** Block height in which the transaction is included */ + readonly height: number; /** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */ readonly transactionHash: string; + readonly gasWanted: number; + readonly gasUsed: number; } export interface MigrateResult { readonly logs: readonly logs.Log[]; + /** Block height in which the transaction is included */ + readonly height: number; /** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */ readonly transactionHash: string; + readonly gasWanted: number; + readonly gasUsed: number; } export interface ExecuteResult { readonly logs: readonly logs.Log[]; + /** Block height in which the transaction is included */ + readonly height: number; /** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */ readonly transactionHash: string; + readonly gasWanted: number; + readonly gasUsed: number; } function createDeliverTxResponseErrorMessage(result: DeliverTxResponse): string { @@ -249,7 +269,10 @@ export class SigningCosmWasmClient extends CosmWasmClient { compressedChecksum: toHex(sha256(compressed)), codeId: Number.parseInt(codeIdAttr.value, 10), logs: parsedLogs, + height: result.height, transactionHash: result.transactionHash, + gasWanted: result.gasWanted, + gasUsed: result.gasUsed, }; } @@ -281,7 +304,10 @@ export class SigningCosmWasmClient extends CosmWasmClient { return { contractAddress: contractAddressAttr.value, logs: parsedLogs, + height: result.height, transactionHash: result.transactionHash, + gasWanted: result.gasWanted, + gasUsed: result.gasUsed, }; } @@ -306,7 +332,10 @@ export class SigningCosmWasmClient extends CosmWasmClient { } return { logs: logs.parseRawLog(result.rawLog), + height: result.height, transactionHash: result.transactionHash, + gasWanted: result.gasWanted, + gasUsed: result.gasUsed, }; } @@ -329,7 +358,10 @@ export class SigningCosmWasmClient extends CosmWasmClient { } return { logs: logs.parseRawLog(result.rawLog), + height: result.height, transactionHash: result.transactionHash, + gasWanted: result.gasWanted, + gasUsed: result.gasUsed, }; } @@ -356,7 +388,10 @@ export class SigningCosmWasmClient extends CosmWasmClient { } return { logs: logs.parseRawLog(result.rawLog), + height: result.height, transactionHash: result.transactionHash, + gasWanted: result.gasWanted, + gasUsed: result.gasUsed, }; } @@ -383,7 +418,10 @@ export class SigningCosmWasmClient extends CosmWasmClient { } return { logs: logs.parseRawLog(result.rawLog), + height: result.height, transactionHash: result.transactionHash, + gasWanted: result.gasWanted, + gasUsed: result.gasUsed, }; } diff --git a/packages/cosmwasm-stargate/src/testutils.spec.ts b/packages/cosmwasm-stargate/src/testutils.spec.ts index cbec10b833..163fe98d48 100644 --- a/packages/cosmwasm-stargate/src/testutils.spec.ts +++ b/packages/cosmwasm-stargate/src/testutils.spec.ts @@ -27,7 +27,7 @@ import { SigningCosmWasmClientOptions } from "./signingcosmwasmclient"; import hackatom from "./testdata/contract.json"; export const defaultGasPrice = GasPrice.fromString("0.025ucosm"); -export const defaultSendFee = calculateFee(80_000, defaultGasPrice); +export const defaultSendFee = calculateFee(100_000, defaultGasPrice); export const defaultUploadFee = calculateFee(1_500_000, defaultGasPrice); export const defaultInstantiateFee = calculateFee(500_000, defaultGasPrice); export const defaultExecuteFee = calculateFee(200_000, defaultGasPrice); @@ -72,7 +72,7 @@ export const tendermintIdMatcher = /^[0-9A-F]{64}$/; export const base64Matcher = /^(?:[a-zA-Z0-9+/]{4})*(?:|(?:[a-zA-Z0-9+/]{3}=)|(?:[a-zA-Z0-9+/]{2}==)|(?:[a-zA-Z0-9+/]{1}===))$/; // https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#bech32 -export const bech32AddressMatcher = /^[\x21-\x7e]{1,83}1[02-9ac-hj-np-z]{38}$/; +export const bech32AddressMatcher = /^[\x21-\x7e]{1,83}1[02-9ac-hj-np-z]{38,58}$/; export const alice = { mnemonic: "enlist hip relief stomach skate base shallow young switch frequent cry park", @@ -122,17 +122,17 @@ export const deployedHackatom = { instances: [ { beneficiary: alice.address0, - address: "wasm14hj2tavq8fpesdwxxcu44rty3hh90vhujgqwg3", + address: "wasm14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s0phg4d", label: "From deploy_hackatom.js (0)", }, { beneficiary: alice.address1, - address: "wasm1suhgf5svhu4usrurvxzlgn54ksxmn8glszahxx", + address: "wasm1suhgf5svhu4usrurvxzlgn54ksxmn8gljarjtxqnapv8kjnp4nrss5maay", label: "From deploy_hackatom.js (1)", }, { beneficiary: alice.address2, - address: "wasm1yyca08xqdgvjz0psg56z67ejh9xms6l49ntww0", + address: "wasm1yyca08xqdgvjz0psg56z67ejh9xms6l436u8y58m82npdqqhmmtqas0cl7", label: "From deploy_hackatom.js (2)", }, ], @@ -143,8 +143,8 @@ export const deployedIbcReflect = { codeId: 2, instances: [ { - address: "wasm1aakfpghcanxtc45gpqlx8j3rq0zcpyf4duy76f", - ibcPortId: "wasm.wasm1aakfpghcanxtc45gpqlx8j3rq0zcpyf4duy76f", + address: "wasm1aakfpghcanxtc45gpqlx8j3rq0zcpyf49qmhm9mdjrfx036h4z5se0hfnq", + ibcPortId: "wasm.wasm1aakfpghcanxtc45gpqlx8j3rq0zcpyf49qmhm9mdjrfx036h4z5se0hfnq", }, ], }; diff --git a/packages/crypto/src/secp256k1.spec.ts b/packages/crypto/src/secp256k1.spec.ts index 0e90d4a293..fcbcca2c96 100644 --- a/packages/crypto/src/secp256k1.spec.ts +++ b/packages/crypto/src/secp256k1.spec.ts @@ -570,6 +570,30 @@ describe("Secp256k1", () => { }); }); + describe("uncompressPubkey", () => { + it("throws for a pubkey with invalid length", () => { + const pubkey = fromHex("aa".repeat(32)); + expect(() => Secp256k1.uncompressPubkey(pubkey)).toThrowError(/invalid pubkey length/i); + }); + + it("returns an uncompressPubkey pubkey unchanged", () => { + // Test data generated at https://iancoleman.io/bitcoin-key-compression/ + const pubkey = fromHex( + "044f04181eeba35391b858633a765c4a0c189697b40d216354d50890d350c7029013b587a681e836cc187a8164b98a5848a2b89b3173315fdd0740d5032e259cd5", + ); + expect(Secp256k1.uncompressPubkey(pubkey)).toEqual(pubkey); + }); + + it("uncompresses a compressed pubkey", () => { + // Test data generated at https://iancoleman.io/bitcoin-key-compression/ + const uncompressed = fromHex( + "044f04181eeba35391b858633a765c4a0c189697b40d216354d50890d350c7029013b587a681e836cc187a8164b98a5848a2b89b3173315fdd0740d5032e259cd5", + ); + const compressed = fromHex("034f04181eeba35391b858633a765c4a0c189697b40d216354d50890d350c70290"); + expect(Secp256k1.uncompressPubkey(compressed)).toEqual(uncompressed); + }); + }); + describe("trimRecoveryByte", () => { it("throws for a signature with invalid length", () => { const signature = fromHex("aa".repeat(66)); diff --git a/packages/crypto/src/secp256k1.ts b/packages/crypto/src/secp256k1.ts index d9357f9868..b16ca917a1 100644 --- a/packages/crypto/src/secp256k1.ts +++ b/packages/crypto/src/secp256k1.ts @@ -8,11 +8,26 @@ const secp256k1 = new elliptic.ec("secp256k1"); const secp256k1N = new BN("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", "hex"); export interface Secp256k1Keypair { + /** A 32 byte private key */ readonly pubkey: Uint8Array; + /** + * A raw secp256k1 public key. + * + * The type itself does not give you any guarantee if this is + * compressed or uncompressed. If you are unsure where the data + * is coming from, use `Secp256k1.compressPubkey` or + * `Secp256k1.uncompressPubkey` (both idempotent) before processing it. + */ readonly privkey: Uint8Array; } export class Secp256k1 { + /** + * Takes a 32 byte private key and returns a privkey/pubkey pair. + * + * The resulting pubkey is uncompressed. For the use in Cosmos it should + * be compressed first using `Secp256k1.compressPubkey`. + */ public static async makeKeypair(privkey: Uint8Array): Promise { if (privkey.length !== 32) { // is this check missing in secp256k1.validatePrivateKey? @@ -43,10 +58,12 @@ export class Secp256k1 { return out; } - // Creates a signature that is - // - deterministic (RFC 6979) - // - lowS signature - // - DER encoded + /** + * Creates a signature that is + * - deterministic (RFC 6979) + * - lowS signature + * - DER encoded + */ public static async createSignature( messageHash: Uint8Array, privkey: Uint8Array, @@ -110,6 +127,11 @@ export class Secp256k1 { return fromHex(keypair.getPublic(false, "hex")); } + /** + * Takes a compressed or uncompressed pubkey and return a compressed one. + * + * This function is idempotent. + */ public static compressPubkey(pubkey: Uint8Array): Uint8Array { switch (pubkey.length) { case 33: @@ -121,6 +143,22 @@ export class Secp256k1 { } } + /** + * Takes a compressed or uncompressed pubkey and returns an uncompressed one. + * + * This function is idempotent. + */ + public static uncompressPubkey(pubkey: Uint8Array): Uint8Array { + switch (pubkey.length) { + case 33: + return Uint8Array.from(secp256k1.keyFromPublic(pubkey).getPublic(false, "array")); + case 65: + return pubkey; + default: + throw new Error("Invalid pubkey length"); + } + } + public static trimRecoveryByte(signature: Uint8Array): Uint8Array { switch (signature.length) { case 64: diff --git a/packages/faucet-client/README.md b/packages/faucet-client/README.md index a408ecdd96..1424313331 100644 --- a/packages/faucet-client/README.md +++ b/packages/faucet-client/README.md @@ -8,7 +8,7 @@ First of all you will need an instance of wasmd running. From the root directory of this repository: ```sh -./scripts/launchpad/start.sh && ./scripts/launchpad/init.sh +./scripts/wasmd/start.sh && ./scripts/wasmd/init.sh ``` You will also need a faucet. From the root directory of this repository: diff --git a/packages/faucet-client/src/faucetclient.spec.ts b/packages/faucet-client/src/faucetclient.spec.ts index 4d7386cbfd..9928123364 100644 --- a/packages/faucet-client/src/faucetclient.spec.ts +++ b/packages/faucet-client/src/faucetclient.spec.ts @@ -10,7 +10,7 @@ describe("FaucetClient", () => { const faucetUrl = "http://localhost:8000"; const primaryToken = "ucosm"; const secondaryToken = "ustake"; - const defaultAddress = "cosmos14qemq0vw6y3gc3u3e0aty2e764u4gs5le3hada"; + const defaultAddress = "wasm14qemq0vw6y3gc3u3e0aty2e764u4gs5lndxgyk"; it("can be constructed", () => { // http diff --git a/packages/faucet/README.md b/packages/faucet/README.md index 1af4b071a8..66cab433c0 100644 --- a/packages/faucet/README.md +++ b/packages/faucet/README.md @@ -49,7 +49,7 @@ FAUCET_PORT Port of the webserver. Defaults to 8000. FAUCET_MEMO Memo for send transactions. Defaults to unset. FAUCET_GAS_PRICE Gas price for transactions as a comma separated list. Defaults to "0.025ucosm". -FAUCET_GAS_LIMIT Gas limit for send transactions. Defaults to 80000. +FAUCET_GAS_LIMIT Gas limit for send transactions. Defaults to 100000. FAUCET_MNEMONIC Secret mnemonic that serves as the base secret for the faucet HD accounts FAUCET_PATH_PATTERN The pattern of BIP32 paths for the faucet accounts. diff --git a/packages/faucet/package.json b/packages/faucet/package.json index 024447125b..424a9fc7aa 100644 --- a/packages/faucet/package.json +++ b/packages/faucet/package.json @@ -41,7 +41,6 @@ "dependencies": { "@cosmjs/crypto": "workspace:packages/crypto", "@cosmjs/encoding": "workspace:packages/encoding", - "@cosmjs/launchpad": "workspace:packages/launchpad", "@cosmjs/math": "workspace:packages/math", "@cosmjs/proto-signing": "workspace:packages/proto-signing", "@cosmjs/stargate": "workspace:packages/stargate", diff --git a/packages/faucet/src/actions/generate.ts b/packages/faucet/src/actions/generate.ts index 7c47226db3..5f90494d96 100644 --- a/packages/faucet/src/actions/generate.ts +++ b/packages/faucet/src/actions/generate.ts @@ -18,5 +18,5 @@ export async function generate(args: readonly string[]): Promise { console.info(`FAUCET_PATH_PATTERN="${constants.pathPattern}"`); // Log the addresses - await createWallets(mnemonic, pathBuilder, constants.addressPrefix, constants.concurrency, true, true); + await createWallets(mnemonic, pathBuilder, constants.addressPrefix, constants.concurrency, true); } diff --git a/packages/faucet/src/actions/help.ts b/packages/faucet/src/actions/help.ts index 31834d2e7d..e018375332 100644 --- a/packages/faucet/src/actions/help.ts +++ b/packages/faucet/src/actions/help.ts @@ -22,7 +22,7 @@ FAUCET_PORT Port of the webserver. Defaults to 8000. FAUCET_MEMO Memo for send transactions. Defaults to unset. FAUCET_GAS_PRICE Gas price for transactions as a comma separated list. Defaults to "0.025ucosm". -FAUCET_GAS_LIMIT Gas limit for send transactions. Defaults to 80000. +FAUCET_GAS_LIMIT Gas limit for send transactions. Defaults to 100000. FAUCET_MNEMONIC Secret mnemonic that serves as the base secret for the faucet HD accounts FAUCET_PATH_PATTERN The pattern of BIP32 paths for the faucet accounts. diff --git a/packages/faucet/src/actions/start.ts b/packages/faucet/src/actions/start.ts index 71497687bf..5890233c4b 100644 --- a/packages/faucet/src/actions/start.ts +++ b/packages/faucet/src/actions/start.ts @@ -1,4 +1,3 @@ -import { CosmosClient } from "@cosmjs/launchpad"; import { StargateClient } from "@cosmjs/stargate"; import { Webserver } from "../api/webserver"; @@ -17,14 +16,8 @@ export async function start(args: readonly string[]): Promise { // Connection const blockchainBaseUrl = args[0]; console.info(`Connecting to blockchain ${blockchainBaseUrl} ...`); - let chainId; - let stargate = true; - try { - chainId = await (await StargateClient.connect(blockchainBaseUrl)).getChainId(); - } catch (_error) { - chainId = await new CosmosClient(blockchainBaseUrl).getChainId(); - stargate = false; - } + const client = await StargateClient.connect(blockchainBaseUrl); + const chainId = await client.getChainId(); console.info(`Connected to network: ${chainId}`); // Faucet @@ -38,7 +31,6 @@ export async function start(args: readonly string[]): Promise { constants.mnemonic, pathBuilder, constants.concurrency, - stargate, logging, ); const chainTokens = faucet.configuredTokens(); diff --git a/packages/faucet/src/api/webserver.ts b/packages/faucet/src/api/webserver.ts index 4a000531f9..ae17951f1f 100644 --- a/packages/faucet/src/api/webserver.ts +++ b/packages/faucet/src/api/webserver.ts @@ -16,6 +16,7 @@ export interface ChainConstants { export class Webserver { private readonly api = new Koa(); + private readonly addressCounter = new Map(); public constructor(faucet: Faucet, chainConstants: ChainConstants) { this.api.use(cors()); @@ -58,13 +59,22 @@ export class Webserver { // context.request.body is set by the bodyParser() plugin const requestBody = context.request.body; const creditBody = RequestParser.parseCreditBody(requestBody); - const { address, denom } = creditBody; if (!isValidAddress(address, constants.addressPrefix)) { throw new HttpError(400, "Address is not in the expected format for this chain."); } + const entry = this.addressCounter.get(address); + if (entry !== undefined) { + if (entry.getTime() + 24 * 3600 > Date.now()) { + throw new HttpError( + 405, + "Too many request from the same address. Blocked to prevent draining. Please wait 24h and try it again!", + ); + } + } + const availableTokens = await faucet.availableTokens(); const matchingDenom = availableTokens.find((availableDenom) => availableDenom === denom); if (matchingDenom === undefined) { @@ -73,6 +83,8 @@ export class Webserver { try { await faucet.credit(address, matchingDenom); + // Count addresses to prevent draining + this.addressCounter.set(address, new Date()); } catch (e) { console.error(e); throw new HttpError(500, "Sending tokens failed"); diff --git a/packages/faucet/src/constants.ts b/packages/faucet/src/constants.ts index a88b65a920..a6f5350513 100644 --- a/packages/faucet/src/constants.ts +++ b/packages/faucet/src/constants.ts @@ -1,4 +1,4 @@ -import { CosmosFeeTable, GasLimits, GasPrice } from "@cosmjs/launchpad"; +import { GasPrice } from "@cosmjs/stargate"; import { TokenConfiguration } from "./tokenmanager"; import { parseBankTokens } from "./tokens"; @@ -6,9 +6,9 @@ import { parseBankTokens } from "./tokens"; export const binaryName = "cosmos-faucet"; export const memo: string | undefined = process.env.FAUCET_MEMO; export const gasPrice = GasPrice.fromString(process.env.FAUCET_GAS_PRICE || "0.025ucosm"); -export const gasLimits: GasLimits = { - send: parseInt(process.env.FAUCET_GAS_LIMIT || "80000", 10), -}; +export const gasLimitSend = process.env.FAUCET_GAS_LIMIT + ? parseInt(process.env.FAUCET_GAS_LIMIT, 10) + : 100_000; export const concurrency: number = Number.parseInt(process.env.FAUCET_CONCURRENCY || "", 10) || 5; export const port: number = Number.parseInt(process.env.FAUCET_PORT || "", 10) || 8000; export const mnemonic: string | undefined = process.env.FAUCET_MNEMONIC; diff --git a/packages/faucet/src/debugging.ts b/packages/faucet/src/debugging.ts index 85063d7cdf..bad1055274 100644 --- a/packages/faucet/src/debugging.ts +++ b/packages/faucet/src/debugging.ts @@ -1,4 +1,4 @@ -import { Coin } from "@cosmjs/launchpad"; +import { Coin } from "@cosmjs/stargate"; import { MinimalAccount, SendJob } from "./types"; diff --git a/packages/faucet/src/faucet.spec.ts b/packages/faucet/src/faucet.spec.ts index 21b42b2fba..1dc8eacf91 100644 --- a/packages/faucet/src/faucet.spec.ts +++ b/packages/faucet/src/faucet.spec.ts @@ -1,18 +1,11 @@ import { Random } from "@cosmjs/crypto"; import { Bech32 } from "@cosmjs/encoding"; -import { CosmosClient } from "@cosmjs/launchpad"; import { makeCosmoshubPath, StargateClient } from "@cosmjs/stargate"; import { assert } from "@cosmjs/utils"; import { Faucet } from "./faucet"; import { TokenConfiguration } from "./tokenmanager"; -function pendingWithoutLaunchpad(): void { - if (!process.env.LAUNCHPAD_ENABLED) { - return pending("Set LAUNCHPAD_ENABLED to enable Launchpad node-based tests"); - } -} - function pendingWithoutSimapp(): void { if (!process.env.SIMAPP42_ENABLED && !process.env.SIMAPP44_ENABLED) { return pending("Set SIMAPP42_ENABLED or SIMAPP44_ENABLED to enabled Stargate node-based tests"); @@ -34,237 +27,20 @@ const faucetMnemonic = describe("Faucet", () => { const pathBuilder = makeCosmoshubPath; - describe("launchpad", () => { - const apiUrl = "http://localhost:1317"; - const stargate = false; - - describe("constructor", () => { - it("can be constructed", async () => { - pendingWithoutLaunchpad(); - const faucet = await Faucet.make( - apiUrl, - defaultAddressPrefix, - defaultTokenConfig, - faucetMnemonic, - pathBuilder, - 3, - stargate, - ); - expect(faucet).toBeTruthy(); - }); - }); - - describe("availableTokens", () => { - it("is empty when no tokens are configured", async () => { - pendingWithoutLaunchpad(); - const faucet = await Faucet.make( - apiUrl, - defaultAddressPrefix, - { bankTokens: [] }, - faucetMnemonic, - pathBuilder, - 3, - stargate, - ); - const tickers = await faucet.availableTokens(); - expect(tickers).toEqual([]); - }); - - it("is not empty with default token config", async () => { - pendingWithoutLaunchpad(); - const faucet = await Faucet.make( - apiUrl, - defaultAddressPrefix, - defaultTokenConfig, - faucetMnemonic, - pathBuilder, - 3, - stargate, - ); - const tickers = await faucet.availableTokens(); - expect(tickers).toEqual(["ucosm", "ustake"]); - }); - }); + const apiUrl = "localhost:26658"; + const stargate = true; + let originalEnvVariable: string | undefined; - describe("send", () => { - it("can send bank token", async () => { - pendingWithoutLaunchpad(); - const faucet = await Faucet.make( - apiUrl, - defaultAddressPrefix, - defaultTokenConfig, - faucetMnemonic, - pathBuilder, - 3, - stargate, - ); - const recipient = makeRandomAddress(); - await faucet.send({ - amount: { - amount: "23456", - denom: "ucosm", - }, - sender: faucet.holderAddress, - recipient: recipient, - }); - - const readOnlyClient = new CosmosClient(apiUrl); - const account = await readOnlyClient.getAccount(recipient); - assert(account); - expect(account.balance).toEqual([ - { - amount: "23456", - denom: "ucosm", - }, - ]); - }); - }); - - describe("refill", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const faucet = await Faucet.make( - apiUrl, - defaultAddressPrefix, - defaultTokenConfig, - faucetMnemonic, - pathBuilder, - 3, - stargate, - ); - await faucet.refill(); - const readOnlyClient = new CosmosClient(apiUrl); - const distributorBalance = (await readOnlyClient.getAccount(faucet.distributorAddresses[0]))?.balance; - assert(distributorBalance); - expect(distributorBalance).toEqual([ - jasmine.objectContaining({ - denom: "ucosm", - }), - jasmine.objectContaining({ - denom: "ustake", - }), - ]); - expect(Number.parseInt(distributorBalance[0].amount, 10)).toBeGreaterThanOrEqual(80_000000); - expect(Number.parseInt(distributorBalance[1].amount, 10)).toBeGreaterThanOrEqual(80_000000); - }); - }); - - describe("credit", () => { - it("works for fee token", async () => { - pendingWithoutLaunchpad(); - const faucet = await Faucet.make( - apiUrl, - defaultAddressPrefix, - defaultTokenConfig, - faucetMnemonic, - pathBuilder, - 3, - stargate, - ); - const recipient = makeRandomAddress(); - await faucet.credit(recipient, "ucosm"); - - const readOnlyClient = new CosmosClient(apiUrl); - const account = await readOnlyClient.getAccount(recipient); - assert(account); - expect(account.balance).toEqual([ - { - amount: "10000000", - denom: "ucosm", - }, - ]); - }); - - it("works for stake token", async () => { - pendingWithoutLaunchpad(); - const faucet = await Faucet.make( - apiUrl, - defaultAddressPrefix, - defaultTokenConfig, - faucetMnemonic, - pathBuilder, - 3, - stargate, - ); - const recipient = makeRandomAddress(); - await faucet.credit(recipient, "ustake"); - - const readOnlyClient = new CosmosClient(apiUrl); - const account = await readOnlyClient.getAccount(recipient); - assert(account); - expect(account.balance).toEqual([ - { - amount: "10000000", - denom: "ustake", - }, - ]); - }); - }); - - describe("configuredTokens", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const faucet = await Faucet.make( - apiUrl, - defaultAddressPrefix, - defaultTokenConfig, - faucetMnemonic, - pathBuilder, - 3, - stargate, - ); - const tickers = faucet.configuredTokens(); - expect(tickers).toEqual(["ucosm", "ustake"]); - }); - }); - - describe("loadAccounts", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const faucet = await Faucet.make( - apiUrl, - defaultAddressPrefix, - defaultTokenConfig, - faucetMnemonic, - pathBuilder, - 1, - stargate, - ); - const accounts = await faucet.loadAccounts(); + beforeAll(() => { + originalEnvVariable = process.env.FAUCET_CREDIT_AMOUNT_USTAKE; + process.env.FAUCET_CREDIT_AMOUNT_USTAKE = "100000"; + }); - const readOnlyClient = new CosmosClient(apiUrl); - const expectedHolderAccount = await readOnlyClient.getAccount(faucet.holderAddress); - const expectedDistributorAccount = await readOnlyClient.getAccount(faucet.distributorAddresses[0]); - assert(expectedHolderAccount); - assert(expectedDistributorAccount); - expect(accounts).toEqual([ - jasmine.objectContaining({ - address: expectedHolderAccount.address, - balance: expectedHolderAccount.balance, - }), - jasmine.objectContaining({ - address: expectedDistributorAccount.address, - balance: expectedDistributorAccount.balance, - }), - ]); - }); - }); + afterAll(() => { + process.env.FAUCET_CREDIT_AMOUNT_USTAKE = originalEnvVariable; }); describe("stargate", () => { - const apiUrl = "localhost:26658"; - const stargate = true; - let originalEnvVariable: string | undefined; - - beforeAll(() => { - originalEnvVariable = process.env.FAUCET_CREDIT_AMOUNT_USTAKE; - process.env.FAUCET_CREDIT_AMOUNT_USTAKE = "100000"; - }); - - afterAll(() => { - process.env.FAUCET_CREDIT_AMOUNT_USTAKE = originalEnvVariable; - }); - describe("constructor", () => { it("can be constructed", async () => { pendingWithoutSimapp(); diff --git a/packages/faucet/src/faucet.ts b/packages/faucet/src/faucet.ts index a436938327..bf9bd760c7 100644 --- a/packages/faucet/src/faucet.ts +++ b/packages/faucet/src/faucet.ts @@ -1,8 +1,3 @@ -import { - assertIsBroadcastTxSuccess as assertIsBroadcastTxSuccessLaunchpad, - CosmosClient, - SigningCosmosClient, -} from "@cosmjs/launchpad"; import { assertIsDeliverTxSuccess as assertIsDeliverTxSuccessStargate, calculateFee, @@ -30,19 +25,11 @@ export class Faucet { mnemonic: string, pathBuilder: PathBuilder, numberOfDistributors: number, - stargate = true, logging = false, ): Promise { - const wallets = await createWallets( - mnemonic, - pathBuilder, - addressPrefix, - numberOfDistributors, - stargate, - logging, - ); + const wallets = await createWallets(mnemonic, pathBuilder, addressPrefix, numberOfDistributors, logging); const clients = await createClients(apiUrl, wallets); - const readonlyClient = stargate ? await StargateClient.connect(apiUrl) : new CosmosClient(apiUrl); + const readonlyClient = await StargateClient.connect(apiUrl); return new Faucet(addressPrefix, config, clients, readonlyClient, logging); } @@ -52,16 +39,16 @@ export class Faucet { private readonly tokenConfig: TokenConfiguration; private readonly tokenManager: TokenManager; - private readonly readOnlyClient: CosmosClient | StargateClient; - private readonly clients: { [senderAddress: string]: SigningCosmosClient | SigningStargateClient }; + private readonly readOnlyClient: StargateClient; + private readonly clients: { [senderAddress: string]: SigningStargateClient }; private readonly logging: boolean; private creditCount = 0; private constructor( addressPrefix: string, config: TokenConfiguration, - clients: ReadonlyArray, - readonlyClient: CosmosClient | StargateClient, + clients: ReadonlyArray, + readonlyClient: StargateClient, logging = false, ) { this.addressPrefix = addressPrefix; @@ -94,11 +81,7 @@ export class Faucet { */ public async send(job: SendJob): Promise { const client = this.clients[job.sender]; - if (client instanceof SigningCosmosClient) { - const result = await client.sendTokens(job.recipient, [job.amount], constants.memo); - return assertIsBroadcastTxSuccessLaunchpad(result); - } - const fee = calculateFee(constants.gasLimits.send, constants.gasPrice); + const fee = calculateFee(constants.gasLimitSend, constants.gasPrice); const result = await client.sendTokens(job.sender, job.recipient, [job.amount], fee, constants.memo); assertIsDeliverTxSuccessStargate(result); } @@ -122,11 +105,7 @@ export class Faucet { } public async loadAccount(address: string): Promise { - const balance = - this.readOnlyClient instanceof CosmosClient - ? (await this.readOnlyClient.getAccount(address))?.balance ?? [] - : await this.readOnlyClient.getAllBalances(address); - + const balance = await this.readOnlyClient.getAllBalances(address); return { address: address, balance: balance, diff --git a/packages/faucet/src/profile.ts b/packages/faucet/src/profile.ts index 40d35b2737..a29eb25432 100644 --- a/packages/faucet/src/profile.ts +++ b/packages/faucet/src/profile.ts @@ -1,9 +1,7 @@ import { pathToString } from "@cosmjs/crypto"; -import { Secp256k1HdWallet, SigningCosmosClient } from "@cosmjs/launchpad"; -import { DirectSecp256k1HdWallet, isOfflineDirectSigner, OfflineSigner } from "@cosmjs/proto-signing"; +import { DirectSecp256k1HdWallet, OfflineSigner } from "@cosmjs/proto-signing"; import { SigningStargateClient } from "@cosmjs/stargate"; -import * as constants from "./constants"; import { PathBuilder } from "./pathbuilder"; export async function createWallets( @@ -11,17 +9,18 @@ export async function createWallets( pathBuilder: PathBuilder, addressPrefix: string, numberOfDistributors: number, - stargate: boolean, logging: boolean, ): Promise> { - const createWallet = stargate ? DirectSecp256k1HdWallet.fromMnemonic : Secp256k1HdWallet.fromMnemonic; const wallets = new Array(); // first account is the token holder const numberOfIdentities = 1 + numberOfDistributors; for (let i = 0; i < numberOfIdentities; i++) { const path = pathBuilder(i); - const wallet = await createWallet(mnemonic, { hdPaths: [path], prefix: addressPrefix }); + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, { + hdPaths: [path], + prefix: addressPrefix, + }); const [{ address }] = await wallet.getAccounts(); if (logging) { const role = i === 0 ? "token holder " : `distributor ${i}`; @@ -36,18 +35,13 @@ export async function createWallets( export async function createClients( apiUrl: string, wallets: ReadonlyArray, -): Promise> { +): Promise> { // we need one client per sender - return Promise.all( - wallets.map( - async ([senderAddress, wallet]): Promise< - readonly [string, SigningCosmosClient | SigningStargateClient] - > => [ - senderAddress, - isOfflineDirectSigner(wallet) - ? await SigningStargateClient.connectWithSigner(apiUrl, wallet) - : new SigningCosmosClient(apiUrl, senderAddress, wallet, constants.gasPrice, constants.gasLimits), - ], - ), + const pendingClients = wallets.map( + async ([senderAddress, wallet]): Promise => [ + senderAddress, + await SigningStargateClient.connectWithSigner(apiUrl, wallet), + ], ); + return Promise.all(pendingClients); } diff --git a/packages/faucet/src/tokenmanager.ts b/packages/faucet/src/tokenmanager.ts index b8e249a4ce..e0f283bbe2 100644 --- a/packages/faucet/src/tokenmanager.ts +++ b/packages/faucet/src/tokenmanager.ts @@ -1,5 +1,5 @@ -import { Coin } from "@cosmjs/launchpad"; import { Decimal, Uint53 } from "@cosmjs/math"; +import { Coin } from "@cosmjs/stargate"; import { MinimalAccount } from "./types"; diff --git a/packages/faucet/src/types.ts b/packages/faucet/src/types.ts index 9241c57261..f031d29a54 100644 --- a/packages/faucet/src/types.ts +++ b/packages/faucet/src/types.ts @@ -1,4 +1,4 @@ -import { Account, Coin } from "@cosmjs/launchpad"; +import { Coin } from "@cosmjs/stargate"; export interface SendJob { readonly sender: string; @@ -6,4 +6,8 @@ export interface SendJob { readonly amount: Coin; } -export type MinimalAccount = Pick; +export interface MinimalAccount { + /** Bech32 account address */ + readonly address: string; + readonly balance: readonly Coin[]; +} diff --git a/packages/launchpad/.eslintignore b/packages/launchpad/.eslintignore deleted file mode 120000 index 86039baf54..0000000000 --- a/packages/launchpad/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -../../.eslintignore \ No newline at end of file diff --git a/packages/launchpad/.eslintrc.js b/packages/launchpad/.eslintrc.js deleted file mode 100644 index b76dd7be36..0000000000 --- a/packages/launchpad/.eslintrc.js +++ /dev/null @@ -1,94 +0,0 @@ -module.exports = { - env: { - es6: true, - jasmine: true, - node: true, - worker: true, - }, - parser: "@typescript-eslint/parser", - parserOptions: { - ecmaVersion: 2018, - project: "./tsconfig.eslint.json", - tsconfigRootDir: __dirname, - }, - plugins: ["@typescript-eslint", "prettier", "simple-import-sort", "import"], - extends: [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "prettier", - "plugin:prettier/recommended", - "plugin:import/typescript", - ], - rules: { - curly: ["warn", "multi-line", "consistent"], - "no-bitwise": "warn", - "no-console": ["warn", { allow: ["error", "info", "table", "warn"] }], - "no-param-reassign": "warn", - "no-shadow": "off", // disabled in favour of @typescript-eslint/no-shadow, see https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-shadow.md - "no-unused-vars": "off", // disabled in favour of @typescript-eslint/no-unused-vars, see https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unused-vars.md - "prefer-const": "warn", - radix: ["warn", "always"], - "spaced-comment": ["warn", "always", { line: { markers: ["/ { - const [{ address: authorAddress }] = await signer.getAccounts(); - - const memo = "My first proposal on chain"; - const msg: MsgSubmitProposal = { - type: "cosmos-sdk/MsgSubmitProposal", - value: { - content: { - type: "cosmos-sdk/TextProposal", - value: { - description: - "This proposal proposes to test whether this proposal passes", - title: "Test Proposal", - }, - }, - proposer: authorAddress, - initial_deposit: coins(25000000, "ustake"), - }, - }; - const fee: StdFee = { - amount: coins(5000000, "ucosm"), - gas: "89000000", - }; - - const client = new SigningCosmosClient(apiUrl, authorAddress, signer); - return client.signAndBroadcast([msg], fee, memo); -} -``` - -### Custom modules - -Both query and message support is implemented in a decentralized fashion, which -allows applications to add their extensions without changing CosmJS. As an -example we show how to build a client for a blockchain with a wasm module: - -```ts -import { - MsgExecuteContract, - setupWasmExtension, -} from "@cosmjs/cosmwasm-launchpad"; -import { - assertIsBroadcastTxResult, - LcdClient, - makeSignDoc, - setupAuthExtension, - StdFee, - StdTx, -} from "@cosmjs/launchpad"; - -const client = LcdClient.withExtensions( - { apiUrl }, - setupAuthExtension, - // 👇 this extension can come from a chain-specific package or the application itself - setupWasmExtension, -); - -// 👇 this message type can come from a chain-specific package or the application itself -const msg: MsgExecuteContract = { - type: "wasm/MsgExecuteContract", - value: { - sender: myAddress, - contract: contractAddress, - msg: wasmMsg, - sent_funds: [], - }, -}; - -const fee: StdFee = { - amount: coins(5000000, "ucosm"), - gas: "89000000", -}; -const memo = "Time for action"; -const { account_number, sequence } = (await client.auth.account(myAddress)) - .result.value; -const signDoc = makeSignDoc([msg], fee, apiUrl, memo, account_number, sequence); -const { signed, signature } = await signer.sign(myAddress, signDoc); -const signedTx = makeStdTx(signed, signature); -const result = await client.broadcastTx(signedTx); -assertIsBroadcastTxResult(result); -``` - -## Secure key storage - -[Secp256k1HdWallet](https://cosmwasm.github.io/cosmjs/latest/launchpad/classes/secp256k1hdwallet.html) -supports securely encrypted serialization/deserialization using Argon2 for key -derivation and XChaCha20Poly1305 for authenticated encryption. It can be used as -easily as: - -```ts -// generate an 18 word mnemonic -const wallet = await Secp256k1HdWallet.generate(18); -const serialized = await original.serialize("my password"); - -// serialized is encrypted and can now be stored in an application-specific way - -const restored = await Secp256k1HdWallet.deserialize(serialized, "my password"); -``` - -If you want to use really strong KDF parameters in a user interface, you should -offload the KDF execution to a separate thread in order to avoid freezing the -UI. This can be done in the advanced mode: - -**Session 1 (main thread)** - -```ts -const wallet = await Secp256k1HdWallet.generate(18); -``` - -**Session 1 (WebWorker)** - -This operation can now run a couple of seconds without freezing the UI. - -```ts -import { executeKdf } from "@cosmjs/launchpad"; - -// pass password to the worker - -const strongKdfParams: KdfConfiguration = { - algorithm: "argon2id", - params: { - outputLength: 32, - opsLimit: 5000, - memLimitKib: 15 * 1024, - }, -}; -const encryptionKey = await executeKdf(password, strongKdfParams); - -// pass encryptionKey to the main thread -``` - -**Session 1 (main thread)** - -```ts -const serialized = await wallet.serializeWithEncryptionKey( - encryptionKey, - anyKdfParams, -); -``` - -**Session 2 (WebWorker)** - -```ts -import { executeKdf, extractKdfConfiguration } from "@cosmjs/launchpad"; - -// pass serialized and password to the worker - -const kdfConfiguration = extractKdfConfiguration(serialized); -const encryptionKey = await executeKdf(password, kdfConfiguration); - -// pass encryptionKey to the main thread -``` - -**Session 2 (main thead)** - -```ts -const restored = await Secp256k1HdWallet.deserializeWithEncryptionKey( - serialized, - encryptionKey, -); - -// use restored for signing -``` - -## License - -This package is part of the cosmjs repository, licensed under the Apache License -2.0 (see [NOTICE](https://github.com/cosmos/cosmjs/blob/main/NOTICE) and -[LICENSE](https://github.com/cosmos/cosmjs/blob/main/LICENSE)). diff --git a/packages/launchpad/jasmine-testrunner.js b/packages/launchpad/jasmine-testrunner.js deleted file mode 100644 index afefb63a40..0000000000 --- a/packages/launchpad/jasmine-testrunner.js +++ /dev/null @@ -1,38 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ - -if (process.env.SES_ENABLED) { - require("ses/lockdown"); - // eslint-disable-next-line no-undef - lockdown(); -} - -require("source-map-support").install(); -const defaultSpecReporterConfig = require("../../jasmine-spec-reporter.config.json"); - -// setup Jasmine -const Jasmine = require("jasmine"); -const jasmine = new Jasmine(); -jasmine.loadConfig({ - spec_dir: "build", - spec_files: ["**/*.spec.js"], - helpers: [], - random: false, - seed: null, - stopSpecOnExpectationFailure: false, -}); -jasmine.jasmine.DEFAULT_TIMEOUT_INTERVAL = 15 * 1000; - -// setup reporter -const { SpecReporter } = require("jasmine-spec-reporter"); -const reporter = new SpecReporter({ - ...defaultSpecReporterConfig, - spec: { - ...defaultSpecReporterConfig.spec, - displaySuccessful: !process.argv.includes("--quiet"), - }, -}); - -// initialize and execute -jasmine.env.clearReporters(); -jasmine.addReporter(reporter); -void jasmine.execute(); diff --git a/packages/launchpad/karma.conf.js b/packages/launchpad/karma.conf.js deleted file mode 100644 index 31c44e8edf..0000000000 --- a/packages/launchpad/karma.conf.js +++ /dev/null @@ -1,54 +0,0 @@ -const chrome = require("karma-chrome-launcher"); -const firefox = require("karma-firefox-launcher"); -const jasmine = require("karma-jasmine"); -const kjhtml = require("karma-jasmine-html-reporter"); - -module.exports = function (config) { - config.set({ - // base path that will be used to resolve all patterns (eg. files, exclude) - basePath: ".", - // registers plugins but does not activate them - plugins: [jasmine, kjhtml, chrome, firefox], - - // frameworks to use - // available frameworks: https://npmjs.org/browse/keyword/karma-adapter - frameworks: ["jasmine"], - - // list of files / patterns to load in the browser - files: ["dist/web/tests.js"], - - client: { - jasmine: { - random: false, - timeoutInterval: 15000, - }, - }, - - // test results reporter to use - // possible values: 'dots', 'progress' - // available reporters: https://npmjs.org/browse/keyword/karma-reporter - reporters: ["progress", "kjhtml"], - - // web server port - port: 9876, - - // enable / disable colors in the output (reporters and logs) - colors: true, - - // level of logging - // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG - logLevel: config.LOG_INFO, - - // enable / disable watching file and executing tests whenever any file changes - autoWatch: false, - - // start these browsers - // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher - browsers: ["Firefox"], - - browserNoActivityTimeout: 90000, - - // Keep brower open for debugging. This is overridden by yarn scripts - singleRun: false, - }); -}; diff --git a/packages/launchpad/package.json b/packages/launchpad/package.json deleted file mode 100644 index ca03f2c91d..0000000000 --- a/packages/launchpad/package.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "name": "@cosmjs/launchpad", - "version": "0.27.1", - "description": "A client library for the Cosmos SDK 0.37 (cosmoshub-3), 0.38 and 0.39 (Launchpad)", - "contributors": [ - "Ethan Frey ", - "Simon Warta " - ], - "license": "Apache-2.0", - "main": "build/index.js", - "types": "build/index.d.ts", - "files": [ - "build/", - "*.md", - "!*.spec.*", - "!**/testdata/" - ], - "repository": { - "type": "git", - "url": "https://github.com/cosmos/cosmjs/tree/main/packages/launchpad" - }, - "publishConfig": { - "access": "public", - "registry": "https://registry.npmjs.org" - }, - "scripts": { - "docs": "typedoc --options typedoc.js", - "format": "prettier --write --loglevel warn \"./src/**/*.ts\"", - "format-text": "prettier --write \"./*.md\"", - "lint": "eslint --max-warnings 0 \"./**/*.ts\" \"./*.js\"", - "lint-fix": "eslint --fix --max-warnings 0 \"./**/*.ts\" \"./*.js\"", - "build": "rm -rf ./build && tsc", - "build-or-skip": "[ -n \"$SKIP_BUILD\" ] || yarn build", - "test-node": "yarn node jasmine-testrunner.js", - "test-firefox": "yarn pack-web && karma start --single-run --browsers Firefox", - "test-chrome": "yarn pack-web && karma start --single-run --browsers ChromeHeadless", - "test": "yarn build-or-skip && yarn test-node", - "coverage": "nyc --reporter=text --reporter=lcov yarn test --quiet", - "pack-web": "yarn build-or-skip && webpack --mode development --config webpack.web.config.js" - }, - "dependencies": { - "@cosmjs/amino": "workspace:packages/amino", - "@cosmjs/crypto": "workspace:packages/crypto", - "@cosmjs/encoding": "workspace:packages/encoding", - "@cosmjs/math": "workspace:packages/math", - "@cosmjs/utils": "workspace:packages/utils", - "axios": "^0.21.2", - "fast-deep-equal": "^3.1.3" - }, - "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.1", - "@types/eslint-plugin-prettier": "^3", - "@types/jasmine": "^3.8", - "@types/karma-firefox-launcher": "^2", - "@types/karma-jasmine": "^4", - "@types/karma-jasmine-html-reporter": "^1", - "@types/node": "^15.0.1", - "@typescript-eslint/eslint-plugin": "^4.28", - "@typescript-eslint/parser": "^4.28", - "eslint": "^7.5", - "eslint-config-prettier": "^8.3.0", - "eslint-import-resolver-node": "^0.3.4", - "eslint-plugin-import": "^2.22.1", - "eslint-plugin-prettier": "^3.4.0", - "eslint-plugin-simple-import-sort": "^7.0.0", - "esm": "^3.2.25", - "glob": "^7.1.6", - "jasmine": "^3.8", - "jasmine-core": "^3.7.1", - "jasmine-spec-reporter": "^6", - "karma": "^6.1.1", - "karma-chrome-launcher": "^3.1.0", - "karma-firefox-launcher": "^2.1.0", - "karma-jasmine": "^4.0.1", - "karma-jasmine-html-reporter": "^1.5.4", - "nyc": "^15.1.0", - "prettier": "^2.4.1", - "readonly-date": "^1.0.0", - "ses": "^0.11.0", - "source-map-support": "^0.5.19", - "stream-browserify": "^3.0.0", - "ts-node": "^8", - "typedoc": "^0.22", - "typescript": "~4.4", - "webpack": "^5.32.0", - "webpack-cli": "^4.6.0" - } -} diff --git a/packages/launchpad/src/cosmosclient.searchtx.spec.ts b/packages/launchpad/src/cosmosclient.searchtx.spec.ts deleted file mode 100644 index 0262b561b9..0000000000 --- a/packages/launchpad/src/cosmosclient.searchtx.spec.ts +++ /dev/null @@ -1,304 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { coins, makeSignDoc, makeStdTx, Secp256k1HdWallet } from "@cosmjs/amino"; -import { assert, sleep } from "@cosmjs/utils"; - -import { CosmosClient, isBroadcastTxFailure } from "./cosmosclient"; -import { LcdClient } from "./lcdapi"; -import { isMsgSend, MsgSend } from "./msgs"; -import { SigningCosmosClient } from "./signingcosmosclient"; -import { - faucet, - fromOneElementArray, - launchpad, - launchpadEnabled, - makeRandomAddress, - pendingWithoutLaunchpad, -} from "./testutils.spec"; -import { WrappedStdTx } from "./tx"; - -interface TestTxSend { - readonly sender: string; - readonly recipient: string; - readonly hash: string; - readonly height: number; - readonly tx: WrappedStdTx; -} - -describe("CosmosClient.getTx and .searchTx", () => { - let sendUnsuccessful: TestTxSend | undefined; - let sendSuccessful: TestTxSend | undefined; - - beforeAll(async () => { - if (launchpadEnabled()) { - const wallet = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic); - const accounts = await wallet.getAccounts(); - const [{ address: walletAddress }] = accounts; - const client = new SigningCosmosClient(launchpad.endpoint, faucet.address0, wallet); - - { - const memo = "Sending more than I can afford"; - const recipient = makeRandomAddress(); - const amount = coins(123456700000000, "ucosm"); - const sendMsg: MsgSend = { - type: "cosmos-sdk/MsgSend", - value: { - from_address: faucet.address0, - to_address: recipient, - amount: amount, - }, - }; - const fee = { - amount: coins(2000, "ucosm"), - gas: "80000", // 80k - }; - const { accountNumber, sequence } = await client.getSequence(); - const chainId = await client.getChainId(); - const signDoc = makeSignDoc([sendMsg], fee, chainId, memo, accountNumber, sequence); - const { signed, signature } = await wallet.signAmino(walletAddress, signDoc); - const tx: WrappedStdTx = { - type: "cosmos-sdk/StdTx", - value: makeStdTx(signed, signature), - }; - const transactionId = await client.getIdentifier(tx); - const result = await client.broadcastTx(tx.value); - if (isBroadcastTxFailure(result)) { - sendUnsuccessful = { - sender: faucet.address0, - recipient: recipient, - hash: transactionId, - height: result.height, - tx: tx, - }; - } - } - - { - const recipient = makeRandomAddress(); - const amount = coins(1234567, "ucosm"); - const result = await client.sendTokens(recipient, amount); - await sleep(75); // wait until tx is indexed - const txDetails = await new LcdClient(launchpad.endpoint).txById(result.transactionHash); - sendSuccessful = { - sender: faucet.address0, - recipient: recipient, - hash: result.transactionHash, - height: Number.parseInt(txDetails.height, 10), - tx: txDetails.tx, - }; - } - } - }); - - describe("getTx", () => { - it("can get successful tx by ID", async () => { - pendingWithoutLaunchpad(); - assert(sendSuccessful, "value must be set in beforeAll()"); - const client = new CosmosClient(launchpad.endpoint); - const result = await client.getTx(sendSuccessful.hash); - expect(result).toEqual( - jasmine.objectContaining({ - height: sendSuccessful.height, - hash: sendSuccessful.hash, - code: 0, - tx: sendSuccessful.tx, - }), - ); - }); - - it("can get unsuccessful tx by ID", async () => { - pendingWithoutLaunchpad(); - assert(sendUnsuccessful, "value must be set in beforeAll()"); - const client = new CosmosClient(launchpad.endpoint); - const result = await client.getTx(sendUnsuccessful.hash); - expect(result).toEqual( - jasmine.objectContaining({ - height: sendUnsuccessful.height, - hash: sendUnsuccessful.hash, - code: 5, - tx: sendUnsuccessful.tx, - }), - ); - }); - - it("can get by ID (non existent)", async () => { - pendingWithoutLaunchpad(); - const client = new CosmosClient(launchpad.endpoint); - const nonExistentId = "0000000000000000000000000000000000000000000000000000000000000000"; - const result = await client.getTx(nonExistentId); - expect(result).toBeNull(); - }); - }); - - describe("with SearchByHeightQuery", () => { - it("can search successful tx by height", async () => { - pendingWithoutLaunchpad(); - assert(sendSuccessful, "value must be set in beforeAll()"); - const client = new CosmosClient(launchpad.endpoint); - const result = await client.searchTx({ height: sendSuccessful.height }); - expect(result.length).toBeGreaterThanOrEqual(1); - expect(result).toContain( - jasmine.objectContaining({ - height: sendSuccessful.height, - hash: sendSuccessful.hash, - code: 0, - tx: sendSuccessful.tx, - }), - ); - }); - - it("can search unsuccessful tx by height", async () => { - pendingWithoutLaunchpad(); - assert(sendUnsuccessful, "value must be set in beforeAll()"); - const client = new CosmosClient(launchpad.endpoint); - const result = await client.searchTx({ height: sendUnsuccessful.height }); - expect(result.length).toBeGreaterThanOrEqual(1); - expect(result).toContain( - jasmine.objectContaining({ - height: sendUnsuccessful.height, - hash: sendUnsuccessful.hash, - code: 5, - tx: sendUnsuccessful.tx, - }), - ); - }); - }); - - describe("with SearchBySentFromOrToQuery", () => { - it("can search by sender", async () => { - pendingWithoutLaunchpad(); - assert(sendSuccessful, "value must be set in beforeAll()"); - const client = new CosmosClient(launchpad.endpoint); - const results = await client.searchTx({ sentFromOrTo: sendSuccessful.sender }); - expect(results.length).toBeGreaterThanOrEqual(1); - - // Check basic structure of all results - for (const result of results) { - const containsMsgWithSender = !!result.tx.value.msg.find( - (msg) => isMsgSend(msg) && msg.value.from_address == sendSuccessful!.sender, - ); - const containsMsgWithRecipient = !!result.tx.value.msg.find( - (msg) => isMsgSend(msg) && msg.value.to_address === sendSuccessful!.sender, - ); - expect(containsMsgWithSender || containsMsgWithRecipient).toEqual(true); - } - - // Check details of most recent result - expect(results[results.length - 1]).toEqual( - jasmine.objectContaining({ - height: sendSuccessful.height, - hash: sendSuccessful.hash, - tx: sendSuccessful.tx, - }), - ); - }); - - it("can search by recipient", async () => { - pendingWithoutLaunchpad(); - assert(sendSuccessful, "value must be set in beforeAll()"); - const client = new CosmosClient(launchpad.endpoint); - const results = await client.searchTx({ sentFromOrTo: sendSuccessful.recipient }); - expect(results.length).toBeGreaterThanOrEqual(1); - - // Check basic structure of all results - for (const result of results) { - const msg = fromOneElementArray(result.tx.value.msg); - assert(isMsgSend(msg), `${result.hash} (height ${result.height}) is not a bank send transaction`); - expect( - msg.value.to_address === sendSuccessful.recipient || - msg.value.from_address == sendSuccessful.recipient, - ).toEqual(true); - } - - // Check details of most recent result - expect(results[results.length - 1]).toEqual( - jasmine.objectContaining({ - height: sendSuccessful.height, - hash: sendSuccessful.hash, - tx: sendSuccessful.tx, - }), - ); - }); - - it("can search by recipient and filter by minHeight", async () => { - pendingWithoutLaunchpad(); - assert(sendSuccessful); - const client = new CosmosClient(launchpad.endpoint); - const query = { sentFromOrTo: sendSuccessful.recipient }; - - { - const result = await client.searchTx(query, { minHeight: 0 }); - expect(result.length).toEqual(1); - } - - { - const result = await client.searchTx(query, { minHeight: sendSuccessful.height - 1 }); - expect(result.length).toEqual(1); - } - - { - const result = await client.searchTx(query, { minHeight: sendSuccessful.height }); - expect(result.length).toEqual(1); - } - - { - const result = await client.searchTx(query, { minHeight: sendSuccessful.height + 1 }); - expect(result.length).toEqual(0); - } - }); - - it("can search by recipient and filter by maxHeight", async () => { - pendingWithoutLaunchpad(); - assert(sendSuccessful); - const client = new CosmosClient(launchpad.endpoint); - const query = { sentFromOrTo: sendSuccessful.recipient }; - - { - const result = await client.searchTx(query, { maxHeight: 9999999999999 }); - expect(result.length).toEqual(1); - } - - { - const result = await client.searchTx(query, { maxHeight: sendSuccessful.height + 1 }); - expect(result.length).toEqual(1); - } - - { - const result = await client.searchTx(query, { maxHeight: sendSuccessful.height }); - expect(result.length).toEqual(1); - } - - { - const result = await client.searchTx(query, { maxHeight: sendSuccessful.height - 1 }); - expect(result.length).toEqual(0); - } - }); - }); - - describe("with SearchByTagsQuery", () => { - it("can search by transfer.recipient", async () => { - pendingWithoutLaunchpad(); - assert(sendSuccessful, "value must be set in beforeAll()"); - const client = new CosmosClient(launchpad.endpoint); - const results = await client.searchTx({ - tags: [{ key: "transfer.recipient", value: sendSuccessful.recipient }], - }); - expect(results.length).toBeGreaterThanOrEqual(1); - - // Check basic structure of all results - for (const result of results) { - const msg = fromOneElementArray(result.tx.value.msg); - assert(isMsgSend(msg), `${result.hash} (height ${result.height}) is not a bank send transaction`); - expect(msg.value.to_address).toEqual(sendSuccessful.recipient); - } - - // Check details of most recent result - expect(results[results.length - 1]).toEqual( - jasmine.objectContaining({ - height: sendSuccessful.height, - hash: sendSuccessful.hash, - tx: sendSuccessful.tx, - }), - ); - }); - }); -}); diff --git a/packages/launchpad/src/cosmosclient.spec.ts b/packages/launchpad/src/cosmosclient.spec.ts deleted file mode 100644 index 0f955cd7a2..0000000000 --- a/packages/launchpad/src/cosmosclient.spec.ts +++ /dev/null @@ -1,243 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { makeSignDoc, makeStdTx, Secp256k1HdWallet, StdFee } from "@cosmjs/amino"; -import { assert, sleep } from "@cosmjs/utils"; -import { ReadonlyDate } from "readonly-date"; - -import { assertIsBroadcastTxSuccess, CosmosClient, PrivateCosmosClient } from "./cosmosclient"; -import { findAttribute } from "./logs"; -import { MsgSend } from "./msgs"; -import cosmoshub from "./testdata/cosmoshub.json"; -import { - faucet, - launchpad, - makeRandomAddress, - pendingWithoutLaunchpad, - tendermintIdMatcher, - unused, -} from "./testutils.spec"; -import { isWrappedStdTx } from "./tx"; - -const blockTime = 1_000; // ms - -const guest = { - address: "cosmos17d0jcz59jf68g52vq38tuuncmwwjk42u6mcxej", -}; - -describe("CosmosClient", () => { - describe("constructor", () => { - it("can be constructed", () => { - const client = new CosmosClient(launchpad.endpoint); - expect(client).toBeTruthy(); - }); - }); - - describe("getChainId", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = new CosmosClient(launchpad.endpoint); - expect(await client.getChainId()).toEqual(launchpad.chainId); - }); - - it("caches chain ID", async () => { - pendingWithoutLaunchpad(); - const client = new CosmosClient(launchpad.endpoint); - const openedClient = client as unknown as PrivateCosmosClient; - const getCodeSpy = spyOn(openedClient.lcdClient, "nodeInfo").and.callThrough(); - - expect(await client.getChainId()).toEqual(launchpad.chainId); // from network - expect(await client.getChainId()).toEqual(launchpad.chainId); // from cache - - expect(getCodeSpy).toHaveBeenCalledTimes(1); - }); - }); - - describe("getHeight", () => { - it("gets height via last block", async () => { - pendingWithoutLaunchpad(); - const client = new CosmosClient(launchpad.endpoint); - const openedClient = client as unknown as PrivateCosmosClient; - const blockLatestSpy = spyOn(openedClient.lcdClient, "blocksLatest").and.callThrough(); - - const height1 = await client.getHeight(); - expect(height1).toBeGreaterThan(0); - await sleep(blockTime * 1.4); // tolerate chain being 40% slower than expected - const height2 = await client.getHeight(); - expect(height2).toBeGreaterThanOrEqual(height1 + 1); - expect(height2).toBeLessThanOrEqual(height1 + 2); - - expect(blockLatestSpy).toHaveBeenCalledTimes(2); - }); - - it("gets height via authAccount once an address is known", async () => { - pendingWithoutLaunchpad(); - const client = new CosmosClient(launchpad.endpoint); - - const openedClient = client as unknown as PrivateCosmosClient; - const blockLatestSpy = spyOn(openedClient.lcdClient, "blocksLatest").and.callThrough(); - const authAccountsSpy = spyOn(openedClient.lcdClient.auth, "account").and.callThrough(); - - const height1 = await client.getHeight(); - expect(height1).toBeGreaterThan(0); - - await client.getAccount(guest.address); // warm up the client - - const height2 = await client.getHeight(); - expect(height2).toBeGreaterThan(0); - await sleep(blockTime * 1.3); // tolerate chain being 30% slower than expected - const height3 = await client.getHeight(); - expect(height3).toBeGreaterThanOrEqual(height2 + 1); - expect(height3).toBeLessThanOrEqual(height2 + 2); - - expect(blockLatestSpy).toHaveBeenCalledTimes(1); - expect(authAccountsSpy).toHaveBeenCalledTimes(3); - }); - }); - - describe("getSequence", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = new CosmosClient(launchpad.endpoint); - expect(await client.getSequence(unused.address)).toEqual({ - accountNumber: unused.accountNumber, - sequence: unused.sequence, - }); - }); - - it("throws for missing accounts", async () => { - pendingWithoutLaunchpad(); - const client = new CosmosClient(launchpad.endpoint); - const missing = makeRandomAddress(); - await client.getSequence(missing).then( - () => fail("this must not succeed"), - (error) => expect(error).toMatch(/account does not exist on chain/i), - ); - }); - }); - - describe("getAccount", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = new CosmosClient(launchpad.endpoint); - expect(await client.getAccount(unused.address)).toEqual({ - address: unused.address, - accountNumber: unused.accountNumber, - sequence: unused.sequence, - pubkey: undefined, - balance: [ - { denom: "ucosm", amount: "1000000000" }, - { denom: "ustake", amount: "1000000000" }, - ], - }); - }); - - it("returns undefined for missing accounts", async () => { - pendingWithoutLaunchpad(); - const client = new CosmosClient(launchpad.endpoint); - const missing = makeRandomAddress(); - expect(await client.getAccount(missing)).toBeUndefined(); - }); - }); - - describe("getBlock", () => { - it("works for latest block", async () => { - pendingWithoutLaunchpad(); - const client = new CosmosClient(launchpad.endpoint); - const response = await client.getBlock(); - - expect(response).toEqual( - jasmine.objectContaining({ - id: jasmine.stringMatching(tendermintIdMatcher), - header: jasmine.objectContaining({ - chainId: await client.getChainId(), - }), - txs: [], - }), - ); - - expect(response.header.height).toBeGreaterThanOrEqual(1); - expect(new ReadonlyDate(response.header.time).getTime()).toBeLessThan(ReadonlyDate.now()); - expect(new ReadonlyDate(response.header.time).getTime()).toBeGreaterThanOrEqual( - ReadonlyDate.now() - 5_000, - ); - }); - - it("works for block by height", async () => { - pendingWithoutLaunchpad(); - const client = new CosmosClient(launchpad.endpoint); - const height = (await client.getBlock()).header.height; - const response = await client.getBlock(height - 1); - - expect(response).toEqual( - jasmine.objectContaining({ - id: jasmine.stringMatching(tendermintIdMatcher), - header: jasmine.objectContaining({ - height: height - 1, - chainId: await client.getChainId(), - }), - txs: [], - }), - ); - - expect(new ReadonlyDate(response.header.time).getTime()).toBeLessThan(ReadonlyDate.now()); - expect(new ReadonlyDate(response.header.time).getTime()).toBeGreaterThanOrEqual( - ReadonlyDate.now() - 5_000, - ); - }); - }); - - describe("getIdentifier", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = new CosmosClient(launchpad.endpoint); - assert(isWrappedStdTx(cosmoshub.tx)); - expect(await client.getIdentifier(cosmoshub.tx)).toEqual(cosmoshub.id); - }); - }); - - describe("broadcastTx", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const wallet = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic); - const accounts = await wallet.getAccounts(); - const [{ address: walletAddress }] = accounts; - const client = new CosmosClient(launchpad.endpoint); - - const memo = "Test send"; - const sendMsg: MsgSend = { - type: "cosmos-sdk/MsgSend", - value: { - from_address: faucet.address0, - to_address: makeRandomAddress(), - amount: [ - { - denom: "ucosm", - amount: "1234567", - }, - ], - }, - }; - - const fee: StdFee = { - amount: [ - { - amount: "5000", - denom: "ucosm", - }, - ], - gas: "890000", - }; - - const chainId = await client.getChainId(); - const { accountNumber, sequence } = await client.getSequence(faucet.address0); - const signDoc = makeSignDoc([sendMsg], fee, chainId, memo, accountNumber, sequence); - const { signed, signature } = await wallet.signAmino(walletAddress, signDoc); - const signedTx = makeStdTx(signed, signature); - const txResult = await client.broadcastTx(signedTx); - assertIsBroadcastTxSuccess(txResult); - const { logs, transactionHash } = txResult; - const amountAttr = findAttribute(logs, "transfer", "amount"); - expect(amountAttr.value).toEqual("1234567ucosm"); - expect(transactionHash).toMatch(/^[0-9A-F]{64}$/); - }); - }); -}); diff --git a/packages/launchpad/src/cosmosclient.ts b/packages/launchpad/src/cosmosclient.ts deleted file mode 100644 index 79e0f93ca3..0000000000 --- a/packages/launchpad/src/cosmosclient.ts +++ /dev/null @@ -1,347 +0,0 @@ -import { Coin, Pubkey, StdTx } from "@cosmjs/amino"; -import { sha256 } from "@cosmjs/crypto"; -import { fromBase64, fromHex, toHex } from "@cosmjs/encoding"; -import { Uint53 } from "@cosmjs/math"; - -import { - AuthExtension, - BroadcastMode, - LcdClient, - normalizePubkey, - setupAuthExtension, - uint64ToNumber, -} from "./lcdapi"; -import { Log, parseLogs } from "./logs"; -import { WrappedStdTx } from "./tx"; - -export interface GetSequenceResult { - readonly accountNumber: number; - readonly sequence: number; -} - -export interface Account { - /** Bech32 account address */ - readonly address: string; - readonly balance: readonly Coin[]; - readonly pubkey: Pubkey | undefined; - readonly accountNumber: number; - readonly sequence: number; -} - -export interface BroadcastTxFailure { - /** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */ - readonly transactionHash: string; - readonly height: number; - readonly code: number; - readonly rawLog: string; -} - -export interface BroadcastTxSuccess { - readonly logs: readonly Log[]; - readonly rawLog: string; - /** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */ - readonly transactionHash: string; - readonly data?: Uint8Array; -} - -export type BroadcastTxResult = BroadcastTxSuccess | BroadcastTxFailure; - -export function isBroadcastTxFailure(result: BroadcastTxResult): result is BroadcastTxFailure { - return !!(result as BroadcastTxFailure).code; -} - -export function isBroadcastTxSuccess(result: BroadcastTxResult): result is BroadcastTxSuccess { - return !isBroadcastTxFailure(result); -} - -/** - * Ensures the given result is a success. Throws a detailed error message otherwise. - */ -export function assertIsBroadcastTxSuccess(result: BroadcastTxResult): asserts result is BroadcastTxSuccess { - if (isBroadcastTxFailure(result)) { - throw new Error( - `Error when broadcasting tx ${result.transactionHash} at height ${result.height}. Code: ${result.code}; Raw log: ${result.rawLog}`, - ); - } -} - -export interface SearchByHeightQuery { - readonly height: number; -} - -export interface SearchBySentFromOrToQuery { - readonly sentFromOrTo: string; -} - -/** - * This query type allows you to pass arbitrary key/value pairs to the backend. It is - * more powerful and slightly lower level than the other search options. - */ -export interface SearchByTagsQuery { - readonly tags: ReadonlyArray<{ readonly key: string; readonly value: string }>; -} - -export type SearchTxQuery = SearchByHeightQuery | SearchBySentFromOrToQuery | SearchByTagsQuery; - -export function isSearchByHeightQuery(query: SearchTxQuery): query is SearchByHeightQuery { - return (query as SearchByHeightQuery).height !== undefined; -} - -export function isSearchBySentFromOrToQuery(query: SearchTxQuery): query is SearchBySentFromOrToQuery { - return (query as SearchBySentFromOrToQuery).sentFromOrTo !== undefined; -} - -export function isSearchByTagsQuery(query: SearchTxQuery): query is SearchByTagsQuery { - return (query as SearchByTagsQuery).tags !== undefined; -} - -export interface SearchTxFilter { - readonly minHeight?: number; - readonly maxHeight?: number; -} - -/** A transaction that is indexed as part of the transaction history */ -export interface IndexedTx { - readonly height: number; - /** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */ - readonly hash: string; - /** Transaction execution error code. 0 on success. */ - readonly code: number; - readonly rawLog: string; - readonly logs: readonly Log[]; - readonly tx: WrappedStdTx; - /** The gas limit as set by the user */ - readonly gasWanted?: number; - /** The gas used by the execution */ - readonly gasUsed?: number; - /** An RFC 3339 time string like e.g. '2020-02-15T10:39:10.4696305Z' */ - readonly timestamp: string; -} - -export interface BlockHeader { - readonly version: { - readonly block: string; - readonly app: string; - }; - readonly height: number; - readonly chainId: string; - /** An RFC 3339 time string like e.g. '2020-02-15T10:39:10.4696305Z' */ - readonly time: string; -} - -export interface Block { - /** The ID is a hash of the block header (uppercase hex) */ - readonly id: string; - readonly header: BlockHeader; - /** Array of raw transactions */ - readonly txs: readonly Uint8Array[]; -} - -/** Use for testing only */ -export interface PrivateCosmosClient { - readonly lcdClient: LcdClient & AuthExtension; -} - -export class CosmosClient { - protected readonly lcdClient: LcdClient & AuthExtension; - /** Any address the chain considers valid (valid bech32 with proper prefix) */ - protected anyValidAddress: string | undefined; - - private chainId: string | undefined; - - /** - * Creates a new client to interact with a CosmWasm blockchain. - * - * This instance does a lot of caching. In order to benefit from that you should try to use one instance - * for the lifetime of your application. When switching backends, a new instance must be created. - * - * @param apiUrl The URL of a Cosmos SDK light client daemon API (sometimes called REST server or REST API) - * @param broadcastMode Defines at which point of the transaction processing the broadcastTx method returns - */ - public constructor(apiUrl: string, broadcastMode = BroadcastMode.Block) { - this.lcdClient = LcdClient.withExtensions( - { apiUrl: apiUrl, broadcastMode: broadcastMode }, - setupAuthExtension, - ); - } - - public async getChainId(): Promise { - if (!this.chainId) { - const response = await this.lcdClient.nodeInfo(); - const chainId = response.node_info.network; - if (!chainId) throw new Error("Chain ID must not be empty"); - this.chainId = chainId; - } - - return this.chainId; - } - - public async getHeight(): Promise { - if (this.anyValidAddress) { - const { height } = await this.lcdClient.auth.account(this.anyValidAddress); - return parseInt(height, 10); - } else { - // Note: this gets inefficient when blocks contain a lot of transactions since it - // requires downloading and deserializing all transactions in the block. - const latest = await this.lcdClient.blocksLatest(); - return parseInt(latest.block.header.height, 10); - } - } - - /** - * Returns a 32 byte upper-case hex transaction hash (typically used as the transaction ID) - */ - public async getIdentifier(tx: WrappedStdTx): Promise { - // We consult the REST API because we don't have a local amino encoder - const response = await this.lcdClient.encodeTx(tx); - const hash = sha256(fromBase64(response.tx)); - return toHex(hash).toUpperCase(); - } - - /** - * Returns account number and sequence. - * - * Throws if the account does not exist on chain. - * - * @param address returns data for this address. When unset, the client's sender adddress is used. - */ - public async getSequence(address: string): Promise { - const account = await this.getAccount(address); - if (!account) { - throw new Error( - "Account does not exist on chain. Send some tokens there before trying to query sequence.", - ); - } - return { - accountNumber: account.accountNumber, - sequence: account.sequence, - }; - } - - public async getAccount(address: string): Promise { - const account = await this.lcdClient.auth.account(address); - const value = account.result.value; - if (value.address === "") { - return undefined; - } else { - this.anyValidAddress = value.address; - return { - address: value.address, - balance: value.coins, - pubkey: normalizePubkey(value.public_key) || undefined, - accountNumber: uint64ToNumber(value.account_number), - sequence: uint64ToNumber(value.sequence), - }; - } - } - - /** - * Gets block header and meta - * - * @param height The height of the block. If undefined, the latest height is used. - */ - public async getBlock(height?: number): Promise { - const response = - height !== undefined ? await this.lcdClient.blocks(height) : await this.lcdClient.blocksLatest(); - - return { - id: response.block_id.hash, - header: { - version: response.block.header.version, - time: response.block.header.time, - height: parseInt(response.block.header.height, 10), - chainId: response.block.header.chain_id, - }, - txs: (response.block.data.txs || []).map(fromBase64), - }; - } - - public async getTx(id: string): Promise { - const results = await this.txsQuery(`tx.hash=${id}`); - return results[0] ?? null; - } - - public async searchTx(query: SearchTxQuery, filter: SearchTxFilter = {}): Promise { - const minHeight = filter.minHeight || 0; - const maxHeight = filter.maxHeight || Number.MAX_SAFE_INTEGER; - - if (maxHeight < minHeight) return []; // optional optimization - - function withFilters(originalQuery: string): string { - return `${originalQuery}&tx.minheight=${minHeight}&tx.maxheight=${maxHeight}`; - } - - let txs: readonly IndexedTx[]; - if (isSearchByHeightQuery(query)) { - // optional optimization to avoid network request - if (query.height < minHeight || query.height > maxHeight) { - txs = []; - } else { - txs = await this.txsQuery(`tx.height=${query.height}`); - } - } else if (isSearchBySentFromOrToQuery(query)) { - // We cannot get both in one request (see https://github.com/cosmos/gaia/issues/75) - const sentQuery = withFilters(`message.module=bank&message.sender=${query.sentFromOrTo}`); - const receivedQuery = withFilters(`message.module=bank&transfer.recipient=${query.sentFromOrTo}`); - const sent = await this.txsQuery(sentQuery); - const received = await this.txsQuery(receivedQuery); - - const sentHashes = sent.map((t) => t.hash); - txs = [...sent, ...received.filter((t) => !sentHashes.includes(t.hash))]; - } else if (isSearchByTagsQuery(query)) { - const rawQuery = withFilters(query.tags.map((t) => `${t.key}=${t.value}`).join("&")); - txs = await this.txsQuery(rawQuery); - } else { - throw new Error("Unknown query type"); - } - - // backend sometimes messes up with min/max height filtering - const filtered = txs.filter((tx) => tx.height >= minHeight && tx.height <= maxHeight); - - return filtered; - } - - public async broadcastTx(tx: StdTx): Promise { - const result = await this.lcdClient.broadcastTx(tx); - if (!result.txhash.match(/^([0-9A-F][0-9A-F])+$/)) { - throw new Error("Received ill-formatted txhash. Must be non-empty upper-case hex"); - } - - return result.code !== undefined - ? { - height: Uint53.fromString(result.height).toNumber(), - transactionHash: result.txhash, - code: result.code, - rawLog: result.raw_log || "", - } - : { - logs: result.logs ? parseLogs(result.logs) : [], - rawLog: result.raw_log || "", - transactionHash: result.txhash, - data: result.data ? fromHex(result.data) : undefined, - }; - } - - private async txsQuery(query: string): Promise { - // TODO: we need proper pagination support - const limit = 100; - const result = await this.lcdClient.txsQuery(`${query}&limit=${limit}`); - const pages = parseInt(result.page_total, 10); - if (pages > 1) { - throw new Error( - `Found more results on the backend than we can process currently. Results: ${result.total_count}, supported: ${limit}`, - ); - } - return result.txs.map( - (restItem): IndexedTx => ({ - height: parseInt(restItem.height, 10), - hash: restItem.txhash, - code: restItem.code || 0, - rawLog: restItem.raw_log, - logs: parseLogs(restItem.logs || []), - tx: restItem.tx, - timestamp: restItem.timestamp, - }), - ); - } -} diff --git a/packages/launchpad/src/fee.spec.ts b/packages/launchpad/src/fee.spec.ts deleted file mode 100644 index 0185462435..0000000000 --- a/packages/launchpad/src/fee.spec.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { Decimal } from "@cosmjs/math"; - -import { GasPrice } from "./fee"; - -describe("GasPrice", () => { - it("can be constructed", () => { - const inputs = ["3.14", "3", "0.14"]; - inputs.forEach((input) => { - const gasPrice = new GasPrice(Decimal.fromUserInput(input, 18), "utest"); - expect(gasPrice.amount.toString()).toEqual(input); - expect(gasPrice.denom).toEqual("utest"); - }); - }); - - describe("fromString", () => { - it("works", () => { - const inputs: Record = { - // Test amounts - "3.14utest": { amount: "3.14", denom: "utest" }, - "3utest": { amount: "3", denom: "utest" }, - "0.14utest": { amount: "0.14", denom: "utest" }, - // Test denoms - "0.14sht": { amount: "0.14", denom: "sht" }, - "0.14testtesttesttest": { amount: "0.14", denom: "testtesttesttest" }, - "0.14ucoin2": { amount: "0.14", denom: "ucoin2" }, - }; - for (const [input, expected] of Object.entries(inputs)) { - const gasPrice = GasPrice.fromString(input); - expect(gasPrice.amount.toString()).withContext(`Input: ${input}`).toEqual(expected.amount); - expect(gasPrice.denom).withContext(`Input: ${input}`).toEqual(expected.denom); - } - }); - - it("errors for invalid gas price", () => { - // Checks basic format - expect(() => GasPrice.fromString("")).toThrowError(/Invalid gas price string/i); - expect(() => GasPrice.fromString("utkn")).toThrowError(/Invalid gas price string/i); - expect(() => GasPrice.fromString("@utkn")).toThrowError(/Invalid gas price string/i); - expect(() => GasPrice.fromString("234")).toThrowError(/Invalid gas price string/i); - expect(() => GasPrice.fromString("-234tkn")).toThrowError(/Invalid gas price string/i); - // Checks details of - expect(() => GasPrice.fromString("234t")).toThrowError(/denom must be between 3 and 16 characters/i); - expect(() => GasPrice.fromString("234tt")).toThrowError(/denom must be between 3 and 16 characters/i); - expect(() => GasPrice.fromString("234ttttttttttttttttt")).toThrowError( - /denom must be between 3 and 16 characters/i, - ); - expect(() => GasPrice.fromString("234ATOM")).toThrowError( - /denom must only contain lower case letters a-z and digits 0-9/i, - ); - // Checks details of - expect(() => GasPrice.fromString("3.utkn")).toThrowError(/Fractional part missing/i); - expect(() => GasPrice.fromString("..utkn")).toThrowError(/More than one separator found/i); - }); - }); -}); diff --git a/packages/launchpad/src/fee.ts b/packages/launchpad/src/fee.ts deleted file mode 100644 index 5f608af9fc..0000000000 --- a/packages/launchpad/src/fee.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { coins, StdFee } from "@cosmjs/amino"; -import { Decimal, Uint53 } from "@cosmjs/math"; - -export type FeeTable = Record; - -/** - * Denom checker for the Cosmos SDK 0.39 denom pattern - * (https://github.com/cosmos/cosmos-sdk/blob/v0.39.3/types/coin.go#L597-L598). - * - * This is like a regexp but with helpful error messages. - */ -function checkDenom(denom: string): void { - if (denom.length < 3 || denom.length > 16) { - throw new Error("Denom must be between 3 and 16 characters"); - } - if (denom.match(/[^a-z0-9]/)) { - throw new Error("Denom must only contain lower case letters a-z and digits 0-9"); - } -} - -/** - * A gas price, i.e. the price of a single unit of gas. This is typically a fraction of - * the smallest fee token unit, such as 0.012utoken. - */ -export class GasPrice { - public readonly amount: Decimal; - public readonly denom: string; - - public constructor(amount: Decimal, denom: string) { - this.amount = amount; - this.denom = denom; - } - - /** - * Parses a gas price formatted as ``, e.g. `GasPrice.fromString("0.012utoken")`. - * - * The denom must match the Cosmos SDK 0.39 pattern (https://github.com/cosmos/cosmos-sdk/blob/v0.39.3/types/coin.go#L597-L598). - * See `GasPrice` in @cosmjs/stargate for a more generic matcher. - */ - public static fromString(gasPrice: string): GasPrice { - // Use Decimal.fromUserInput and checkDenom for detailed checks and helpful error messages - const matchResult = gasPrice.match(/^([0-9.]+)([a-z][a-z0-9]*)$/i); - if (!matchResult) { - throw new Error("Invalid gas price string"); - } - const [_, amount, denom] = matchResult; - checkDenom(denom); - const fractionalDigits = 18; - const decimalAmount = Decimal.fromUserInput(amount, fractionalDigits); - return new GasPrice(decimalAmount, denom); - } -} - -export type GasLimits> = { - readonly [key in keyof T]: number; -}; - -function calculateFee(gasLimit: number, { denom, amount: gasPriceAmount }: GasPrice): StdFee { - const amount = Math.ceil(gasPriceAmount.multiply(new Uint53(gasLimit)).toFloatApproximation()); - return { - amount: coins(amount, denom), - gas: gasLimit.toString(), - }; -} - -export function buildFeeTable>( - gasPrice: GasPrice, - defaultGasLimits: GasLimits, - gasLimits: Partial>, -): T { - return Object.entries(defaultGasLimits).reduce( - (feeTable, [type, defaultGasLimit]) => ({ - ...feeTable, - [type]: calculateFee(gasLimits[type] || defaultGasLimit, gasPrice), - }), - {} as T, - ); -} diff --git a/packages/launchpad/src/index.ts b/packages/launchpad/src/index.ts deleted file mode 100644 index 3a2bb3a830..0000000000 --- a/packages/launchpad/src/index.ts +++ /dev/null @@ -1,163 +0,0 @@ -// Re-exports for backwards compatibility -export { - AccountData, - Algo, - AminoSignResponse, - Coin, - coin, - coins, - decodeAminoPubkey, - decodeBech32Pubkey, - decodeSignature, - encodeAminoPubkey, - encodeBech32Pubkey, - encodeSecp256k1Pubkey, - encodeSecp256k1Signature, - executeKdf, - extractKdfConfiguration, - isStdTx, - KdfConfiguration, - makeCosmoshubPath, - makeSignDoc, - makeStdTx, - AminoMsg as Msg, - OfflineAminoSigner as OfflineSigner, - parseCoins, - pubkeyToAddress, - pubkeyType, - Secp256k1HdWallet, - Secp256k1Wallet, - serializeSignDoc, - StdFee, - StdSignature, - StdSignDoc, - StdTx, -} from "@cosmjs/amino"; -import { SinglePubkey } from "@cosmjs/amino"; -/** @deprecated PubKey is deprecated. Use `SinglePubkey` or the more general `Pubkey` from `@cosmjs/amino`. */ -export type PubKey = SinglePubkey; - -import * as logs from "./logs"; -export { logs }; - -export { - Account, - assertIsBroadcastTxSuccess, - Block, - BlockHeader, - BroadcastTxFailure, - BroadcastTxResult, - BroadcastTxSuccess, - CosmosClient, - GetSequenceResult, - IndexedTx, - isBroadcastTxFailure, - isBroadcastTxSuccess, - isSearchByHeightQuery, - isSearchBySentFromOrToQuery, - isSearchByTagsQuery, - SearchByHeightQuery, - SearchBySentFromOrToQuery, - SearchByTagsQuery, - SearchTxFilter, - SearchTxQuery, -} from "./cosmosclient"; -export { buildFeeTable, FeeTable, GasLimits, GasPrice } from "./fee"; -export { - AuthAccountsResponse, - AuthExtension, - BankBalancesResponse, - BankExtension, - BaseAccount, - BlockResponse, - BroadcastMode, - BroadcastTxsResponse, - DistributionCommunityPoolResponse, - DistributionDelegatorRewardResponse, - DistributionDelegatorRewardsResponse, - DistributionExtension, - DistributionParametersResponse, - DistributionValidatorOutstandingRewardsResponse, - DistributionValidatorResponse, - DistributionValidatorRewardsResponse, - DistributionWithdrawAddressResponse, - EncodeTxResponse, - GovDepositResponse, - GovDepositsResponse, - GovExtension, - GovParametersResponse, - GovProposalResponse, - GovProposalsResponse, - GovProposerResponse, - GovTallyResponse, - GovVoteResponse, - GovVotesResponse, - LcdApiArray, - LcdClient, - MintAnnualProvisionsResponse, - MintExtension, - MintInflationResponse, - MintParametersResponse, - NodeInfoResponse, - normalizeLcdApiArray, - normalizePubkey, - SearchTxsResponse, - setupAuthExtension, - setupBankExtension, - setupDistributionExtension, - setupGovExtension, - setupMintExtension, - setupSlashingExtension, - setupStakingExtension, - setupSupplyExtension, - SlashingExtension, - SlashingParametersResponse, - SlashingSigningInfosResponse, - StakingDelegationResponse, - StakingDelegatorDelegationsResponse, - StakingDelegatorTransactionsResponse, - StakingDelegatorUnbondingDelegationsResponse, - StakingDelegatorValidatorResponse, - StakingDelegatorValidatorsResponse, - StakingExtension, - StakingHistoricalInfoResponse, - StakingParametersResponse, - StakingPoolResponse, - StakingRedelegationsResponse, - StakingUnbondingDelegationResponse, - StakingValidatorDelegationsResponse, - StakingValidatorResponse, - StakingValidatorsResponse, - StakingValidatorUnbondingDelegationsResponse, - SupplyExtension, - TxsResponse, - uint64ToNumber, - uint64ToString, -} from "./lcdapi"; -export { - isMsgBeginRedelegate, - isMsgCreateValidator, - isMsgDelegate, - isMsgEditValidator, - isMsgFundCommunityPool, - isMsgMultiSend, - isMsgSend, - isMsgSetWithdrawAddress, - isMsgUndelegate, - isMsgWithdrawDelegatorReward, - isMsgWithdrawValidatorCommission, - MsgBeginRedelegate, - MsgCreateValidator, - MsgDelegate, - MsgEditValidator, - MsgFundCommunityPool, - MsgMultiSend, - MsgSend, - MsgSetWithdrawAddress, - MsgUndelegate, - MsgWithdrawDelegatorReward, - MsgWithdrawValidatorCommission, -} from "./msgs"; -export { findSequenceForSignedTx } from "./sequence"; -export { CosmosFeeTable, SigningCosmosClient } from "./signingcosmosclient"; -export { CosmosSdkTx, isWrappedStdTx, WrappedStdTx, WrappedTx } from "./tx"; diff --git a/packages/launchpad/src/lcdapi/auth.spec.ts b/packages/launchpad/src/lcdapi/auth.spec.ts deleted file mode 100644 index ac395c3e7b..0000000000 --- a/packages/launchpad/src/lcdapi/auth.spec.ts +++ /dev/null @@ -1,67 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { - faucet, - launchpad, - makeRandomAddress, - nonNegativeIntegerMatcher, - pendingWithoutLaunchpad, - unused, -} from "../testutils.spec"; -import { AuthExtension, setupAuthExtension } from "./auth"; -import { LcdClient } from "./lcdclient"; - -function makeAuthClient(apiUrl: string): LcdClient & AuthExtension { - return LcdClient.withExtensions({ apiUrl }, setupAuthExtension); -} - -describe("AuthExtension", () => { - it("works for unused account without pubkey", async () => { - pendingWithoutLaunchpad(); - const client = makeAuthClient(launchpad.endpoint); - const { height, result } = await client.auth.account(unused.address); - expect(height).toMatch(nonNegativeIntegerMatcher); - expect(result).toEqual({ - type: "cosmos-sdk/Account", - value: { - address: unused.address, - public_key: null, // not known to the chain - coins: [ - { - amount: "1000000000", - denom: "ucosm", - }, - { - amount: "1000000000", - denom: "ustake", - }, - ], - account_number: unused.accountNumber.toString(), - sequence: unused.sequence.toString(), - }, - }); - }); - - // This fails in the first test run if you forget to run `./scripts/launchpad/init.sh` - it("has correct pubkey for faucet", async () => { - pendingWithoutLaunchpad(); - const client = makeAuthClient(launchpad.endpoint); - const { result } = await client.auth.account(faucet.address0); - expect(result.value).toEqual( - jasmine.objectContaining({ - public_key: faucet.pubkey0, - }), - ); - }); - - // This property is used by CosmWasmClient.getAccount - it("returns empty address for non-existent account", async () => { - pendingWithoutLaunchpad(); - const client = makeAuthClient(launchpad.endpoint); - const nonExistentAccount = makeRandomAddress(); - const { result } = await client.auth.account(nonExistentAccount); - expect(result).toEqual({ - type: "cosmos-sdk/Account", - value: jasmine.objectContaining({ address: "" }), - }); - }); -}); diff --git a/packages/launchpad/src/lcdapi/auth.ts b/packages/launchpad/src/lcdapi/auth.ts deleted file mode 100644 index bea6e46b0b..0000000000 --- a/packages/launchpad/src/lcdapi/auth.ts +++ /dev/null @@ -1,78 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { Coin, Pubkey } from "@cosmjs/amino"; - -import { LcdClient } from "./lcdclient"; - -/** - * A Cosmos SDK base account. - * - * This type describes the base account representation as returned - * by the Cosmos SDK 0.37–0.39 LCD API. - * - * @see https://docs.cosmos.network/master/modules/auth/02_state.html#base-account - */ -export interface BaseAccount { - /** Bech32 account address */ - readonly address: string; - readonly coins: readonly Coin[]; - /** - * The public key of the account. This is not available on-chain as long as the account - * did not send a transaction. - * - * This was a type/value object in Cosmos SDK 0.37, changed to bech32 in Cosmos SDK 0.38 ([1]) - * and changed back to type/value object in Cosmos SDK 0.39 ([2]). - * - * [1]: https://github.com/cosmos/cosmos-sdk/pull/5280 - * [2]: https://github.com/cosmos/cosmos-sdk/pull/6749 - */ - readonly public_key: string | Pubkey | null; - /** - * The account number assigned by the blockchain. - * - * This was string encoded in Cosmos SDK 0.37, changed to number in Cosmos SDK 0.38 ([1]) - * and changed back to string in Cosmos SDK 0.39 ([2]). - * - * [1]: https://github.com/cosmos/cosmos-sdk/pull/5280 - * [2]: https://github.com/cosmos/cosmos-sdk/pull/6749 - */ - readonly account_number: number | string; - /** - * The sequence number for replay protection. - * - * This was string encoded in Cosmos SDK 0.37, changed to number in Cosmos SDK 0.38 ([1]) - * and changed back to string in Cosmos SDK 0.39 ([2]). - * - * [1]: https://github.com/cosmos/cosmos-sdk/pull/5280 - * [2]: https://github.com/cosmos/cosmos-sdk/pull/6749 - */ - readonly sequence: number | string; -} - -export interface AuthAccountsResponse { - readonly height: string; - readonly result: { - readonly type: "cosmos-sdk/Account"; - readonly value: BaseAccount; - }; -} - -export interface AuthExtension { - readonly auth: { - readonly account: (address: string) => Promise; - }; -} - -export function setupAuthExtension(base: LcdClient): AuthExtension { - return { - auth: { - account: async (address: string) => { - const path = `/auth/accounts/${address}`; - const responseData = await base.get(path); - if (responseData.result.type !== "cosmos-sdk/Account") { - throw new Error("Unexpected response data format"); - } - return responseData as AuthAccountsResponse; - }, - }, - }; -} diff --git a/packages/launchpad/src/lcdapi/bank.spec.ts b/packages/launchpad/src/lcdapi/bank.spec.ts deleted file mode 100644 index 9a7f305a95..0000000000 --- a/packages/launchpad/src/lcdapi/bank.spec.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { - launchpad, - makeRandomAddress, - nonNegativeIntegerMatcher, - pendingWithoutLaunchpad, - unused, -} from "../testutils.spec"; -import { BankExtension, setupBankExtension } from "./bank"; -import { LcdClient } from "./lcdclient"; - -function makeBankClient(apiUrl: string): LcdClient & BankExtension { - return LcdClient.withExtensions({ apiUrl }, setupBankExtension); -} - -describe("BankExtension", () => { - it("returns correct values for the unused account", async () => { - pendingWithoutLaunchpad(); - const client = makeBankClient(launchpad.endpoint); - const balances = await client.bank.balances(unused.address); - expect(balances).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: [ - { - denom: "ucosm", - amount: "1000000000", - }, - { - denom: "ustake", - amount: "1000000000", - }, - ], - }); - }); - - it("returns an empty result for a non-existent account", async () => { - pendingWithoutLaunchpad(); - const client = makeBankClient(launchpad.endpoint); - const nonExistentAddress = makeRandomAddress(); - const balances = await client.bank.balances(nonExistentAddress); - expect(balances).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: [], - }); - }); -}); diff --git a/packages/launchpad/src/lcdapi/bank.ts b/packages/launchpad/src/lcdapi/bank.ts deleted file mode 100644 index 552db8e8b0..0000000000 --- a/packages/launchpad/src/lcdapi/bank.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Coin } from "@cosmjs/amino"; - -import { LcdClient } from "./lcdclient"; - -export interface BankBalancesResponse { - readonly height: string; - readonly result: readonly Coin[]; -} - -export interface BankExtension { - readonly bank: { - readonly balances: (address: string) => Promise; - }; -} - -export function setupBankExtension(base: LcdClient): BankExtension { - return { - bank: { - balances: async (address: string) => { - const path = `/bank/balances/${address}`; - return base.get(path); - }, - }, - }; -} diff --git a/packages/launchpad/src/lcdapi/base.ts b/packages/launchpad/src/lcdapi/base.ts deleted file mode 100644 index 442eda3f16..0000000000 --- a/packages/launchpad/src/lcdapi/base.ts +++ /dev/null @@ -1,146 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { WrappedStdTx } from "../tx"; - -/** - * The mode used to send transaction - * - * @see https://cosmos.network/rpc/#/Transactions/post_txs - */ -export enum BroadcastMode { - /** Return after tx commit */ - Block = "block", - /** Return after CheckTx */ - Sync = "sync", - /** Return right away */ - Async = "async", -} - -/** A response from the /txs/encode endpoint */ -export interface EncodeTxResponse { - /** base64-encoded amino-binary encoded representation */ - readonly tx: string; -} - -interface NodeInfo { - readonly protocol_version: { - readonly p2p: string; - readonly block: string; - readonly app: string; - }; - readonly id: string; - readonly listen_addr: string; - readonly network: string; - readonly version: string; - readonly channels: string; - readonly moniker: string; - readonly other: { - readonly tx_index: string; - readonly rpc_address: string; - }; -} - -interface ApplicationVersion { - readonly name: string; - readonly server_name: string; - readonly client_name: string; - readonly version: string; - readonly commit: string; - readonly build_tags: string; - readonly go: string; -} - -export interface NodeInfoResponse { - readonly node_info: NodeInfo; - readonly application_version: ApplicationVersion; -} - -interface BlockId { - readonly hash: string; - // TODO: here we also have this - // parts: { - // total: '1', - // hash: '7AF200C78FBF9236944E1AB270F4045CD60972B7C265E3A9DA42973397572931' - // } -} - -export interface BlockHeader { - readonly version: { - readonly block: string; - readonly app: string; - }; - readonly height: string; - readonly chain_id: string; - /** An RFC 3339 time string like e.g. '2020-02-15T10:39:10.4696305Z' */ - readonly time: string; - readonly last_commit_hash: string; - readonly last_block_id: BlockId; - /** Can be empty */ - readonly data_hash: string; - readonly validators_hash: string; - readonly next_validators_hash: string; - readonly consensus_hash: string; - readonly app_hash: string; - /** Can be empty */ - readonly last_results_hash: string; - /** Can be empty */ - readonly evidence_hash: string; - readonly proposer_address: string; -} - -interface Block { - readonly header: BlockHeader; - readonly data: { - /** Array of base64 encoded transactions */ - readonly txs: readonly string[] | null; - }; -} - -export interface BlockResponse { - readonly block_id: BlockId; - readonly block: Block; -} - -export interface TxsResponse { - readonly height: string; - readonly txhash: string; - /** 🤷‍♂️ */ - readonly codespace?: string; - /** Falsy when transaction execution succeeded. Contains error code on error. */ - readonly code?: number; - readonly raw_log: string; - readonly logs?: unknown[]; - readonly tx: WrappedStdTx; - /** The gas limit as set by the user */ - readonly gas_wanted?: string; - /** The gas used by the execution */ - readonly gas_used?: string; - readonly timestamp: string; -} - -export interface SearchTxsResponse { - readonly total_count: string; - readonly count: string; - readonly page_number: string; - readonly page_total: string; - readonly limit: string; - readonly txs: readonly TxsResponse[]; -} - -export interface BroadcastTxsResponse { - readonly height: string; - readonly txhash: string; - readonly code?: number; - /** - * The result data of the execution (hex encoded). - * - * @see https://github.com/cosmos/cosmos-sdk/blob/v0.38.4/types/result.go#L101 - */ - readonly data?: string; - readonly raw_log?: string; - /** The same as `raw_log` but deserialized? */ - readonly logs?: unknown[]; - /** The gas limit as set by the user */ - readonly gas_wanted?: string; - /** The gas used by the execution */ - readonly gas_used?: string; -} diff --git a/packages/launchpad/src/lcdapi/distribution.spec.ts b/packages/launchpad/src/lcdapi/distribution.spec.ts deleted file mode 100644 index 95a487dbc8..0000000000 --- a/packages/launchpad/src/lcdapi/distribution.spec.ts +++ /dev/null @@ -1,188 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { coin, coins, makeSignDoc, makeStdTx, Secp256k1HdWallet } from "@cosmjs/amino"; -import { Bech32 } from "@cosmjs/encoding"; -import { sleep } from "@cosmjs/utils"; - -import { assertIsBroadcastTxSuccess } from "../cosmosclient"; -import { MsgDelegate } from "../msgs"; -import { SigningCosmosClient } from "../signingcosmosclient"; -import { - bigDecimalMatcher, - faucet, - launchpad, - launchpadEnabled, - nonNegativeIntegerMatcher, - pendingWithoutLaunchpad, -} from "../testutils.spec"; -import { DistributionExtension, setupDistributionExtension } from "./distribution"; -import { LcdClient } from "./lcdclient"; - -function makeDistributionClient(apiUrl: string): LcdClient & DistributionExtension { - return LcdClient.withExtensions({ apiUrl }, setupDistributionExtension); -} - -describe("DistributionExtension", () => { - const defaultFee = { - amount: coins(25000, "ucosm"), - gas: "1500000", // 1.5 million - }; - - beforeAll(async () => { - if (launchpadEnabled()) { - const wallet = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic); - const client = new SigningCosmosClient(launchpad.endpoint, faucet.address0, wallet); - - const chainId = await client.getChainId(); - const msg: MsgDelegate = { - type: "cosmos-sdk/MsgDelegate", - value: { - delegator_address: faucet.address0, - validator_address: launchpad.validator.address, - amount: coin(25000, "ustake"), - }, - }; - const memo = "Test delegation for launchpad"; - const { accountNumber, sequence } = await client.getSequence(); - const signDoc = makeSignDoc([msg], defaultFee, chainId, memo, accountNumber, sequence); - const { signed, signature } = await wallet.signAmino(faucet.address0, signDoc); - const signedTx = makeStdTx(signed, signature); - - const result = await client.broadcastTx(signedTx); - assertIsBroadcastTxSuccess(result); - - await sleep(75); // wait until transactions are indexed - } - }); - - describe("delegatorRewards", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeDistributionClient(launchpad.endpoint); - const response = await client.distribution.delegatorRewards(faucet.address0); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: { - rewards: [ - { - validator_address: launchpad.validator.address, - reward: null, - }, - ], - total: null, - }, - }); - }); - }); - - describe("delegatorReward", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeDistributionClient(launchpad.endpoint); - const response = await client.distribution.delegatorReward( - faucet.address0, - launchpad.validator.address, - ); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: [], - }); - }); - }); - - describe("withdrawAddress", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeDistributionClient(launchpad.endpoint); - const response = await client.distribution.withdrawAddress(faucet.address0); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: faucet.address0, - }); - }); - }); - - describe("validator", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeDistributionClient(launchpad.endpoint); - const response = await client.distribution.validator(launchpad.validator.address); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: { - // TODO: This smells like a bug in the backend to me - operator_address: Bech32.encode("cosmos", Bech32.decode(launchpad.validator.address).data), - self_bond_rewards: [ - { denom: "ucosm", amount: jasmine.stringMatching(bigDecimalMatcher) }, - { denom: "ustake", amount: jasmine.stringMatching(bigDecimalMatcher) }, - ], - val_commission: [ - { denom: "ucosm", amount: jasmine.stringMatching(bigDecimalMatcher) }, - { denom: "ustake", amount: jasmine.stringMatching(bigDecimalMatcher) }, - ], - }, - }); - }); - }); - - describe("validatorRewards", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeDistributionClient(launchpad.endpoint); - const response = await client.distribution.validatorRewards(launchpad.validator.address); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: [ - { denom: "ucosm", amount: jasmine.stringMatching(bigDecimalMatcher) }, - { denom: "ustake", amount: jasmine.stringMatching(bigDecimalMatcher) }, - ], - }); - }); - }); - - describe("validatorOutstandingRewards", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeDistributionClient(launchpad.endpoint); - const response = await client.distribution.validatorOutstandingRewards(launchpad.validator.address); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: [ - { denom: "ucosm", amount: jasmine.stringMatching(bigDecimalMatcher) }, - { denom: "ustake", amount: jasmine.stringMatching(bigDecimalMatcher) }, - ], - }); - }); - }); - - describe("parameters", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeDistributionClient(launchpad.endpoint); - const response = await client.distribution.parameters(); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: { - community_tax: "0.020000000000000000", - base_proposer_reward: "0.010000000000000000", - bonus_proposer_reward: "0.040000000000000000", - withdraw_addr_enabled: true, - }, - }); - }); - }); - - describe("communityPool", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeDistributionClient(launchpad.endpoint); - const response = await client.distribution.communityPool(); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: [ - { denom: "ucosm", amount: jasmine.stringMatching(bigDecimalMatcher) }, - { denom: "ustake", amount: jasmine.stringMatching(bigDecimalMatcher) }, - ], - }); - }); - }); -}); diff --git a/packages/launchpad/src/lcdapi/distribution.ts b/packages/launchpad/src/lcdapi/distribution.ts deleted file mode 100644 index 209e85c080..0000000000 --- a/packages/launchpad/src/lcdapi/distribution.ts +++ /dev/null @@ -1,100 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { Coin } from "@cosmjs/amino"; - -import { LcdClient } from "./lcdclient"; - -export interface RewardContainer { - readonly validator_address: string; - readonly reward: readonly Coin[] | null; -} - -export interface DistributionDelegatorRewardsResponse { - readonly height: string; - readonly result: { - readonly rewards: readonly RewardContainer[] | null; - readonly total: readonly Coin[] | null; - }; -} - -export interface DistributionDelegatorRewardResponse { - readonly height: string; - readonly result: readonly Coin[]; -} - -export interface DistributionWithdrawAddressResponse { - readonly height: string; - readonly result: string; -} - -export interface DistributionValidatorResponse { - readonly height: string; - readonly result: { - readonly operator_address: string; - readonly self_bond_rewards: readonly Coin[]; - readonly val_commission: readonly Coin[]; - }; -} - -export interface DistributionValidatorRewardsResponse { - readonly height: string; - readonly result: readonly Coin[]; -} - -export interface DistributionValidatorOutstandingRewardsResponse { - readonly height: string; - readonly result: readonly Coin[]; -} - -export interface DistributionParametersResponse { - readonly height: string; - readonly result: { - readonly community_tax: string; - readonly base_proposer_reward: string; - readonly bonus_proposer_reward: string; - readonly withdraw_addr_enabled: boolean; - }; -} - -export interface DistributionCommunityPoolResponse { - readonly height: string; - readonly result: readonly Coin[]; -} - -export interface DistributionExtension { - readonly distribution: { - readonly delegatorRewards: (delegatorAddress: string) => Promise; - readonly delegatorReward: ( - delegatorAddress: string, - validatorAddress: string, - ) => Promise; - readonly withdrawAddress: (delegatorAddress: string) => Promise; - readonly validator: (validatorAddress: string) => Promise; - readonly validatorRewards: (validatorAddress: string) => Promise; - readonly validatorOutstandingRewards: ( - validatorAddress: string, - ) => Promise; - - readonly parameters: () => Promise; - readonly communityPool: () => Promise; - }; -} - -export function setupDistributionExtension(base: LcdClient): DistributionExtension { - return { - distribution: { - delegatorRewards: async (delegatorAddress: string) => - base.get(`/distribution/delegators/${delegatorAddress}/rewards`), - delegatorReward: async (delegatorAddress: string, validatorAddress: string) => - base.get(`/distribution/delegators/${delegatorAddress}/rewards/${validatorAddress}`), - withdrawAddress: async (delegatorAddress: string) => - base.get(`/distribution/delegators/${delegatorAddress}/withdraw_address`), - validator: async (validatorAddress: string) => base.get(`/distribution/validators/${validatorAddress}`), - validatorRewards: async (validatorAddress: string) => - base.get(`/distribution/validators/${validatorAddress}/rewards`), - validatorOutstandingRewards: async (validatorAddress: string) => - base.get(`/distribution/validators/${validatorAddress}/outstanding_rewards`), - parameters: async () => base.get(`/distribution/parameters`), - communityPool: async () => base.get(`/distribution/community_pool`), - }, - }; -} diff --git a/packages/launchpad/src/lcdapi/gov.spec.ts b/packages/launchpad/src/lcdapi/gov.spec.ts deleted file mode 100644 index 8fe54e4798..0000000000 --- a/packages/launchpad/src/lcdapi/gov.spec.ts +++ /dev/null @@ -1,302 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { coins, makeSignDoc, Secp256k1HdWallet } from "@cosmjs/amino"; -import { sleep } from "@cosmjs/utils"; - -import { assertIsBroadcastTxSuccess } from "../cosmosclient"; -import { SigningCosmosClient } from "../signingcosmosclient"; -import { - dateTimeStampMatcher, - faucet, - launchpad, - launchpadEnabled, - nonNegativeIntegerMatcher, - pendingWithoutLaunchpad, -} from "../testutils.spec"; -import { GovExtension, GovParametersType, setupGovExtension } from "./gov"; -import { LcdClient } from "./lcdclient"; - -function makeGovClient(apiUrl: string): LcdClient & GovExtension { - return LcdClient.withExtensions({ apiUrl }, setupGovExtension); -} - -describe("GovExtension", () => { - const defaultFee = { - amount: coins(25000, "ucosm"), - gas: "1500000", // 1.5 million - }; - let proposalId: string; - - beforeAll(async () => { - if (launchpadEnabled()) { - const wallet = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic); - const client = new SigningCosmosClient(launchpad.endpoint, faucet.address0, wallet); - - const chainId = await client.getChainId(); - const proposalMsg = { - type: "cosmos-sdk/MsgSubmitProposal", - value: { - content: { - type: "cosmos-sdk/TextProposal", - value: { - description: "This proposal proposes to test whether this proposal passes", - title: "Test Proposal", - }, - }, - proposer: faucet.address0, - initial_deposit: coins(25000000, "ustake"), - }, - }; - const proposalMemo = "Test proposal for wasmd"; - const { accountNumber: proposalAccountNumber, sequence: proposalSequence } = await client.getSequence(); - const proposalSignDoc = makeSignDoc( - [proposalMsg], - defaultFee, - chainId, - proposalMemo, - proposalAccountNumber, - proposalSequence, - ); - const { signature: proposalSignature } = await wallet.signAmino(faucet.address0, proposalSignDoc); - const proposalTx = { - msg: [proposalMsg], - fee: defaultFee, - memo: proposalMemo, - signatures: [proposalSignature], - }; - - const proposalResult = await client.broadcastTx(proposalTx); - assertIsBroadcastTxSuccess(proposalResult); - proposalId = proposalResult.logs[0].events - .find(({ type }) => type === "submit_proposal")! - .attributes.find(({ key }) => key === "proposal_id")!.value; - - const voteMsg = { - type: "cosmos-sdk/MsgVote", - value: { - proposal_id: proposalId, - voter: faucet.address0, - option: "Yes", - }, - }; - const voteMemo = "Test vote for wasmd"; - const { accountNumber: voteAccountNumber, sequence: voteSequence } = await client.getSequence(); - const voteSignDoc = makeSignDoc( - [voteMsg], - defaultFee, - chainId, - voteMemo, - voteAccountNumber, - voteSequence, - ); - const { signature: voteSignature } = await wallet.signAmino(faucet.address0, voteSignDoc); - const voteTx = { - msg: [voteMsg], - fee: defaultFee, - memo: voteMemo, - signatures: [voteSignature], - }; - await client.broadcastTx(voteTx); - - await sleep(75); // wait until transactions are indexed - } - }); - - describe("parameters", () => { - it("works for deposit", async () => { - pendingWithoutLaunchpad(); - const client = makeGovClient(launchpad.endpoint); - const paramsType = GovParametersType.Deposit; - const response = await client.gov.parameters(paramsType); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: { - min_deposit: [{ denom: "ustake", amount: "10000000" }], - max_deposit_period: "172800000000000", - }, - }); - }); - - it("works for tallying", async () => { - pendingWithoutLaunchpad(); - const client = makeGovClient(launchpad.endpoint); - const paramsType = GovParametersType.Tallying; - const response = await client.gov.parameters(paramsType); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: { - quorum: "0.334000000000000000", - threshold: "0.500000000000000000", - veto: "0.334000000000000000", - }, - }); - }); - - it("works for voting", async () => { - pendingWithoutLaunchpad(); - const client = makeGovClient(launchpad.endpoint); - const paramsType = GovParametersType.Voting; - const response = await client.gov.parameters(paramsType); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: { - voting_period: "172800000000000", - }, - }); - }); - }); - - describe("proposals", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeGovClient(launchpad.endpoint); - const response = await client.gov.proposals(); - expect(response.height).toMatch(nonNegativeIntegerMatcher); - expect(response.result.length).toBeGreaterThanOrEqual(1); - expect(response.result[response.result.length - 1]).toEqual({ - content: { - type: "cosmos-sdk/TextProposal", - value: { - title: "Test Proposal", - description: "This proposal proposes to test whether this proposal passes", - }, - }, - id: proposalId, - proposal_status: "VotingPeriod", - final_tally_result: { yes: "0", abstain: "0", no: "0", no_with_veto: "0" }, - submit_time: jasmine.stringMatching(dateTimeStampMatcher), - deposit_end_time: jasmine.stringMatching(dateTimeStampMatcher), - total_deposit: [{ denom: "ustake", amount: "25000000" }], - voting_start_time: jasmine.stringMatching(dateTimeStampMatcher), - voting_end_time: jasmine.stringMatching(dateTimeStampMatcher), - }); - }); - }); - - describe("proposal", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeGovClient(launchpad.endpoint); - const response = await client.gov.proposal(proposalId); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: { - content: { - type: "cosmos-sdk/TextProposal", - value: { - title: "Test Proposal", - description: "This proposal proposes to test whether this proposal passes", - }, - }, - id: proposalId, - proposal_status: "VotingPeriod", - final_tally_result: { yes: "0", abstain: "0", no: "0", no_with_veto: "0" }, - submit_time: jasmine.stringMatching(dateTimeStampMatcher), - deposit_end_time: jasmine.stringMatching(dateTimeStampMatcher), - total_deposit: [{ denom: "ustake", amount: "25000000" }], - voting_start_time: jasmine.stringMatching(dateTimeStampMatcher), - voting_end_time: jasmine.stringMatching(dateTimeStampMatcher), - }, - }); - }); - }); - - describe("proposer", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeGovClient(launchpad.endpoint); - const response = await client.gov.proposer(proposalId); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: { - proposal_id: proposalId, - proposer: faucet.address0, - }, - }); - }); - }); - - describe("deposits", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeGovClient(launchpad.endpoint); - const response = await client.gov.deposits(proposalId); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: [ - { - proposal_id: proposalId, - depositor: faucet.address0, - amount: [{ denom: "ustake", amount: "25000000" }], - }, - ], - }); - }); - }); - - describe("deposit", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeGovClient(launchpad.endpoint); - const response = await client.gov.deposit(proposalId, faucet.address0); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: { - proposal_id: proposalId, - depositor: faucet.address0, - amount: [{ denom: "ustake", amount: "25000000" }], - }, - }); - }); - }); - - describe("tally", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeGovClient(launchpad.endpoint); - const response = await client.gov.tally(proposalId); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: { - yes: jasmine.stringMatching(nonNegativeIntegerMatcher), - abstain: jasmine.stringMatching(nonNegativeIntegerMatcher), - no: jasmine.stringMatching(nonNegativeIntegerMatcher), - no_with_veto: jasmine.stringMatching(nonNegativeIntegerMatcher), - }, - }); - }); - }); - - describe("votes", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeGovClient(launchpad.endpoint); - const response = await client.gov.votes(proposalId); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: [ - { - proposal_id: proposalId, - voter: faucet.address0, - option: "Yes", - }, - ], - }); - }); - }); - - describe("vote", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeGovClient(launchpad.endpoint); - const response = await client.gov.vote(proposalId, faucet.address0); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: { - voter: faucet.address0, - proposal_id: proposalId, - option: "Yes", - }, - }); - }); - }); -}); diff --git a/packages/launchpad/src/lcdapi/gov.ts b/packages/launchpad/src/lcdapi/gov.ts deleted file mode 100644 index 7c05c0c3a5..0000000000 --- a/packages/launchpad/src/lcdapi/gov.ts +++ /dev/null @@ -1,151 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { Coin } from "@cosmjs/amino"; - -import { LcdClient } from "./lcdclient"; - -export enum GovParametersType { - Deposit = "deposit", - Tallying = "tallying", - Voting = "voting", -} - -export interface GovParametersDepositResponse { - readonly height: string; - readonly result: { - readonly min_deposit: readonly Coin[]; - readonly max_deposit_period: string; - }; -} - -export interface GovParametersTallyingResponse { - readonly height: string; - readonly result: { - readonly quorum: string; - readonly threshold: string; - readonly veto: string; - }; -} - -export interface GovParametersVotingResponse { - readonly height: string; - readonly result: { - readonly voting_period: string; - }; -} - -export type GovParametersResponse = - | GovParametersDepositResponse - | GovParametersTallyingResponse - | GovParametersVotingResponse; - -export interface Tally { - readonly yes: string; - readonly abstain: string; - readonly no: string; - readonly no_with_veto: string; -} - -export interface Proposal { - readonly id: string; - readonly proposal_status: string; - readonly final_tally_result: Tally; - readonly submit_time: string; - readonly total_deposit: readonly Coin[]; - readonly deposit_end_time: string; - readonly voting_start_time: string; - readonly voting_end_time: string; - readonly content: { - readonly type: string; - readonly value: { - readonly title: string; - readonly description: string; - }; - }; -} - -export interface GovProposalsResponse { - readonly height: string; - readonly result: readonly Proposal[]; -} - -export interface GovProposalResponse { - readonly height: string; - readonly result: Proposal; -} - -export interface GovProposerResponse { - readonly height: string; - readonly result: { - readonly proposal_id: string; - readonly proposer: string; - }; -} - -export interface Deposit { - readonly amount: readonly Coin[]; - readonly proposal_id: string; - readonly depositor: string; -} - -export interface GovDepositsResponse { - readonly height: string; - readonly result: readonly Deposit[]; -} - -export interface GovDepositResponse { - readonly height: string; - readonly result: Deposit; -} - -export interface GovTallyResponse { - readonly height: string; - readonly result: Tally; -} - -export interface Vote { - readonly voter: string; - readonly proposal_id: string; - readonly option: string; -} - -export interface GovVotesResponse { - readonly height: string; - readonly result: readonly Vote[]; -} - -export interface GovVoteResponse { - readonly height: string; - readonly result: Vote; -} - -export interface GovExtension { - readonly gov: { - readonly parameters: (parametersType: GovParametersType) => Promise; - readonly proposals: () => Promise; - readonly proposal: (proposalId: string) => Promise; - readonly proposer: (proposalId: string) => Promise; - readonly deposits: (proposalId: string) => Promise; - readonly deposit: (proposalId: string, depositorAddress: string) => Promise; - readonly tally: (proposalId: string) => Promise; - readonly votes: (proposalId: string) => Promise; - readonly vote: (proposalId: string, voterAddress: string) => Promise; - }; -} - -export function setupGovExtension(base: LcdClient): GovExtension { - return { - gov: { - parameters: async (parametersType: GovParametersType) => base.get(`/gov/parameters/${parametersType}`), - proposals: async () => base.get("/gov/proposals"), - proposal: async (proposalId: string) => base.get(`/gov/proposals/${proposalId}`), - proposer: async (proposalId: string) => base.get(`/gov/proposals/${proposalId}/proposer`), - deposits: async (proposalId: string) => base.get(`/gov/proposals/${proposalId}/deposits`), - deposit: async (proposalId: string, depositorAddress: string) => - base.get(`/gov/proposals/${proposalId}/deposits/${depositorAddress}`), - tally: async (proposalId: string) => base.get(`/gov/proposals/${proposalId}/tally`), - votes: async (proposalId: string) => base.get(`/gov/proposals/${proposalId}/votes`), - vote: async (proposalId: string, voterAddress: string) => - base.get(`/gov/proposals/${proposalId}/votes/${voterAddress}`), - }, - }; -} diff --git a/packages/launchpad/src/lcdapi/index.ts b/packages/launchpad/src/lcdapi/index.ts deleted file mode 100644 index f68f6b3c26..0000000000 --- a/packages/launchpad/src/lcdapi/index.ts +++ /dev/null @@ -1,84 +0,0 @@ -// -// Standard modules (see tracking issue https://github.com/cosmos/cosmjs/issues/276) -// - -export { AuthAccountsResponse, AuthExtension, BaseAccount, setupAuthExtension } from "./auth"; -export { BankBalancesResponse, BankExtension, setupBankExtension } from "./bank"; -export { - DistributionCommunityPoolResponse, - DistributionDelegatorRewardResponse, - DistributionDelegatorRewardsResponse, - DistributionExtension, - DistributionParametersResponse, - DistributionValidatorOutstandingRewardsResponse, - DistributionValidatorResponse, - DistributionValidatorRewardsResponse, - DistributionWithdrawAddressResponse, - setupDistributionExtension, -} from "./distribution"; -export { - GovDepositResponse, - GovDepositsResponse, - GovExtension, - GovParametersResponse, - GovProposalResponse, - GovProposalsResponse, - GovProposerResponse, - GovTallyResponse, - GovVoteResponse, - GovVotesResponse, - setupGovExtension, -} from "./gov"; -export { - MintAnnualProvisionsResponse, - MintExtension, - MintInflationResponse, - MintParametersResponse, - setupMintExtension, -} from "./mint"; -export { - setupSlashingExtension, - SlashingExtension, - SlashingParametersResponse, - SlashingSigningInfosResponse, -} from "./slashing"; -export { - setupStakingExtension, - StakingDelegationResponse, - StakingDelegatorDelegationsResponse, - StakingDelegatorTransactionsResponse, - StakingDelegatorUnbondingDelegationsResponse, - StakingDelegatorValidatorResponse, - StakingDelegatorValidatorsResponse, - StakingExtension, - StakingHistoricalInfoResponse, - StakingParametersResponse, - StakingPoolResponse, - StakingRedelegationsResponse, - StakingUnbondingDelegationResponse, - StakingValidatorDelegationsResponse, - StakingValidatorResponse, - StakingValidatorsResponse, - StakingValidatorUnbondingDelegationsResponse, -} from "./staking"; -export { setupSupplyExtension, SupplyExtension, TotalSupplyAllResponse, TotalSupplyResponse } from "./supply"; - -// -// Base types -// - -export { - BlockResponse, - BroadcastMode, - BroadcastTxsResponse, - EncodeTxResponse, - NodeInfoResponse, - SearchTxsResponse, - TxsResponse, -} from "./base"; -export { LcdApiArray, LcdClient, normalizeLcdApiArray } from "./lcdclient"; - -// -// Utils for interacting with the client/API -// -export { normalizePubkey, uint64ToNumber, uint64ToString } from "./utils"; diff --git a/packages/launchpad/src/lcdapi/lcdclient.spec.ts b/packages/launchpad/src/lcdapi/lcdclient.spec.ts deleted file mode 100644 index 8499ec1dc4..0000000000 --- a/packages/launchpad/src/lcdapi/lcdclient.spec.ts +++ /dev/null @@ -1,872 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { - Coin, - coins, - makeCosmoshubPath, - makeSignDoc, - makeStdTx, - Secp256k1HdWallet, - StdFee, - StdTx, -} from "@cosmjs/amino"; -import { assert, sleep } from "@cosmjs/utils"; - -import { isBroadcastTxFailure } from "../cosmosclient"; -import { parseLogs } from "../logs"; -import { MsgSend } from "../msgs"; -import { SigningCosmosClient } from "../signingcosmosclient"; -import cosmoshub from "../testdata/cosmoshub.json"; -import { - faucet, - launchpad, - launchpadEnabled, - makeRandomAddress, - nonNegativeIntegerMatcher, - pendingWithoutLaunchpad, - tendermintIdMatcher, - unused, -} from "../testutils.spec"; -import { isWrappedStdTx } from "../tx"; -import { setupAuthExtension } from "./auth"; -import { TxsResponse } from "./base"; -import { LcdApiArray, LcdClient } from "./lcdclient"; - -describe("LcdClient", () => { - const defaultRecipientAddress = makeRandomAddress(); - - it("can be constructed", () => { - const client = new LcdClient(launchpad.endpoint); - expect(client).toBeTruthy(); - }); - - describe("withModules", () => { - interface TotalSupplyAllResponse { - readonly height: string; - readonly result: LcdApiArray; - } - - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type - function setupSupplyExtension(base: LcdClient) { - return { - supply: { - totalAll: async (): Promise => { - return base.get(`/supply/total`); - }, - }, - }; - } - - interface BankBalancesResponse { - readonly height: string; - readonly result: readonly Coin[]; - } - - interface BankExtension { - readonly bank: { - readonly balances: (address: string) => Promise; - }; - } - - function setupBankExtension(base: LcdClient): BankExtension { - return { - bank: { - balances: async (address: string) => { - const path = `/bank/balances/${address}`; - return base.get(path); - }, - }, - }; - } - - it("works for no extension", async () => { - const client = LcdClient.withExtensions({ apiUrl: launchpad.endpoint }); - expect(client).toBeTruthy(); - }); - - it("works for one extension", async () => { - pendingWithoutLaunchpad(); - - const client = LcdClient.withExtensions({ apiUrl: launchpad.endpoint }, setupSupplyExtension); - const supply = await client.supply.totalAll(); - expect(supply).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: [ - { - amount: jasmine.stringMatching(nonNegativeIntegerMatcher), - denom: "ucosm", - }, - { - amount: jasmine.stringMatching(nonNegativeIntegerMatcher), - denom: "ustake", - }, - ], - }); - }); - - it("works for two extensions", async () => { - pendingWithoutLaunchpad(); - - const client = LcdClient.withExtensions( - { apiUrl: launchpad.endpoint }, - setupSupplyExtension, - setupBankExtension, - ); - const supply = await client.supply.totalAll(); - expect(supply).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: [ - { - amount: jasmine.stringMatching(nonNegativeIntegerMatcher), - denom: "ucosm", - }, - { - amount: jasmine.stringMatching(nonNegativeIntegerMatcher), - denom: "ustake", - }, - ], - }); - const balances = await client.bank.balances(unused.address); - expect(balances).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: [ - { - denom: "ucosm", - amount: "1000000000", - }, - { - denom: "ustake", - amount: "1000000000", - }, - ], - }); - }); - - it("can merge two extensions into the same module", async () => { - pendingWithoutLaunchpad(); - - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type - function setupSupplyExtensionBasic(base: LcdClient) { - return { - supply: { - totalAll: async () => { - const path = `/supply/total`; - return base.get(path); - }, - }, - }; - } - - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type - function setupSupplyExtensionPremium(base: LcdClient) { - return { - supply: { - total: async (denom: string) => { - return base.get(`/supply/total/${denom}`); - }, - }, - }; - } - - const client = LcdClient.withExtensions( - { apiUrl: launchpad.endpoint }, - setupSupplyExtensionBasic, - setupSupplyExtensionPremium, - ); - expect(client.supply.totalAll).toEqual(jasmine.any(Function)); - expect(client.supply.total).toEqual(jasmine.any(Function)); - }); - }); - - // The /txs endpoints - - describe("txById", () => { - let successful: - | { - readonly sender: string; - readonly recipient: string; - readonly hash: string; - } - | undefined; - let unsuccessful: - | { - readonly sender: string; - readonly recipient: string; - readonly hash: string; - } - | undefined; - - beforeAll(async () => { - if (launchpadEnabled()) { - const wallet = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic); - const accounts = await wallet.getAccounts(); - const [{ address: walletAddress }] = accounts; - const client = new SigningCosmosClient(launchpad.endpoint, faucet.address0, wallet); - - { - const recipient = makeRandomAddress(); - const amount = coins(1234567, "ucosm"); - const result = await client.sendTokens(recipient, amount); - successful = { - sender: faucet.address0, - recipient: recipient, - hash: result.transactionHash, - }; - } - - { - const memo = "Sending more than I can afford"; - const recipient = makeRandomAddress(); - const amount = coins(123456700000000, "ucosm"); - const sendMsg: MsgSend = { - type: "cosmos-sdk/MsgSend", - value: { - from_address: faucet.address0, - to_address: recipient, - amount: amount, - }, - }; - const fee = { - amount: coins(2000, "ucosm"), - gas: "80000", // 80k - }; - const { accountNumber, sequence } = await client.getSequence(); - const chainId = await client.getChainId(); - const signDoc = makeSignDoc([sendMsg], fee, chainId, memo, accountNumber, sequence); - const { signed, signature } = await wallet.signAmino(walletAddress, signDoc); - const signedTx = makeStdTx(signed, signature); - const transactionId = await client.getIdentifier({ type: "cosmos-sdk/StdTx", value: signedTx }); - const result = await client.broadcastTx(signedTx); - assert(isBroadcastTxFailure(result)); - unsuccessful = { - sender: faucet.address0, - recipient: recipient, - hash: transactionId, - }; - } - - await sleep(75); // wait until transactions are indexed - } - }); - - it("works for successful transaction", async () => { - pendingWithoutLaunchpad(); - assert(successful); - const client = new LcdClient(launchpad.endpoint); - const result = await client.txById(successful.hash); - expect(result.height).toBeGreaterThanOrEqual(1); - expect(result.txhash).toEqual(successful.hash); - expect(result.codespace).toBeUndefined(); - expect(result.code).toBeUndefined(); - const logs = parseLogs(result.logs); - expect(logs).toEqual([ - { - msg_index: 0, - log: "", - events: [ - { - type: "message", - attributes: [ - { key: "action", value: "send" }, - { key: "sender", value: successful.sender }, - { key: "module", value: "bank" }, - ], - }, - { - type: "transfer", - attributes: [ - { key: "recipient", value: successful.recipient }, - { key: "sender", value: successful.sender }, - { key: "amount", value: "1234567ucosm" }, - ], - }, - ], - }, - ]); - }); - - it("works for unsuccessful transaction", async () => { - pendingWithoutLaunchpad(); - assert(unsuccessful); - const client = new LcdClient(launchpad.endpoint); - const result = await client.txById(unsuccessful.hash); - expect(result.height).toBeGreaterThanOrEqual(1); - expect(result.txhash).toEqual(unsuccessful.hash); - expect(result.codespace).toEqual("sdk"); - expect(result.code).toEqual(5); - expect(result.logs).toBeUndefined(); - expect(result.raw_log).toContain("insufficient funds"); - }); - }); - - describe("txsQuery", () => { - let broadcasted: - | { - readonly sender: string; - readonly recipient: string; - readonly hash: string; - readonly height: number; - readonly tx: TxsResponse; - } - | undefined; - - beforeAll(async () => { - if (launchpadEnabled()) { - const wallet = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic); - const client = new SigningCosmosClient(launchpad.endpoint, faucet.address0, wallet); - - const recipient = makeRandomAddress(); - const amount = coins(1234567, "ucosm"); - const result = await client.sendTokens(recipient, amount); - - await sleep(75); // wait until tx is indexed - const txDetails = await new LcdClient(launchpad.endpoint).txById(result.transactionHash); - broadcasted = { - sender: faucet.address0, - recipient: recipient, - hash: result.transactionHash, - height: Number.parseInt(txDetails.height, 10), - tx: txDetails, - }; - } - }); - - it("can query transactions by height", async () => { - pendingWithoutLaunchpad(); - assert(broadcasted); - const client = new LcdClient(launchpad.endpoint); - const result = await client.txsQuery(`tx.height=${broadcasted.height}&limit=26`); - expect(result).toEqual({ - count: jasmine.stringMatching(/^(1|2|3|4|5)$/), // 1-5 transactions as string - limit: "26", - page_number: "1", - page_total: "1", - total_count: jasmine.stringMatching(/^(1|2|3|4|5)$/), // 1-5 transactions as string - txs: jasmine.arrayContaining([broadcasted.tx]), - }); - }); - - it("can query transactions by ID", async () => { - pendingWithoutLaunchpad(); - assert(broadcasted); - const client = new LcdClient(launchpad.endpoint); - const result = await client.txsQuery(`tx.hash=${broadcasted.hash}&limit=26`); - expect(result).toEqual({ - count: "1", - limit: "26", - page_number: "1", - page_total: "1", - total_count: "1", - txs: [broadcasted.tx], - }); - }); - - it("can query transactions by sender", async () => { - pendingWithoutLaunchpad(); - assert(broadcasted); - const client = new LcdClient(launchpad.endpoint); - const result = await client.txsQuery(`message.sender=${broadcasted.sender}&limit=200`); - expect(parseInt(result.count, 10)).toBeGreaterThanOrEqual(1); - expect(parseInt(result.limit, 10)).toEqual(200); - expect(parseInt(result.page_number, 10)).toEqual(1); - expect(parseInt(result.page_total, 10)).toEqual(1); - expect(parseInt(result.total_count, 10)).toBeGreaterThanOrEqual(1); - expect(result.txs.length).toBeGreaterThanOrEqual(1); - expect(result.txs[result.txs.length - 1]).toEqual(broadcasted.tx); - }); - - it("can query transactions by recipient", async () => { - pendingWithoutLaunchpad(); - assert(broadcasted); - const client = new LcdClient(launchpad.endpoint); - const result = await client.txsQuery(`transfer.recipient=${broadcasted.recipient}&limit=200`); - expect(parseInt(result.count, 10)).toEqual(1); - expect(parseInt(result.limit, 10)).toEqual(200); - expect(parseInt(result.page_number, 10)).toEqual(1); - expect(parseInt(result.page_total, 10)).toEqual(1); - expect(parseInt(result.total_count, 10)).toEqual(1); - expect(result.txs.length).toBeGreaterThanOrEqual(1); - expect(result.txs[result.txs.length - 1]).toEqual(broadcasted.tx); - }); - - it("can filter by tx.hash and tx.minheight", async () => { - pending("This combination is broken 🤷‍♂️. Handle client-side at higher level."); - pendingWithoutLaunchpad(); - assert(broadcasted); - const client = new LcdClient(launchpad.endpoint); - const hashQuery = `tx.hash=${broadcasted.hash}`; - - { - const { count } = await client.txsQuery(`${hashQuery}&tx.minheight=0`); - expect(count).toEqual("1"); - } - - { - const { count } = await client.txsQuery(`${hashQuery}&tx.minheight=${broadcasted.height - 1}`); - expect(count).toEqual("1"); - } - - { - const { count } = await client.txsQuery(`${hashQuery}&tx.minheight=${broadcasted.height}`); - expect(count).toEqual("1"); - } - - { - const { count } = await client.txsQuery(`${hashQuery}&tx.minheight=${broadcasted.height + 1}`); - expect(count).toEqual("0"); - } - }); - - it("can filter by recipient and tx.minheight", async () => { - pendingWithoutLaunchpad(); - assert(broadcasted); - const client = new LcdClient(launchpad.endpoint); - const recipientQuery = `transfer.recipient=${broadcasted.recipient}`; - - { - const { count } = await client.txsQuery(`${recipientQuery}&tx.minheight=0`); - expect(count).toEqual("1"); - } - - { - const { count } = await client.txsQuery(`${recipientQuery}&tx.minheight=${broadcasted.height - 1}`); - expect(count).toEqual("1"); - } - - { - const { count } = await client.txsQuery(`${recipientQuery}&tx.minheight=${broadcasted.height}`); - expect(count).toEqual("1"); - } - - { - const { count } = await client.txsQuery(`${recipientQuery}&tx.minheight=${broadcasted.height + 1}`); - expect(count).toEqual("0"); - } - }); - - it("can filter by recipient and tx.maxheight", async () => { - pendingWithoutLaunchpad(); - assert(broadcasted); - const client = new LcdClient(launchpad.endpoint); - const recipientQuery = `transfer.recipient=${broadcasted.recipient}`; - - { - const { count } = await client.txsQuery(`${recipientQuery}&tx.maxheight=9999999999999`); - expect(count).toEqual("1"); - } - - { - const { count } = await client.txsQuery(`${recipientQuery}&tx.maxheight=${broadcasted.height + 1}`); - expect(count).toEqual("1"); - } - - { - const { count } = await client.txsQuery(`${recipientQuery}&tx.maxheight=${broadcasted.height}`); - expect(count).toEqual("1"); - } - - { - const { count } = await client.txsQuery(`${recipientQuery}&tx.maxheight=${broadcasted.height - 1}`); - expect(count).toEqual("0"); - } - }); - }); - - describe("encodeTx", () => { - it("works for cosmoshub example", async () => { - pendingWithoutLaunchpad(); - const client = new LcdClient(launchpad.endpoint); - assert(isWrappedStdTx(cosmoshub.tx)); - const response = await client.encodeTx(cosmoshub.tx); - expect(response).toEqual( - jasmine.objectContaining({ - tx: cosmoshub.tx_data, - }), - ); - }); - }); - - describe("broadcastTx", () => { - it("can send tokens", async () => { - pendingWithoutLaunchpad(); - const wallet = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic); - const accounts = await wallet.getAccounts(); - const [{ address: walletAddress }] = accounts; - - const memo = "My first contract on chain"; - const theMsg: MsgSend = { - type: "cosmos-sdk/MsgSend", - value: { - from_address: faucet.address0, - to_address: defaultRecipientAddress, - amount: [ - { - denom: "ucosm", - amount: "1234567", - }, - ], - }, - }; - - const fee: StdFee = { - amount: [ - { - amount: "5000", - denom: "ucosm", - }, - ], - gas: "890000", - }; - - const client = LcdClient.withExtensions({ apiUrl: launchpad.endpoint }, setupAuthExtension); - const { account_number, sequence } = (await client.auth.account(faucet.address0)).result.value; - - const signDoc = makeSignDoc([theMsg], fee, launchpad.chainId, memo, account_number, sequence); - const { signed, signature } = await wallet.signAmino(walletAddress, signDoc); - const signedTx = makeStdTx(signed, signature); - const result = await client.broadcastTx(signedTx); - expect(result.code).toBeUndefined(); - expect(result).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - txhash: jasmine.stringMatching(tendermintIdMatcher), - // code is not set - raw_log: jasmine.stringMatching(/^\[.+\]$/i), - logs: jasmine.any(Array), - gas_wanted: jasmine.stringMatching(nonNegativeIntegerMatcher), - gas_used: jasmine.stringMatching(nonNegativeIntegerMatcher), - }); - }); - - it("can't send transaction with additional signatures", async () => { - pendingWithoutLaunchpad(); - const account1 = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic, { - hdPaths: [makeCosmoshubPath(0)], - }); - const account2 = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic, { - hdPaths: [makeCosmoshubPath(1)], - }); - const account3 = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic, { - hdPaths: [makeCosmoshubPath(2)], - }); - const [address1, address2, address3] = await Promise.all( - [account1, account2, account3].map(async (wallet) => { - return (await wallet.getAccounts())[0].address; - }), - ); - - const memo = "My first contract on chain"; - const theMsg: MsgSend = { - type: "cosmos-sdk/MsgSend", - value: { - from_address: address1, - to_address: defaultRecipientAddress, - amount: [ - { - denom: "ucosm", - amount: "1234567", - }, - ], - }, - }; - - const fee: StdFee = { - amount: [ - { - amount: "5000", - denom: "ucosm", - }, - ], - gas: "890000", - }; - - const client = LcdClient.withExtensions({ apiUrl: launchpad.endpoint }, setupAuthExtension); - const { account_number: an1, sequence: sequence1 } = (await client.auth.account(address1)).result.value; - const { account_number: an2, sequence: sequence2 } = (await client.auth.account(address2)).result.value; - const { account_number: an3, sequence: sequence3 } = (await client.auth.account(address3)).result.value; - - const signDoc1 = makeSignDoc([theMsg], fee, launchpad.chainId, memo, an1, sequence1); - const signDoc2 = makeSignDoc([theMsg], fee, launchpad.chainId, memo, an2, sequence2); - const signDoc3 = makeSignDoc([theMsg], fee, launchpad.chainId, memo, an3, sequence3); - const { signature: signature1 } = await account1.signAmino(address1, signDoc1); - const { signature: signature2 } = await account2.signAmino(address2, signDoc2); - const { signature: signature3 } = await account3.signAmino(address3, signDoc3); - const signedTx: StdTx = { - msg: [theMsg], - fee: fee, - memo: memo, - signatures: [signature1, signature2, signature3], - }; - const broadcastResult = await client.broadcastTx(signedTx); - expect(broadcastResult.code).toEqual(4); - expect(broadcastResult.raw_log).toContain("wrong number of signers"); - }); - - it("can send multiple messages with one signature", async () => { - pendingWithoutLaunchpad(); - const wallet = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic); - const accounts = await wallet.getAccounts(); - const [{ address: walletAddress }] = accounts; - - const memo = "My first contract on chain"; - const msg1: MsgSend = { - type: "cosmos-sdk/MsgSend", - value: { - from_address: walletAddress, - to_address: defaultRecipientAddress, - amount: [ - { - denom: "ucosm", - amount: "1234567", - }, - ], - }, - }; - const msg2: MsgSend = { - type: "cosmos-sdk/MsgSend", - value: { - from_address: walletAddress, - to_address: defaultRecipientAddress, - amount: [ - { - denom: "ucosm", - amount: "7654321", - }, - ], - }, - }; - - const fee: StdFee = { - amount: [ - { - amount: "5000", - denom: "ucosm", - }, - ], - gas: "890000", - }; - - const client = LcdClient.withExtensions({ apiUrl: launchpad.endpoint }, setupAuthExtension); - const { account_number, sequence } = (await client.auth.account(walletAddress)).result.value; - - const signDoc = makeSignDoc([msg1, msg2], fee, launchpad.chainId, memo, account_number, sequence); - const { signed, signature } = await wallet.signAmino(walletAddress, signDoc); - const signedTx = makeStdTx(signed, signature); - const broadcastResult = await client.broadcastTx(signedTx); - expect(broadcastResult.code).toBeUndefined(); - }); - - it("can send multiple messages with multiple signatures", async () => { - pendingWithoutLaunchpad(); - const account1 = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic, { - hdPaths: [makeCosmoshubPath(0)], - }); - const account2 = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic, { - hdPaths: [makeCosmoshubPath(1)], - }); - const [address1, address2] = await Promise.all( - [account1, account2].map(async (wallet) => { - return (await wallet.getAccounts())[0].address; - }), - ); - - const memo = "My first contract on chain"; - const msg1: MsgSend = { - type: "cosmos-sdk/MsgSend", - value: { - from_address: address1, - to_address: defaultRecipientAddress, - amount: [ - { - denom: "ucosm", - amount: "1234567", - }, - ], - }, - }; - const msg2: MsgSend = { - type: "cosmos-sdk/MsgSend", - value: { - from_address: address2, - to_address: defaultRecipientAddress, - amount: [ - { - denom: "ucosm", - amount: "7654321", - }, - ], - }, - }; - - const fee: StdFee = { - amount: [ - { - amount: "5000", - denom: "ucosm", - }, - ], - gas: "890000", - }; - - const client = LcdClient.withExtensions({ apiUrl: launchpad.endpoint }, setupAuthExtension); - const { account_number: an1, sequence: sequence1 } = (await client.auth.account(address1)).result.value; - const { account_number: an2, sequence: sequence2 } = (await client.auth.account(address2)).result.value; - - const signDoc1 = makeSignDoc([msg2, msg1], fee, launchpad.chainId, memo, an1, sequence1); - const signDoc2 = makeSignDoc([msg2, msg1], fee, launchpad.chainId, memo, an2, sequence2); - const { signature: signature1 } = await account1.signAmino(address1, signDoc1); - const { signature: signature2 } = await account2.signAmino(address2, signDoc2); - const signedTx: StdTx = { - msg: [msg2, msg1], - fee: fee, - memo: memo, - signatures: [signature2, signature1], - }; - const broadcastResult = await client.broadcastTx(signedTx); - expect(broadcastResult.code).toBeUndefined(); - - await sleep(500); - const searched = await client.txsQuery(`tx.hash=${broadcastResult.txhash}`); - expect(searched.txs.length).toEqual(1); - expect(searched.txs[0].tx.value.signatures).toEqual([signature2, signature1]); - }); - - it("can't send transaction with wrong signature order (1)", async () => { - pendingWithoutLaunchpad(); - const account1 = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic, { - hdPaths: [makeCosmoshubPath(0)], - }); - const account2 = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic, { - hdPaths: [makeCosmoshubPath(1)], - }); - const [address1, address2] = await Promise.all( - [account1, account2].map(async (wallet) => { - return (await wallet.getAccounts())[0].address; - }), - ); - - const memo = "My first contract on chain"; - const msg1: MsgSend = { - type: "cosmos-sdk/MsgSend", - value: { - from_address: address1, - to_address: defaultRecipientAddress, - amount: [ - { - denom: "ucosm", - amount: "1234567", - }, - ], - }, - }; - const msg2: MsgSend = { - type: "cosmos-sdk/MsgSend", - value: { - from_address: address2, - to_address: defaultRecipientAddress, - amount: [ - { - denom: "ucosm", - amount: "7654321", - }, - ], - }, - }; - - const fee: StdFee = { - amount: [ - { - amount: "5000", - denom: "ucosm", - }, - ], - gas: "890000", - }; - - const client = LcdClient.withExtensions({ apiUrl: launchpad.endpoint }, setupAuthExtension); - const { account_number: an1, sequence: sequence1 } = (await client.auth.account(address1)).result.value; - const { account_number: an2, sequence: sequence2 } = (await client.auth.account(address2)).result.value; - - const signDoc1 = makeSignDoc([msg1, msg2], fee, launchpad.chainId, memo, an1, sequence1); - const signDoc2 = makeSignDoc([msg1, msg2], fee, launchpad.chainId, memo, an2, sequence2); - const { signature: signature1 } = await account1.signAmino(address1, signDoc1); - const { signature: signature2 } = await account2.signAmino(address2, signDoc2); - const signedTx: StdTx = { - msg: [msg1, msg2], - fee: fee, - memo: memo, - signatures: [signature2, signature1], - }; - const broadcastResult = await client.broadcastTx(signedTx); - expect(broadcastResult.code).toEqual(8); - }); - - it("can't send transaction with wrong signature order (2)", async () => { - pendingWithoutLaunchpad(); - const account1 = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic, { - hdPaths: [makeCosmoshubPath(0)], - }); - const account2 = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic, { - hdPaths: [makeCosmoshubPath(1)], - }); - const [address1, address2] = await Promise.all( - [account1, account2].map(async (wallet) => { - return (await wallet.getAccounts())[0].address; - }), - ); - - const memo = "My first contract on chain"; - const msg1: MsgSend = { - type: "cosmos-sdk/MsgSend", - value: { - from_address: address1, - to_address: defaultRecipientAddress, - amount: [ - { - denom: "ucosm", - amount: "1234567", - }, - ], - }, - }; - const msg2: MsgSend = { - type: "cosmos-sdk/MsgSend", - value: { - from_address: address2, - to_address: defaultRecipientAddress, - amount: [ - { - denom: "ucosm", - amount: "7654321", - }, - ], - }, - }; - - const fee: StdFee = { - amount: [ - { - amount: "5000", - denom: "ucosm", - }, - ], - gas: "890000", - }; - - const client = LcdClient.withExtensions({ apiUrl: launchpad.endpoint }, setupAuthExtension); - const { account_number: an1, sequence: sequence1 } = (await client.auth.account(address1)).result.value; - const { account_number: an2, sequence: sequence2 } = (await client.auth.account(address2)).result.value; - - const signDoc1 = makeSignDoc([msg2, msg1], fee, launchpad.chainId, memo, an1, sequence1); - const signDoc2 = makeSignDoc([msg2, msg1], fee, launchpad.chainId, memo, an2, sequence2); - const { signature: signature1 } = await account1.signAmino(address1, signDoc1); - const { signature: signature2 } = await account2.signAmino(address2, signDoc2); - const signedTx: StdTx = { - msg: [msg2, msg1], - fee: fee, - memo: memo, - signatures: [signature1, signature2], - }; - const broadcastResult = await client.broadcastTx(signedTx); - expect(broadcastResult.code).toEqual(8); - }); - }); -}); diff --git a/packages/launchpad/src/lcdapi/lcdclient.ts b/packages/launchpad/src/lcdapi/lcdclient.ts deleted file mode 100644 index 6991336273..0000000000 --- a/packages/launchpad/src/lcdapi/lcdclient.ts +++ /dev/null @@ -1,314 +0,0 @@ -/* eslint-disable no-dupe-class-members, @typescript-eslint/ban-types, @typescript-eslint/naming-convention */ -import { StdTx } from "@cosmjs/amino"; -import { assert, isNonNullObject } from "@cosmjs/utils"; -import axios, { AxiosError, AxiosInstance } from "axios"; - -import { WrappedStdTx } from "../tx"; -import { - BlockResponse, - BroadcastMode, - BroadcastTxsResponse, - EncodeTxResponse, - NodeInfoResponse, - SearchTxsResponse, - TxsResponse, -} from "./base"; - -/** Unfortunately, Cosmos SDK encodes empty arrays as null */ -export type LcdApiArray = readonly T[] | null; - -export function normalizeLcdApiArray(backend: LcdApiArray): readonly T[] { - return backend || []; -} - -type LcdExtensionSetup

= (base: LcdClient) => P; - -export interface LcdClientBaseOptions { - readonly apiUrl: string; - readonly broadcastMode?: BroadcastMode; -} - -// We want to get message data from 500 errors -// https://stackoverflow.com/questions/56577124/how-to-handle-500-error-message-with-axios -// this should be chained to catch one error and throw a more informative one -function parseAxiosError(err: AxiosError): never { - // use the error message sent from server, not default 500 msg - if (err.response?.data) { - let errorText: string; - const data = err.response.data; - // expect { error: string }, but otherwise dump - if (data.error && typeof data.error === "string") { - errorText = data.error; - } else if (typeof data === "string") { - errorText = data; - } else { - errorText = JSON.stringify(data); - } - throw new Error(`${errorText} (HTTP ${err.response.status})`); - } else { - throw err; - } -} - -/** - * A client to the LCD's (light client daemon) API. - * This light client connects to Tendermint (i.e. the chain), encodes/decodes Amino data for us and provides a convenient JSON interface. - * - * This _JSON over HTTP_ API is sometimes referred to as "REST" or "RPC", which are both misleading terms - * for the same thing. - * - * Please note that the client to the LCD can not verify light client proofs. When using this, - * you need to trust the API provider as well as the network connection between client and API. - * - * @see https://cosmos.network/rpc - */ -export class LcdClient { - /** Constructs an LCD client with 0 extensions */ - public static withExtensions(options: LcdClientBaseOptions): LcdClient; - - /** Constructs an LCD client with 1 extension */ - public static withExtensions( - options: LcdClientBaseOptions, - setupExtensionA: LcdExtensionSetup, - ): LcdClient & A; - - /** Constructs an LCD client with 2 extensions */ - public static withExtensions( - options: LcdClientBaseOptions, - setupExtensionA: LcdExtensionSetup, - setupExtensionB: LcdExtensionSetup, - ): LcdClient & A & B; - - /** Constructs an LCD client with 3 extensions */ - public static withExtensions( - options: LcdClientBaseOptions, - setupExtensionA: LcdExtensionSetup, - setupExtensionB: LcdExtensionSetup, - setupExtensionC: LcdExtensionSetup, - ): LcdClient & A & B & C; - - /** Constructs an LCD client with 4 extensions */ - public static withExtensions( - options: LcdClientBaseOptions, - setupExtensionA: LcdExtensionSetup, - setupExtensionB: LcdExtensionSetup, - setupExtensionC: LcdExtensionSetup, - setupExtensionD: LcdExtensionSetup, - ): LcdClient & A & B & C & D; - - /** Constructs an LCD client with 5 extensions */ - public static withExtensions< - A extends object, - B extends object, - C extends object, - D extends object, - E extends object, - >( - options: LcdClientBaseOptions, - setupExtensionA: LcdExtensionSetup, - setupExtensionB: LcdExtensionSetup, - setupExtensionC: LcdExtensionSetup, - setupExtensionD: LcdExtensionSetup, - setupExtensionE: LcdExtensionSetup, - ): LcdClient & A & B & C & D & E; - - /** Constructs an LCD client with 6 extensions */ - public static withExtensions< - A extends object, - B extends object, - C extends object, - D extends object, - E extends object, - F extends object, - >( - options: LcdClientBaseOptions, - setupExtensionA: LcdExtensionSetup, - setupExtensionB: LcdExtensionSetup, - setupExtensionC: LcdExtensionSetup, - setupExtensionD: LcdExtensionSetup, - setupExtensionE: LcdExtensionSetup, - setupExtensionF: LcdExtensionSetup, - ): LcdClient & A & B & C & D & E & F; - - /** Constructs an LCD client with 7 extensions */ - public static withExtensions< - A extends object, - B extends object, - C extends object, - D extends object, - E extends object, - F extends object, - G extends object, - >( - options: LcdClientBaseOptions, - setupExtensionA: LcdExtensionSetup, - setupExtensionB: LcdExtensionSetup, - setupExtensionC: LcdExtensionSetup, - setupExtensionD: LcdExtensionSetup, - setupExtensionE: LcdExtensionSetup, - setupExtensionF: LcdExtensionSetup, - setupExtensionG: LcdExtensionSetup, - ): LcdClient & A & B & C & D & E & F & G; - - /** Constructs an LCD client with 8 extensions */ - public static withExtensions< - A extends object, - B extends object, - C extends object, - D extends object, - E extends object, - F extends object, - G extends object, - H extends object, - >( - options: LcdClientBaseOptions, - setupExtensionA: LcdExtensionSetup, - setupExtensionB: LcdExtensionSetup, - setupExtensionC: LcdExtensionSetup, - setupExtensionD: LcdExtensionSetup, - setupExtensionE: LcdExtensionSetup, - setupExtensionF: LcdExtensionSetup, - setupExtensionG: LcdExtensionSetup, - setupExtensionH: LcdExtensionSetup, - ): LcdClient & A & B & C & D & E & F & G & H; - - public static withExtensions( - options: LcdClientBaseOptions, - ...extensionSetups: Array> - ): any { - const client = new LcdClient(options.apiUrl, options.broadcastMode); - const extensions = extensionSetups.map((setupExtension) => setupExtension(client)); - for (const extension of extensions) { - assert(isNonNullObject(extension), `Extension must be a non-null object`); - for (const [moduleKey, moduleValue] of Object.entries(extension)) { - assert( - isNonNullObject(moduleValue), - `Module must be a non-null object. Found type ${typeof moduleValue} for module "${moduleKey}".`, - ); - const current = (client as any)[moduleKey] || {}; - (client as any)[moduleKey] = { - ...current, - ...moduleValue, - }; - } - } - return client; - } - - private readonly client: AxiosInstance; - private readonly broadcastMode: BroadcastMode; - - /** - * Creates a new client to interact with a Cosmos SDK light client daemon. - * This class tries to be a direct mapping onto the API. Some basic decoding and normalizatin is done - * but things like caching are done at a higher level. - * - * When building apps, you should not need to use this class directly. If you do, this indicates a missing feature - * in higher level components. Feel free to raise an issue in this case. - * - * @param apiUrl The URL of a Cosmos SDK light client daemon API (sometimes called REST server or REST API) - * @param broadcastMode Defines at which point of the transaction processing the broadcastTx method returns - */ - public constructor(apiUrl: string, broadcastMode = BroadcastMode.Block) { - const headers = { - post: { "Content-Type": "application/json" }, - }; - this.client = axios.create({ - baseURL: apiUrl, - headers: headers, - }); - this.broadcastMode = broadcastMode; - } - - public async get(path: string, params?: Record): Promise { - const { data } = await this.client.get(path, { params }).catch(parseAxiosError); - if (data === null) { - throw new Error("Received null response from server"); - } - return data; - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types - public async post(path: string, params: any): Promise { - if (!isNonNullObject(params)) throw new Error("Got unexpected type of params. Expected object."); - const { data } = await this.client.post(path, params).catch(parseAxiosError); - if (data === null) { - throw new Error("Received null response from server"); - } - return data; - } - - // The /blocks endpoints - - public async blocksLatest(): Promise { - const responseData = await this.get("/blocks/latest"); - if (!responseData.block) { - throw new Error("Unexpected response data format"); - } - return responseData as BlockResponse; - } - - public async blocks(height: number): Promise { - const responseData = await this.get(`/blocks/${height}`); - if (!responseData.block) { - throw new Error("Unexpected response data format"); - } - return responseData as BlockResponse; - } - - // The /node_info endpoint - - public async nodeInfo(): Promise { - const responseData = await this.get("/node_info"); - if (!responseData.node_info) { - throw new Error("Unexpected response data format"); - } - return responseData as NodeInfoResponse; - } - - // The /txs endpoints - - public async txById(id: string): Promise { - const responseData = await this.get(`/txs/${id}`); - if (!responseData.tx) { - throw new Error("Unexpected response data format"); - } - return responseData as TxsResponse; - } - - public async txsQuery(query: string): Promise { - const responseData = await this.get(`/txs?${query}`); - if (!responseData.txs) { - throw new Error("Unexpected response data format"); - } - return responseData as SearchTxsResponse; - } - - /** returns the amino-encoding of the transaction performed by the server */ - public async encodeTx(tx: WrappedStdTx): Promise { - const responseData = await this.post("/txs/encode", tx); - if (!responseData.tx) { - throw new Error("Unexpected response data format"); - } - return responseData as EncodeTxResponse; - } - - /** - * Broadcasts a signed transaction to the transaction pool. - * Depending on the client's broadcast mode, this might or might - * wait for checkTx or deliverTx to be executed before returning. - * - * @param tx a signed transaction as StdTx (i.e. not wrapped in type/value container) - */ - public async broadcastTx(tx: StdTx): Promise { - const params = { - tx: tx, - mode: this.broadcastMode, - }; - const responseData = await this.post("/txs", params); - if (!responseData.txhash) { - throw new Error("Unexpected response data format"); - } - return responseData as BroadcastTxsResponse; - } -} diff --git a/packages/launchpad/src/lcdapi/mint.spec.ts b/packages/launchpad/src/lcdapi/mint.spec.ts deleted file mode 100644 index ca1289e521..0000000000 --- a/packages/launchpad/src/lcdapi/mint.spec.ts +++ /dev/null @@ -1,59 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { - bigDecimalMatcher, - launchpad, - nonNegativeIntegerMatcher, - pendingWithoutLaunchpad, - smallDecimalMatcher, -} from "../testutils.spec"; -import { LcdClient } from "./lcdclient"; -import { MintExtension, setupMintExtension } from "./mint"; - -function makeMintClient(apiUrl: string): LcdClient & MintExtension { - return LcdClient.withExtensions({ apiUrl }, setupMintExtension); -} - -describe("MintExtension", () => { - describe("parameters", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeMintClient(launchpad.endpoint); - const response = await client.mint.parameters(); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: { - mint_denom: "ustake", - inflation_rate_change: "0.130000000000000000", - inflation_max: "0.200000000000000000", - inflation_min: "0.070000000000000000", - goal_bonded: "0.670000000000000000", - blocks_per_year: "6311520", - }, - }); - }); - }); - - describe("inflation", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeMintClient(launchpad.endpoint); - const response = await client.mint.inflation(); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: jasmine.stringMatching(smallDecimalMatcher), - }); - }); - }); - - describe("annualProvisions", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeMintClient(launchpad.endpoint); - const response = await client.mint.annualProvisions(); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: jasmine.stringMatching(bigDecimalMatcher), - }); - }); - }); -}); diff --git a/packages/launchpad/src/lcdapi/mint.ts b/packages/launchpad/src/lcdapi/mint.ts deleted file mode 100644 index 98fee42d99..0000000000 --- a/packages/launchpad/src/lcdapi/mint.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { LcdClient } from "./lcdclient"; - -export interface MintParametersResponse { - readonly height: string; - readonly result: { - readonly mint_denom: string; - readonly inflation_rate_change: string; - readonly inflation_max: string; - readonly inflation_min: string; - readonly goal_bonded: string; - readonly blocks_per_year: string; - }; -} - -export interface MintInflationResponse { - readonly height: string; - readonly result: string; -} - -export interface MintAnnualProvisionsResponse { - readonly height: string; - readonly result: string; -} - -export interface MintExtension { - readonly mint: { - readonly parameters: () => Promise; - readonly inflation: () => Promise; - readonly annualProvisions: () => Promise; - }; -} - -export function setupMintExtension(base: LcdClient): MintExtension { - return { - mint: { - parameters: async () => base.get(`/minting/parameters`), - inflation: async () => base.get(`/minting/inflation`), - annualProvisions: async () => base.get(`/minting/annual-provisions`), - }, - }; -} diff --git a/packages/launchpad/src/lcdapi/slashing.spec.ts b/packages/launchpad/src/lcdapi/slashing.spec.ts deleted file mode 100644 index dfe1177938..0000000000 --- a/packages/launchpad/src/lcdapi/slashing.spec.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { launchpad, nonNegativeIntegerMatcher, pendingWithoutLaunchpad } from "../testutils.spec"; -import { LcdClient } from "./lcdclient"; -import { setupSlashingExtension, SlashingExtension } from "./slashing"; - -function makeSlashingClient(apiUrl: string): LcdClient & SlashingExtension { - return LcdClient.withExtensions({ apiUrl }, setupSlashingExtension); -} - -describe("SlashingExtension", () => { - describe("signingInfos", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeSlashingClient(launchpad.endpoint); - const response = await client.slashing.signingInfos(); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: [ - { - address: "cosmosvalcons1m74e42saykuj34ugc7weqq4kc97fn5ecqpdl2q", - start_height: "0", - index_offset: jasmine.stringMatching(nonNegativeIntegerMatcher), - jailed_until: "1970-01-01T00:00:00Z", - tombstoned: false, - missed_blocks_counter: "0", - }, - ], - }); - }); - }); - - describe("parameters", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeSlashingClient(launchpad.endpoint); - const response = await client.slashing.parameters(); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: { - signed_blocks_window: "100", - min_signed_per_window: "0.500000000000000000", - downtime_jail_duration: "600000000000", - slash_fraction_double_sign: "0.050000000000000000", - slash_fraction_downtime: "0.010000000000000000", - }, - }); - }); - }); -}); diff --git a/packages/launchpad/src/lcdapi/slashing.ts b/packages/launchpad/src/lcdapi/slashing.ts deleted file mode 100644 index 5338cf525e..0000000000 --- a/packages/launchpad/src/lcdapi/slashing.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { LcdClient } from "./lcdclient"; - -interface SlashingSigningInfo { - readonly address: string; - readonly start_height: string; - readonly index_offset: string; - readonly jailed_until: string; - readonly tombstoned: boolean; - readonly missed_blocks_counter: string; -} - -export interface SlashingSigningInfosResponse { - readonly height: string; - readonly result: readonly SlashingSigningInfo[]; -} - -export interface SlashingParametersResponse { - readonly height: string; - readonly result: { - readonly signed_blocks_window: string; - readonly min_signed_per_window: string; - readonly downtime_jail_duration: string; - readonly slash_fraction_double_sign: string; - readonly slash_fraction_downtime: string; - }; -} - -export interface SlashingExtension { - readonly slashing: { - readonly signingInfos: () => Promise; - readonly parameters: () => Promise; - }; -} - -export function setupSlashingExtension(base: LcdClient): SlashingExtension { - return { - slashing: { - signingInfos: async () => { - return base.get(`/slashing/signing_infos`); - }, - parameters: async () => { - return base.get(`/slashing/parameters`); - }, - }, - }; -} diff --git a/packages/launchpad/src/lcdapi/staking.spec.ts b/packages/launchpad/src/lcdapi/staking.spec.ts deleted file mode 100644 index 6db3e4f585..0000000000 --- a/packages/launchpad/src/lcdapi/staking.spec.ts +++ /dev/null @@ -1,477 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { coin, coins, makeSignDoc, makeStdTx, Secp256k1HdWallet } from "@cosmjs/amino"; -import { assert, sleep } from "@cosmjs/utils"; - -import { assertIsBroadcastTxSuccess } from "../cosmosclient"; -import { MsgDelegate, MsgUndelegate } from "../msgs"; -import { SigningCosmosClient } from "../signingcosmosclient"; -import { - bigDecimalMatcher, - dateTimeStampMatcher, - faucet, - launchpad, - launchpadEnabled, - nonNegativeIntegerMatcher, - pendingWithoutLaunchpad, -} from "../testutils.spec"; -import { LcdClient } from "./lcdclient"; -import { BondStatus, setupStakingExtension, StakingExtension } from "./staking"; - -function makeStakingClient(apiUrl: string): LcdClient & StakingExtension { - return LcdClient.withExtensions({ apiUrl }, setupStakingExtension); -} - -describe("StakingExtension", () => { - const defaultFee = { - amount: coins(25000, "ucosm"), - gas: "1500000", // 1.5 million - }; - - beforeAll(async () => { - if (launchpadEnabled()) { - const wallet = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic); - const client = new SigningCosmosClient(launchpad.endpoint, faucet.address0, wallet); - - const chainId = await client.getChainId(); - { - const msg: MsgDelegate = { - type: "cosmos-sdk/MsgDelegate", - value: { - delegator_address: faucet.address0, - validator_address: launchpad.validator.address, - amount: coin(25000, "ustake"), - }, - }; - const memo = "Test delegation for wasmd"; - const { accountNumber, sequence } = await client.getSequence(); - const signDoc = makeSignDoc([msg], defaultFee, chainId, memo, accountNumber, sequence); - const { signed, signature } = await wallet.signAmino(faucet.address0, signDoc); - const signedTx = makeStdTx(signed, signature); - - const result = await client.broadcastTx(signedTx); - assertIsBroadcastTxSuccess(result); - } - { - const msg: MsgUndelegate = { - type: "cosmos-sdk/MsgUndelegate", - value: { - delegator_address: faucet.address0, - validator_address: launchpad.validator.address, - amount: coin(100, "ustake"), - }, - }; - const memo = "Test undelegation for wasmd"; - const { accountNumber, sequence } = await client.getSequence(); - const signDoc = makeSignDoc([msg], defaultFee, chainId, memo, accountNumber, sequence); - const { signed, signature } = await wallet.signAmino(faucet.address0, signDoc); - const signedTx = makeStdTx(signed, signature); - - const result = await client.broadcastTx(signedTx); - assertIsBroadcastTxSuccess(result); - } - - await sleep(75); // wait until transactions are indexed - } - }); - - describe("delegatorDelegations", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeStakingClient(launchpad.endpoint); - const response = await client.staking.delegatorDelegations(faucet.address0); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: [ - { - delegator_address: faucet.address0, - validator_address: launchpad.validator.address, - shares: jasmine.stringMatching(bigDecimalMatcher), - balance: { denom: "ustake", amount: jasmine.stringMatching(nonNegativeIntegerMatcher) }, - }, - ], - }); - }); - }); - - describe("delegatorUnbondingDelegations", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeStakingClient(launchpad.endpoint); - const { height, result } = await client.staking.delegatorUnbondingDelegations(faucet.address0); - expect(height).toMatch(nonNegativeIntegerMatcher); - assert(result); - expect(result).toEqual([ - { - delegator_address: faucet.address0, - validator_address: launchpad.validator.address, - entries: jasmine.arrayContaining([ - { - creation_height: jasmine.stringMatching(nonNegativeIntegerMatcher), - completion_time: jasmine.stringMatching(dateTimeStampMatcher), - initial_balance: "100", - balance: "100", - }, - ]), - }, - ]); - }); - }); - - describe("delegatorTransactions", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeStakingClient(launchpad.endpoint); - const response = await client.staking.delegatorTransactions(faucet.address0); - expect(response.length).toEqual(3); - }); - }); - - describe("delegatorValidators", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeStakingClient(launchpad.endpoint); - const response = await client.staking.delegatorValidators(faucet.address0); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: [ - { - operator_address: launchpad.validator.address, - consensus_pubkey: launchpad.validator.pubkey, - jailed: false, - status: BondStatus.Bonded, - tokens: jasmine.stringMatching(nonNegativeIntegerMatcher), - delegator_shares: jasmine.stringMatching(bigDecimalMatcher), - description: { - moniker: launchpad.moniker, - identity: "", - website: "", - security_contact: "", - details: "", - }, - unbonding_height: "0", - unbonding_time: "1970-01-01T00:00:00Z", - commission: { - commission_rates: { - rate: "0.100000000000000000", - max_rate: "0.200000000000000000", - max_change_rate: "0.010000000000000000", - }, - update_time: launchpad.commissionUpdateTime, - }, - min_self_delegation: "1", - }, - ], - }); - }); - }); - - describe("delegatorValidator", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeStakingClient(launchpad.endpoint); - const response = await client.staking.delegatorValidator(faucet.address0, launchpad.validator.address); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: { - operator_address: launchpad.validator.address, - consensus_pubkey: launchpad.validator.pubkey, - jailed: false, - status: BondStatus.Bonded, - tokens: jasmine.stringMatching(nonNegativeIntegerMatcher), - delegator_shares: jasmine.stringMatching(bigDecimalMatcher), - description: { - moniker: launchpad.moniker, - identity: "", - website: "", - security_contact: "", - details: "", - }, - unbonding_height: "0", - unbonding_time: "1970-01-01T00:00:00Z", - commission: { - commission_rates: { - rate: "0.100000000000000000", - max_rate: "0.200000000000000000", - max_change_rate: "0.010000000000000000", - }, - update_time: launchpad.commissionUpdateTime, - }, - min_self_delegation: "1", - }, - }); - }); - }); - - describe("delegation", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeStakingClient(launchpad.endpoint); - const response = await client.staking.delegation(faucet.address0, launchpad.validator.address); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: { - delegator_address: faucet.address0, - validator_address: launchpad.validator.address, - shares: jasmine.stringMatching(bigDecimalMatcher), - balance: { denom: "ustake", amount: jasmine.stringMatching(nonNegativeIntegerMatcher) }, - }, - }); - }); - }); - - describe("unbondingDelegation", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeStakingClient(launchpad.endpoint); - const { height, result } = await client.staking.unbondingDelegation( - faucet.address0, - launchpad.validator.address, - ); - expect(height).toMatch(nonNegativeIntegerMatcher); - assert(result); - expect(result).toEqual({ - delegator_address: faucet.address0, - validator_address: launchpad.validator.address, - entries: jasmine.arrayContaining([ - { - creation_height: jasmine.stringMatching(nonNegativeIntegerMatcher), - completion_time: jasmine.stringMatching(dateTimeStampMatcher), - initial_balance: "100", - balance: "100", - }, - ]), - }); - }); - }); - - describe("redelegations", () => { - it("works", async () => { - // TODO: Set up a result for this test - pendingWithoutLaunchpad(); - const client = makeStakingClient(launchpad.endpoint); - const response = await client.staking.redelegations(); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: [], - }); - }); - }); - - describe("validators", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeStakingClient(launchpad.endpoint); - const response = await client.staking.validators(); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: [ - { - operator_address: launchpad.validator.address, - consensus_pubkey: launchpad.validator.pubkey, - jailed: false, - status: BondStatus.Bonded, - tokens: jasmine.stringMatching(nonNegativeIntegerMatcher), - delegator_shares: jasmine.stringMatching(bigDecimalMatcher), - description: { - moniker: launchpad.moniker, - identity: "", - website: "", - security_contact: "", - details: "", - }, - unbonding_height: "0", - unbonding_time: "1970-01-01T00:00:00Z", - commission: { - commission_rates: { - rate: "0.100000000000000000", - max_rate: "0.200000000000000000", - max_change_rate: "0.010000000000000000", - }, - update_time: launchpad.commissionUpdateTime, - }, - min_self_delegation: "1", - }, - ], - }); - }); - - it("can filter by status with no results", async () => { - pendingWithoutLaunchpad(); - const client = makeStakingClient(launchpad.endpoint); - const response = await client.staking.validators({ status: "unbonded" }); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: [], - }); - }); - - it("can filter by status with some results", async () => { - pendingWithoutLaunchpad(); - const client = makeStakingClient(launchpad.endpoint); - const response = await client.staking.validators({ status: "bonded" }); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: [ - { - operator_address: launchpad.validator.address, - consensus_pubkey: launchpad.validator.pubkey, - jailed: false, - status: BondStatus.Bonded, - tokens: jasmine.stringMatching(nonNegativeIntegerMatcher), - delegator_shares: jasmine.stringMatching(bigDecimalMatcher), - description: { - moniker: launchpad.moniker, - identity: "", - website: "", - security_contact: "", - details: "", - }, - unbonding_height: "0", - unbonding_time: "1970-01-01T00:00:00Z", - commission: { - commission_rates: { - rate: "0.100000000000000000", - max_rate: "0.200000000000000000", - max_change_rate: "0.010000000000000000", - }, - update_time: launchpad.commissionUpdateTime, - }, - min_self_delegation: "1", - }, - ], - }); - }); - }); - - describe("validator", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeStakingClient(launchpad.endpoint); - const response = await client.staking.validator(launchpad.validator.address); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: { - operator_address: launchpad.validator.address, - consensus_pubkey: launchpad.validator.pubkey, - jailed: false, - status: BondStatus.Bonded, - tokens: jasmine.stringMatching(nonNegativeIntegerMatcher), - delegator_shares: jasmine.stringMatching(bigDecimalMatcher), - description: { - moniker: launchpad.moniker, - identity: "", - website: "", - security_contact: "", - details: "", - }, - unbonding_height: "0", - unbonding_time: "1970-01-01T00:00:00Z", - commission: { - commission_rates: { - rate: "0.100000000000000000", - max_rate: "0.200000000000000000", - max_change_rate: "0.010000000000000000", - }, - update_time: launchpad.commissionUpdateTime, - }, - min_self_delegation: "1", - }, - }); - }); - }); - - describe("validatorDelegations", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeStakingClient(launchpad.endpoint); - const response = await client.staking.validatorDelegations(launchpad.validator.address); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: jasmine.arrayContaining([ - { - delegator_address: faucet.address0, - validator_address: launchpad.validator.address, - shares: jasmine.stringMatching(bigDecimalMatcher), - balance: { denom: "ustake", amount: jasmine.stringMatching(nonNegativeIntegerMatcher) }, - }, - { - delegator_address: launchpad.validator.delegatorAddress, - validator_address: launchpad.validator.address, - shares: "250000000.000000000000000000", - balance: { denom: "ustake", amount: "250000000" }, - }, - ]), - }); - }); - }); - - describe("validatorUnbondingDelegations", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeStakingClient(launchpad.endpoint); - const { height, result } = await client.staking.validatorUnbondingDelegations( - launchpad.validator.address, - ); - expect(height).toMatch(nonNegativeIntegerMatcher); - assert(result); - expect(result).toEqual([ - { - delegator_address: faucet.address0, - validator_address: launchpad.validator.address, - entries: jasmine.arrayContaining([ - { - creation_height: jasmine.stringMatching(nonNegativeIntegerMatcher), - completion_time: jasmine.stringMatching(dateTimeStampMatcher), - initial_balance: "100", - balance: "100", - }, - ]), - }, - ]); - }); - }); - - describe("historicalInfo", () => { - it("doesn't work yet", async () => { - pendingWithoutLaunchpad(); - const client = makeStakingClient(launchpad.endpoint); - const currentHeight = (await client.blocksLatest()).block.header.height; - return expectAsync(client.staking.historicalInfo(currentHeight)).toBeRejectedWithError( - /no historical info found \(HTTP 400\)/i, - ); - }); - }); - - describe("pool", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeStakingClient(launchpad.endpoint); - const response = await client.staking.pool(); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: { - not_bonded_tokens: jasmine.stringMatching(nonNegativeIntegerMatcher), - bonded_tokens: jasmine.stringMatching(nonNegativeIntegerMatcher), - }, - }); - }); - }); - - describe("parameters", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const client = makeStakingClient(launchpad.endpoint); - const response = await client.staking.parameters(); - expect(response).toEqual({ - height: jasmine.stringMatching(nonNegativeIntegerMatcher), - result: { - unbonding_time: "1814400000000000", - max_validators: 100, - max_entries: 7, - historical_entries: 0, - bond_denom: "ustake", - }, - }); - }); - }); -}); diff --git a/packages/launchpad/src/lcdapi/staking.ts b/packages/launchpad/src/lcdapi/staking.ts deleted file mode 100644 index 219e803adb..0000000000 --- a/packages/launchpad/src/lcdapi/staking.ts +++ /dev/null @@ -1,251 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { Coin } from "@cosmjs/amino"; - -import { BlockHeader, SearchTxsResponse } from "./base"; -import { LcdClient } from "./lcdclient"; - -/** - * Numeric bonding status - * - * @see https://github.com/cosmos/cosmos-sdk/blob/v0.38.5/types/staking.go#L43-L49 - */ -export enum BondStatus { - Unbonded = 0, - Unbonding = 1, - Bonded = 2, -} - -interface Validator { - readonly operator_address: string; - readonly consensus_pubkey: string; - readonly jailed: boolean; - readonly status: BondStatus; - readonly tokens: string; - readonly delegator_shares: string; - readonly description: { - readonly moniker: string; - readonly identity: string; - readonly website: string; - readonly security_contact: string; - readonly details: string; - }; - readonly unbonding_height: string; - readonly unbonding_time: string; - readonly commission: { - readonly commission_rates: { - readonly rate: string; - readonly max_rate: string; - readonly max_change_rate: string; - }; - readonly update_time: string; - }; - readonly min_self_delegation: string; -} - -interface Delegation { - readonly delegator_address: string; - readonly validator_address: string; - readonly shares: string; - readonly balance: Coin; -} - -export interface StakingDelegatorDelegationsResponse { - readonly height: string; - readonly result: readonly Delegation[]; -} - -interface UnbondingDelegationEntry { - readonly creation_height: string; - readonly completion_time: string; - readonly initial_balance: string; - readonly balance: string; -} - -interface UnbondingDelegation { - readonly delegator_address: string; - readonly validator_address: string; - readonly entries: readonly UnbondingDelegationEntry[]; -} - -export interface StakingDelegatorUnbondingDelegationsResponse { - readonly height: string; - readonly result: readonly UnbondingDelegation[]; -} - -export type StakingDelegatorTransactionsResponse = readonly SearchTxsResponse[]; - -export interface StakingDelegatorValidatorsResponse { - readonly height: string; - readonly result: readonly Validator[]; -} - -export interface StakingDelegatorValidatorResponse { - readonly height: string; - readonly result: Validator; -} - -export interface StakingDelegationResponse { - readonly height: string; - readonly result: Delegation; -} - -export interface StakingUnbondingDelegationResponse { - readonly height: string; - readonly result: UnbondingDelegation | null; -} - -interface RedelegationEntry { - readonly creation_height: string; - readonly completion_time: string; - readonly initial_balance: Coin; - readonly shares_dst: string; -} - -interface Redelegation { - readonly delegator_address: string; - readonly validator_src_address: string; - readonly validator_dst_address: string; - readonly entries: readonly RedelegationEntry[]; -} - -export interface StakingRedelegationsResponse { - readonly height: string; - readonly result: readonly Redelegation[]; -} - -export interface StakingValidatorsParams { - /** @see https://github.com/cosmos/cosmos-sdk/blob/v0.38.5/types/staking.go#L43-L49 */ - readonly status?: "bonded" | "unbonded" | "unbonding"; - readonly page?: number; - readonly limit?: number; -} - -export interface StakingValidatorsResponse { - readonly height: string; - readonly result: readonly Validator[]; -} - -export interface StakingValidatorResponse { - readonly height: string; - readonly result: Validator; -} - -export interface StakingValidatorDelegationsResponse { - readonly height: string; - readonly result: readonly Delegation[]; -} - -export interface StakingValidatorUnbondingDelegationsResponse { - readonly height: string; - readonly result: readonly UnbondingDelegation[]; -} - -interface HistoricalInfo { - readonly header: BlockHeader; - readonly validators: readonly Validator[]; -} - -export interface StakingHistoricalInfoResponse { - readonly height: string; - readonly result: HistoricalInfo; -} - -export interface StakingPoolResponse { - readonly height: string; - readonly result: { - readonly not_bonded_tokens: string; - readonly bonded_tokens: string; - }; -} - -export interface StakingParametersResponse { - readonly height: string; - readonly result: { - readonly unbonding_time: string; - readonly max_validators: number; - readonly max_entries: number; - readonly historical_entries: number; - readonly bond_denom: string; - }; -} - -export interface StakingExtension { - readonly staking: { - /** Get all delegations from a delegator */ - readonly delegatorDelegations: (delegatorAddress: string) => Promise; - /** Get all unbonding delegations from a delegator */ - readonly delegatorUnbondingDelegations: ( - delegatorAddress: string, - ) => Promise; - /** Get all staking txs (i.e msgs) from a delegator */ - readonly delegatorTransactions: ( - delegatorAddress: string, - ) => Promise; - /** Query all validators that a delegator is bonded to */ - readonly delegatorValidators: (delegatorAddress: string) => Promise; - /** Query a validator that a delegator is bonded to */ - readonly delegatorValidator: ( - delegatorAddress: string, - validatorAddress: string, - ) => Promise; - /** Query a delegation between a delegator and a validator */ - readonly delegation: ( - delegatorAddress: string, - validatorAddress: string, - ) => Promise; - /** Query all unbonding delegations between a delegator and a validator */ - readonly unbondingDelegation: ( - delegatorAddress: string, - validatorAddress: string, - ) => Promise; - /** Query redelegations (filters in query params) */ - readonly redelegations: () => Promise; - /** Get all validators */ - readonly validators: (options?: StakingValidatorsParams) => Promise; - /** Get a single validator info */ - readonly validator: (validatorAddress: string) => Promise; - // Get all delegations to a validator - readonly validatorDelegations: (validatorAddress: string) => Promise; - /** Get all unbonding delegations from a validator */ - readonly validatorUnbondingDelegations: ( - validatorAddress: string, - ) => Promise; - /** Get HistoricalInfo at a given height */ - readonly historicalInfo: (height: string) => Promise; - /** Get the current state of the staking pool */ - readonly pool: () => Promise; - /** Get the current staking parameter values */ - readonly parameters: () => Promise; - }; -} - -export function setupStakingExtension(base: LcdClient): StakingExtension { - return { - staking: { - delegatorDelegations: async (delegatorAddress: string) => - base.get(`/staking/delegators/${delegatorAddress}/delegations`), - delegatorUnbondingDelegations: async (delegatorAddress: string) => - base.get(`/staking/delegators/${delegatorAddress}/unbonding_delegations`), - delegatorTransactions: async (delegatorAddress: string) => - base.get(`/staking/delegators/${delegatorAddress}/txs`), - delegatorValidators: async (delegatorAddress: string) => - base.get(`/staking/delegators/${delegatorAddress}/validators`), - delegatorValidator: async (delegatorAddress: string, validatorAddress: string) => - base.get(`/staking/delegators/${delegatorAddress}/validators/${validatorAddress}`), - delegation: async (delegatorAddress: string, validatorAddress: string) => - base.get(`/staking/delegators/${delegatorAddress}/delegations/${validatorAddress}`), - unbondingDelegation: async (delegatorAddress: string, validatorAddress: string) => - base.get(`/staking/delegators/${delegatorAddress}/unbonding_delegations/${validatorAddress}`), - redelegations: async () => base.get(`/staking/redelegations`), - validators: async (params?: StakingValidatorsParams) => base.get(`/staking/validators`, params), - validator: async (validatorAddress: string) => base.get(`/staking/validators/${validatorAddress}`), - validatorDelegations: async (validatorAddress: string) => - base.get(`/staking/validators/${validatorAddress}/delegations`), - validatorUnbondingDelegations: async (validatorAddress: string) => - base.get(`/staking/validators/${validatorAddress}/unbonding_delegations`), - historicalInfo: async (height: string) => base.get(`/staking/historical_info/${height}`), - pool: async () => base.get(`/staking/pool`), - parameters: async () => base.get(`/staking/parameters`), - }, - }; -} diff --git a/packages/launchpad/src/lcdapi/supply.spec.ts b/packages/launchpad/src/lcdapi/supply.spec.ts deleted file mode 100644 index 263e0e0ef0..0000000000 --- a/packages/launchpad/src/lcdapi/supply.spec.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { launchpad, pendingWithoutLaunchpad } from "../testutils.spec"; -import { LcdClient } from "./lcdclient"; -import { setupSupplyExtension } from "./supply"; - -describe("SupplyExtension", () => { - describe("totalAll", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - - const client = LcdClient.withExtensions({ apiUrl: launchpad.endpoint }, setupSupplyExtension); - const supply = await client.supply.totalAll(); - expect(supply).toEqual({ - height: jasmine.stringMatching(/^[0-9]+$/), - result: [ - { - amount: jasmine.stringMatching(/^[0-9]+$/), - denom: "ucosm", - }, - { - amount: jasmine.stringMatching(/^[0-9]+$/), - denom: "ustake", - }, - ], - }); - }); - }); - - describe("total", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - - const client = LcdClient.withExtensions({ apiUrl: launchpad.endpoint }, setupSupplyExtension); - const supply = await client.supply.total("ucosm"); - expect(supply).toEqual({ - height: jasmine.stringMatching(/^[0-9]+$/), - result: jasmine.stringMatching(/^[0-9]+$/), - }); - }); - }); -}); diff --git a/packages/launchpad/src/lcdapi/supply.ts b/packages/launchpad/src/lcdapi/supply.ts deleted file mode 100644 index 302a1c0004..0000000000 --- a/packages/launchpad/src/lcdapi/supply.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Coin } from "@cosmjs/amino"; - -import { LcdApiArray, LcdClient } from "./lcdclient"; - -export interface TotalSupplyAllResponse { - readonly height: string; - readonly result: LcdApiArray; -} - -export interface TotalSupplyResponse { - readonly height: string; - /** The amount */ - readonly result: string; -} - -export interface SupplyExtension { - readonly supply: { - readonly totalAll: () => Promise; - readonly total: (denom: string) => Promise; - }; -} - -export function setupSupplyExtension(base: LcdClient): SupplyExtension { - return { - supply: { - totalAll: async () => { - return base.get(`/supply/total`); - }, - total: async (denom: string) => { - return base.get(`/supply/total/${denom}`); - }, - }, - }; -} diff --git a/packages/launchpad/src/lcdapi/utils.spec.ts b/packages/launchpad/src/lcdapi/utils.spec.ts deleted file mode 100644 index 646eee1c71..0000000000 --- a/packages/launchpad/src/lcdapi/utils.spec.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { Pubkey } from "@cosmjs/amino"; - -import { normalizePubkey, uint64ToNumber, uint64ToString } from "./utils"; - -describe("utils", () => { - describe("uint64ToNumber", () => { - it("works for numeric inputs", () => { - expect(uint64ToNumber(0)).toEqual(0); - expect(uint64ToNumber(1)).toEqual(1); - expect(uint64ToNumber(Number.MAX_SAFE_INTEGER)).toEqual(Number.MAX_SAFE_INTEGER); - }); - - it("works for string inputs", () => { - expect(uint64ToNumber("0")).toEqual(0); - expect(uint64ToNumber("1")).toEqual(1); - expect(uint64ToNumber("9007199254740991")).toEqual(Number.MAX_SAFE_INTEGER); - }); - - it("throws for invalid numbers", () => { - expect(() => uint64ToNumber(NaN)).toThrow(); - expect(() => uint64ToNumber(1.1)).toThrow(); - expect(() => uint64ToNumber(-1)).toThrow(); - expect(() => uint64ToNumber(Number.MAX_SAFE_INTEGER + 1)).toThrow(); - }); - - it("throws for invalid strings", () => { - expect(() => uint64ToNumber("")).toThrow(); - expect(() => uint64ToNumber("0x22")).toThrow(); - expect(() => uint64ToNumber("-1")).toThrow(); - expect(() => uint64ToNumber("1.1")).toThrow(); - expect(() => uint64ToNumber("9007199254740992")).toThrow(); - }); - }); - - describe("uint64ToString", () => { - it("works for numeric inputs", () => { - expect(uint64ToString(0)).toEqual("0"); - expect(uint64ToString(1)).toEqual("1"); - expect(uint64ToString(Number.MAX_SAFE_INTEGER)).toEqual("9007199254740991"); - }); - - it("works for string inputs", () => { - expect(uint64ToString("0")).toEqual("0"); - expect(uint64ToString("1")).toEqual("1"); - expect(uint64ToString("9007199254740991")).toEqual("9007199254740991"); - }); - - it("works for large string values", () => { - // for the string -> string version, the full uint64 range is supported - expect(uint64ToString("9007199254740992")).toEqual("9007199254740992"); - expect(uint64ToString("18446744073709551615")).toEqual("18446744073709551615"); - }); - - it("throws for invalid numbers", () => { - expect(() => uint64ToString(NaN)).toThrow(); - expect(() => uint64ToString(1.1)).toThrow(); - expect(() => uint64ToString(-1)).toThrow(); - expect(() => uint64ToString(Number.MAX_SAFE_INTEGER + 1)).toThrow(); - }); - - it("throws for invalid strings", () => { - expect(() => uint64ToString("")).toThrow(); - expect(() => uint64ToString("0x22")).toThrow(); - expect(() => uint64ToString("-1")).toThrow(); - expect(() => uint64ToString("1.1")).toThrow(); - expect(() => uint64ToString("18446744073709551616")).toThrow(); - }); - }); - - describe("normalizePubkey", () => { - it("interprets empty bech32 string as unset", () => { - expect(normalizePubkey("")).toBeNull(); - }); - - it("decodes bech32 pubkey", () => { - const input = "cosmospub1addwnpepqd8sgxq7aw348ydctp3n5ajufgxp395hksxjzc6565yfp56scupfqhlgyg5"; - expect(normalizePubkey(input)).toEqual({ - type: "tendermint/PubKeySecp256k1", - value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ", - }); - }); - - it("interprets null as unset", () => { - expect(normalizePubkey(null)).toBeNull(); - }); - - it("passes PubKey unchanged", () => { - const original: Pubkey = { - type: "tendermint/PubKeySecp256k1", - value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ", - }; - expect(normalizePubkey(original)).toEqual(original); - }); - }); -}); diff --git a/packages/launchpad/src/lcdapi/utils.ts b/packages/launchpad/src/lcdapi/utils.ts deleted file mode 100644 index 558033dc3d..0000000000 --- a/packages/launchpad/src/lcdapi/utils.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { decodeBech32Pubkey, Pubkey } from "@cosmjs/amino"; -import { Uint64 } from "@cosmjs/math"; - -/** - * Converts an integer expressed as number or string to a number. - * Throws if input is not a valid uint64 or if the value exceeds MAX_SAFE_INTEGER. - * - * This is needed for supporting Comsos SDK 0.37/0.38/0.39 with one client. - */ -export function uint64ToNumber(input: number | string): number { - const value = typeof input === "number" ? Uint64.fromNumber(input) : Uint64.fromString(input); - return value.toNumber(); -} - -/** - * Converts an integer expressed as number or string to a string. - * Throws if input is not a valid uint64. - * - * This is needed for supporting Comsos SDK 0.37/0.38/0.39 with one client. - */ -export function uint64ToString(input: number | string): string { - const value = typeof input === "number" ? Uint64.fromNumber(input) : Uint64.fromString(input); - return value.toString(); -} - -/** - * Normalizes a pubkey as in `BaseAccount.public_key` to allow supporting - * Comsos SDK 0.37–0.39. - * - * Returns null when unset. - */ -export function normalizePubkey(input: string | Pubkey | null): Pubkey | null { - if (!input) return null; - if (typeof input === "string") return decodeBech32Pubkey(input); - return input; -} diff --git a/packages/launchpad/src/logs.spec.ts b/packages/launchpad/src/logs.spec.ts deleted file mode 100644 index 37be68e8e4..0000000000 --- a/packages/launchpad/src/logs.spec.ts +++ /dev/null @@ -1,165 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { parseAttribute, parseEvent, parseLog, parseLogs } from "./logs"; - -describe("logs", () => { - describe("parseAttribute", () => { - it("works", () => { - const attr = parseAttribute({ key: "a", value: "b" }); - expect(attr).toEqual({ key: "a", value: "b" }); - }); - - it("works for empty value", () => { - const attr = parseAttribute({ key: "foobar", value: "" }); - expect(attr).toEqual({ key: "foobar", value: "" }); - }); - - it("normalized unset value to empty string", () => { - const attr = parseAttribute({ key: "amount" }); - expect(attr).toEqual({ key: "amount", value: "" }); - }); - }); - - describe("parseEvent", () => { - it("works", () => { - const original = { - type: "message", - attributes: [ - { - key: "action", - value: "store-code", - }, - { - key: "module", - value: "wasm", - }, - { - key: "action", - value: "store-code", - }, - { - key: "sender", - value: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", - }, - { - key: "code_id", - value: "1", - }, - ], - } as const; - - const event = parseEvent(original); - expect(event).toEqual(original); - }); - - it("works for transfer event", () => { - const original = { - type: "transfer", - attributes: [ - { - key: "recipient", - value: "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5", - }, - { - key: "amount", - }, - ], - } as const; - const expected = { - type: "transfer", - attributes: [ - { - key: "recipient", - value: "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5", - }, - { - key: "amount", - value: "", - }, - ], - } as const; - - const event = parseEvent(original); - expect(event).toEqual(expected); - }); - }); - - describe("parseLog", () => { - it("works", () => { - const original = { - msg_index: 0, - log: "", - events: [ - { - type: "message", - attributes: [ - { - key: "action", - value: "store-code", - }, - { - key: "module", - value: "wasm", - }, - { - key: "action", - value: "store-code", - }, - { - key: "sender", - value: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", - }, - { - key: "code_id", - value: "1", - }, - ], - }, - ], - } as const; - - const log = parseLog(original); - expect(log).toEqual(original); - }); - }); - - describe("parseLogs", () => { - it("works", () => { - const original = [ - { - msg_index: 0, - log: "", - events: [ - { - type: "message", - attributes: [ - { - key: "action", - value: "store-code", - }, - { - key: "module", - value: "wasm", - }, - { - key: "action", - value: "store-code", - }, - { - key: "sender", - value: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", - }, - { - key: "code_id", - value: "1", - }, - ], - }, - ], - }, - ] as const; - - const logs = parseLogs(original); - expect(logs).toEqual(original); - }); - }); -}); diff --git a/packages/launchpad/src/logs.ts b/packages/launchpad/src/logs.ts deleted file mode 100644 index 6dc2df308e..0000000000 --- a/packages/launchpad/src/logs.ts +++ /dev/null @@ -1,82 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { isNonNullObject } from "@cosmjs/utils"; - -export interface Attribute { - readonly key: string; - readonly value: string; -} - -export interface Event { - readonly type: string; - readonly attributes: readonly Attribute[]; -} - -export interface Log { - readonly msg_index: number; - readonly log: string; - readonly events: readonly Event[]; -} - -export function parseAttribute(input: unknown): Attribute { - if (!isNonNullObject(input)) throw new Error("Attribute must be a non-null object"); - const { key, value } = input as any; - if (typeof key !== "string" || !key) throw new Error("Attribute's key must be a non-empty string"); - if (typeof value !== "string" && typeof value !== "undefined") { - throw new Error("Attribute's value must be a string or unset"); - } - - return { - key: key, - value: value || "", - }; -} - -export function parseEvent(input: unknown): Event { - if (!isNonNullObject(input)) throw new Error("Event must be a non-null object"); - const { type, attributes } = input as any; - if (typeof type !== "string" || type === "") { - throw new Error(`Event type must be a non-empty string`); - } - if (!Array.isArray(attributes)) throw new Error("Event's attributes must be an array"); - return { - type: type, - attributes: attributes.map(parseAttribute), - }; -} - -export function parseLog(input: unknown): Log { - if (!isNonNullObject(input)) throw new Error("Log must be a non-null object"); - const { msg_index, log, events } = input as any; - if (typeof msg_index !== "number") throw new Error("Log's msg_index must be a number"); - if (typeof log !== "string") throw new Error("Log's log must be a string"); - if (!Array.isArray(events)) throw new Error("Log's events must be an array"); - return { - msg_index: msg_index, - log: log, - events: events.map(parseEvent), - }; -} - -export function parseLogs(input: unknown): readonly Log[] { - if (!Array.isArray(input)) throw new Error("Logs must be an array"); - return input.map(parseLog); -} - -/** - * Searches in logs for the first event of the given event type and in that event - * for the first first attribute with the given attribute key. - * - * Throws if the attribute was not found. - */ -export function findAttribute(logs: readonly Log[], eventType: string, attrKey: string): Attribute { - const firstLogs = logs.find(() => true); - const out = firstLogs?.events - .find((event) => event.type === eventType) - ?.attributes.find((attr) => attr.key === attrKey); - if (!out) { - throw new Error( - `Could not find attribute '${attrKey}' in first event of type '${eventType}' in first log.`, - ); - } - return out; -} diff --git a/packages/launchpad/src/msgs.ts b/packages/launchpad/src/msgs.ts deleted file mode 100644 index f1a4a1f3c4..0000000000 --- a/packages/launchpad/src/msgs.ts +++ /dev/null @@ -1,335 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { AminoMsg, Coin } from "@cosmjs/amino"; - -// auth (no messages) - see https://github.com/cosmos/cosmos-sdk/blob/efa73c7/proto/cosmos/auth/auth.proto - -// bank - see https://github.com/cosmos/cosmos-sdk/blob/efa73c7/proto/cosmos/bank/bank.proto - -/** A high level transaction of the coin module */ -export interface MsgSend extends AminoMsg { - readonly type: "cosmos-sdk/MsgSend"; - readonly value: { - /** Bech32 account address */ - readonly from_address: string; - /** Bech32 account address */ - readonly to_address: string; - readonly amount: readonly Coin[]; - }; -} - -export function isMsgSend(msg: AminoMsg): msg is MsgSend { - return (msg as MsgSend).type === "cosmos-sdk/MsgSend"; -} - -interface Input { - /** Bech32 account address */ - readonly address: string; - readonly coins: readonly Coin[]; -} - -interface Output { - /** Bech32 account address */ - readonly address: string; - readonly coins: readonly Coin[]; -} - -/** A high level transaction of the coin module */ -export interface MsgMultiSend extends AminoMsg { - readonly type: "cosmos-sdk/MsgMultiSend"; - readonly value: { - readonly inputs: readonly Input[]; - readonly outputs: readonly Output[]; - }; -} - -export function isMsgMultiSend(msg: AminoMsg): msg is MsgMultiSend { - return (msg as MsgMultiSend).type === "cosmos-sdk/MsgMultiSend"; -} - -// crisis - see https://github.com/cosmos/cosmos-sdk/blob/efa73c7/proto/cosmos/crisis/crisis.proto - -/** Verifies a particular invariance */ -export interface MsgVerifyInvariant extends AminoMsg { - readonly type: "cosmos-sdk/MsgVerifyInvariant"; - readonly value: { - /** Bech32 account address */ - readonly sender: string; - readonly invariant_module_name: string; - readonly invariant_route: string; - }; -} - -export function isMsgVerifyInvariant(msg: AminoMsg): msg is MsgVerifyInvariant { - return (msg as MsgVerifyInvariant).type === "cosmos-sdk/MsgVerifyInvariant"; -} - -// distribution - see https://github.com/cosmos/cosmos-sdk/blob/efa73c7/proto/cosmos/distribution/distribution.proto - -/** Changes the withdraw address for a delegator (or validator self-delegation) */ -export interface MsgSetWithdrawAddress extends AminoMsg { - // NOTE: Type string and names diverge here! - readonly type: "cosmos-sdk/MsgModifyWithdrawAddress"; - readonly value: { - /** Bech32 account address */ - readonly delegator_address: string; - /** Bech32 account address */ - readonly withdraw_address: string; - }; -} - -export function isMsgSetWithdrawAddress(msg: AminoMsg): msg is MsgSetWithdrawAddress { - // NOTE: Type string and names diverge here! - return (msg as MsgSetWithdrawAddress).type === "cosmos-sdk/MsgModifyWithdrawAddress"; -} - -/** Message for delegation withdraw from a single validator */ -export interface MsgWithdrawDelegatorReward extends AminoMsg { - // NOTE: Type string and names diverge here! - readonly type: "cosmos-sdk/MsgWithdrawDelegationReward"; - readonly value: { - /** Bech32 account address */ - readonly delegator_address: string; - /** Bech32 account address */ - readonly validator_address: string; - }; -} - -export function isMsgWithdrawDelegatorReward(msg: AminoMsg): msg is MsgWithdrawDelegatorReward { - // NOTE: Type string and names diverge here! - return (msg as MsgWithdrawDelegatorReward).type === "cosmos-sdk/MsgWithdrawDelegationReward"; -} - -/** Message for validator withdraw */ -export interface MsgWithdrawValidatorCommission extends AminoMsg { - readonly type: "cosmos-sdk/MsgWithdrawValidatorCommission"; - readonly value: { - /** Bech32 account address */ - readonly validator_address: string; - }; -} - -export function isMsgWithdrawValidatorCommission(msg: AminoMsg): msg is MsgWithdrawValidatorCommission { - return (msg as MsgWithdrawValidatorCommission).type === "cosmos-sdk/MsgWithdrawValidatorCommission"; -} - -/** Allows an account to directly fund the community pool. */ -export interface MsgFundCommunityPool extends AminoMsg { - readonly type: "cosmos-sdk/MsgFundCommunityPool"; - readonly value: { - readonly amount: readonly Coin[]; - /** Bech32 account address */ - readonly depositor: string; - }; -} - -export function isMsgFundCommunityPool(msg: AminoMsg): msg is MsgFundCommunityPool { - return (msg as MsgFundCommunityPool).type === "cosmos-sdk/MsgFundCommunityPool"; -} - -// evidence - see https://github.com/cosmos/cosmos-sdk/blob/efa73c7/proto/cosmos/evidence/evidence.proto - -interface Any { - readonly type_url: string; - readonly value: Uint8Array; -} - -/** Supports submitting arbitrary evidence */ -export interface MsgSubmitEvidence extends AminoMsg { - readonly type: "cosmos-sdk/MsgSubmitEvidence"; - readonly value: { - /** Bech32 account address */ - readonly submitter: string; - readonly evidence: Any; - }; -} - -export function isMsgSubmitEvidence(msg: AminoMsg): msg is MsgSubmitEvidence { - return (msg as MsgSubmitEvidence).type === "cosmos-sdk/MsgSubmitEvidence"; -} - -// gov - https://github.com/cosmos/cosmos-sdk/blob/efa73c7edb31a7bd65786501da213b294f89267a/proto/cosmos/gov/gov.proto - -/** Supports submitting arbitrary proposal content. */ -export interface MsgSubmitProposal extends AminoMsg { - readonly type: "cosmos-sdk/MsgSubmitProposal"; - readonly value: { - readonly content: Any; - readonly initial_deposit: readonly Coin[]; - /** Bech32 account address */ - readonly proposer: string; - }; -} - -export function isMsgSubmitProposal(msg: AminoMsg): msg is MsgSubmitProposal { - return (msg as MsgSubmitProposal).type === "cosmos-sdk/MsgSubmitProposal"; -} - -enum VoteOption { - VoteOptionUnspecified, - VoteOptionYes, - VoteOptionAbstain, - VoteOptionNo, - VoteOptionNoWithVeto, -} - -/** Casts a vote */ -export interface MsgVote extends AminoMsg { - readonly type: "cosmos-sdk/MsgVote"; - readonly value: { - readonly proposal_id: number; - /** Bech32 account address */ - readonly voter: string; - readonly option: VoteOption; - }; -} - -export function isMsgVote(msg: AminoMsg): msg is MsgVote { - return (msg as MsgVote).type === "cosmos-sdk/MsgVote"; -} - -/** Submits a deposit to an existing proposal */ -export interface MsgDeposit extends AminoMsg { - readonly type: "cosmos-sdk/MsgDeposit"; - readonly value: { - readonly proposal_id: number; - /** Bech32 account address */ - readonly depositor: string; - readonly amount: readonly Coin[]; - }; -} - -export function isMsgDeposit(msg: AminoMsg): msg is MsgDeposit { - return (msg as MsgDeposit).type === "cosmos-sdk/MsgDeposit"; -} - -// ibc - -// mint (no messages) - see https://github.com/cosmos/cosmos-sdk/blob/efa73c7/proto/cosmos/mint/mint.proto - -// params (no messages) - see https://github.com/cosmos/cosmos-sdk/blob/efa73c7/proto/cosmos/params/params.proto - -// slashing - see https://github.com/cosmos/cosmos-sdk/blob/efa73c7/proto/cosmos/slashing/slashing.proto - -/** Unjails a jailed validator */ -export interface MsgUnjail extends AminoMsg { - readonly type: "cosmos-sdk/MsgUnjail"; - readonly value: { - /** Bech32 account address */ - readonly validator_addr: string; - }; -} - -export function isMsgUnjail(msg: AminoMsg): msg is MsgUnjail { - return (msg as MsgUnjail).type === "cosmos-sdk/MsgUnjail"; -} - -// staking - see https://github.com/cosmos/cosmos-sdk/blob/efa73c7/proto/cosmos/staking/staking.proto - -/** The initial commission rates to be used for creating a validator */ -interface CommissionRates { - readonly rate: string; - readonly max_rate: string; - readonly max_change_rate: string; -} - -/** A validator description. */ -interface Description { - readonly moniker: string; - readonly identity: string; - readonly website: string; - readonly security_contact: string; - readonly details: string; -} - -/** Creates a new validator. */ -export interface MsgCreateValidator extends AminoMsg { - readonly type: "cosmos-sdk/MsgCreateValidator"; - readonly value: { - readonly description: Description; - readonly commission: CommissionRates; - readonly min_self_delegation: string; - /** Bech32 encoded delegator address */ - readonly delegator_address: string; - /** Bech32 encoded validator address */ - readonly validator_address: string; - /** Bech32 encoded public key */ - readonly pubkey: string; - readonly value: Coin; - }; -} - -export function isMsgCreateValidator(msg: AminoMsg): msg is MsgCreateValidator { - return (msg as MsgCreateValidator).type === "cosmos-sdk/MsgCreateValidator"; -} - -/** Edits an existing validator. */ -export interface MsgEditValidator extends AminoMsg { - readonly type: "cosmos-sdk/MsgEditValidator"; - readonly value: { - readonly description: Description; - /** Bech32 encoded validator address */ - readonly validator_address: string; - readonly commission_rate: string; - readonly min_self_delegation: string; - }; -} - -export function isMsgEditValidator(msg: AminoMsg): msg is MsgEditValidator { - return (msg as MsgEditValidator).type === "cosmos-sdk/MsgEditValidator"; -} - -/** - * Performs a delegation from a delegate to a validator. - * - * @see https://docs.cosmos.network/master/modules/staking/03_messages.html#msgdelegate - */ -export interface MsgDelegate extends AminoMsg { - readonly type: "cosmos-sdk/MsgDelegate"; - readonly value: { - /** Bech32 encoded delegator address */ - readonly delegator_address: string; - /** Bech32 encoded validator address */ - readonly validator_address: string; - readonly amount: Coin; - }; -} - -export function isMsgDelegate(msg: AminoMsg): msg is MsgDelegate { - return (msg as MsgDelegate).type === "cosmos-sdk/MsgDelegate"; -} - -/** Performs a redelegation from a delegate and source validator to a destination validator */ -export interface MsgBeginRedelegate extends AminoMsg { - readonly type: "cosmos-sdk/MsgBeginRedelegate"; - readonly value: { - /** Bech32 encoded delegator address */ - readonly delegator_address: string; - /** Bech32 encoded source validator address */ - readonly validator_src_address: string; - /** Bech32 encoded destination validator address */ - readonly validator_dst_address: string; - readonly amount: Coin; - }; -} - -export function isMsgBeginRedelegate(msg: AminoMsg): msg is MsgBeginRedelegate { - return (msg as MsgBeginRedelegate).type === "cosmos-sdk/MsgBeginRedelegate"; -} - -/** Performs an undelegation from a delegate and a validator */ -export interface MsgUndelegate extends AminoMsg { - readonly type: "cosmos-sdk/MsgUndelegate"; - readonly value: { - /** Bech32 encoded delegator address */ - readonly delegator_address: string; - /** Bech32 encoded validator address */ - readonly validator_address: string; - readonly amount: Coin; - }; -} - -export function isMsgUndelegate(msg: AminoMsg): msg is MsgUndelegate { - return (msg as MsgUndelegate).type === "cosmos-sdk/MsgUndelegate"; -} - -// upgrade (no messages) - see https://github.com/cosmos/cosmos-sdk/blob/efa73c7/proto/cosmos/upgrade/upgrade.proto diff --git a/packages/launchpad/src/sequence.spec.ts b/packages/launchpad/src/sequence.spec.ts deleted file mode 100644 index 24c8006a62..0000000000 --- a/packages/launchpad/src/sequence.spec.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { assert } from "@cosmjs/utils"; - -import { findSequenceForSignedTx } from "./sequence"; -import response1 from "./testdata/txresponse1.json"; -import response2 from "./testdata/txresponse2.json"; -import response3 from "./testdata/txresponse3.json"; -import { isWrappedStdTx } from "./tx"; - -// Those values must match ./testdata/txresponse*.json -const chainId = "testing"; -const accountNumber = 4; - -describe("sequence", () => { - describe("findSequenceForSignedTx", () => { - it("works", async () => { - assert(isWrappedStdTx(response1.tx)); - assert(isWrappedStdTx(response2.tx)); - assert(isWrappedStdTx(response3.tx)); - - const current = 100; // what we get from GET /auth/accounts/{address} - expect(await findSequenceForSignedTx(response1.tx, chainId, accountNumber, current)).toEqual(10); - // We know response3.height > response1.height, so the sequence must be at least 10+1 - expect(await findSequenceForSignedTx(response3.tx, chainId, accountNumber, current, 11)).toEqual(19); - // We know response3.height > response2.height > response1.height, so the sequence must be at least 10+1 and smaller than 19 - expect(await findSequenceForSignedTx(response2.tx, chainId, accountNumber, 19, 11)).toEqual(13); - }); - - it("returns undefined when sequence is not in range", async () => { - assert(isWrappedStdTx(response1.tx)); - assert(isWrappedStdTx(response2.tx)); - assert(isWrappedStdTx(response3.tx)); - - expect(await findSequenceForSignedTx(response1.tx, chainId, accountNumber, 5)).toBeUndefined(); - expect(await findSequenceForSignedTx(response1.tx, chainId, accountNumber, 20, 11)).toBeUndefined(); - expect(await findSequenceForSignedTx(response1.tx, chainId, accountNumber, 20, 50)).toBeUndefined(); - - // upper bound is not included in the possible results - expect(await findSequenceForSignedTx(response1.tx, chainId, accountNumber, 10)).toBeUndefined(); - }); - }); -}); diff --git a/packages/launchpad/src/sequence.ts b/packages/launchpad/src/sequence.ts deleted file mode 100644 index c413f1c4eb..0000000000 --- a/packages/launchpad/src/sequence.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { decodeSignature, makeSignDoc, serializeSignDoc } from "@cosmjs/amino"; -import { Secp256k1, Secp256k1Signature, sha256 } from "@cosmjs/crypto"; - -import { WrappedStdTx } from "./tx"; - -/** - * Serach for sequence s with `min` <= `s` < `upperBound` to find the sequence that was used to sign the transaction - * - * @param tx The signed transaction - * @param chainId The chain ID for which this transaction was signed - * @param accountNumber The account number for which this transaction was signed - * @param upperBound The upper bound for the testing, i.e. sequence must be lower than this value - * @param min The lowest sequence that is tested - * - * @returns the sequence if a match was found and undefined otherwise - */ -export async function findSequenceForSignedTx( - tx: WrappedStdTx, - chainId: string, - accountNumber: number, - upperBound: number, - min = 0, -): Promise { - const firstSignature = tx.value.signatures.find(() => true); - if (!firstSignature) throw new Error("Signature missing in tx"); - - const { pubkey, signature } = decodeSignature(firstSignature); - const secp256keSignature = Secp256k1Signature.fromFixedLength(signature); - - for (let s = min; s < upperBound; s++) { - // console.log(`Trying sequence ${s}`); - const signBytes = serializeSignDoc( - makeSignDoc(tx.value.msg, tx.value.fee, chainId, tx.value.memo || "", accountNumber, s), - ); - const prehashed = sha256(signBytes); - const valid = await Secp256k1.verifySignature(secp256keSignature, prehashed, pubkey); - if (valid) return s; - } - return undefined; -} diff --git a/packages/launchpad/src/signingcosmosclient.spec.ts b/packages/launchpad/src/signingcosmosclient.spec.ts deleted file mode 100644 index a5a6f471c6..0000000000 --- a/packages/launchpad/src/signingcosmosclient.spec.ts +++ /dev/null @@ -1,274 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { coin, coins, makeCosmoshubPath, Secp256k1HdWallet } from "@cosmjs/amino"; -import { assert } from "@cosmjs/utils"; - -import { assertIsBroadcastTxSuccess, PrivateCosmosClient } from "./cosmosclient"; -import { GasPrice } from "./fee"; -import { MsgDelegate, MsgSend } from "./msgs"; -import { PrivateSigningCosmosClient, SigningCosmosClient } from "./signingcosmosclient"; -import { - base64Matcher, - faucet, - launchpad, - makeRandomAddress, - pendingWithoutLaunchpad, -} from "./testutils.spec"; - -describe("SigningCosmosClient", () => { - describe("makeReadOnly", () => { - it("can be constructed with default fees", async () => { - const wallet = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic); - const client = new SigningCosmosClient(launchpad.endpoint, faucet.address0, wallet); - const openedClient = client as unknown as PrivateSigningCosmosClient; - expect(openedClient.fees).toEqual({ - send: { - amount: [ - { - amount: "2000", - denom: "ucosm", - }, - ], - gas: "80000", - }, - }); - }); - - it("can be constructed with custom gas price", async () => { - const wallet = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic); - const gasPrice = GasPrice.fromString("3.14utest"); - const client = new SigningCosmosClient(launchpad.endpoint, faucet.address0, wallet, gasPrice); - const openedClient = client as unknown as PrivateSigningCosmosClient; - expect(openedClient.fees).toEqual({ - send: { - amount: [ - { - amount: "251200", // 3.14 * 80_000 - denom: "utest", - }, - ], - gas: "80000", - }, - }); - }); - - it("can be constructed with custom gas limits", async () => { - const wallet = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic); - const gasLimits = { - send: 160000, - }; - const client = new SigningCosmosClient( - launchpad.endpoint, - faucet.address0, - wallet, - undefined, - gasLimits, - ); - const openedClient = client as unknown as PrivateSigningCosmosClient; - expect(openedClient.fees).toEqual({ - send: { - amount: [ - { - amount: "4000", // 0.025 * 160_000 - denom: "ucosm", - }, - ], - gas: "160000", - }, - }); - }); - - it("can be constructed with custom gas price and gas limits", async () => { - const wallet = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic); - const gasPrice = GasPrice.fromString("3.14utest"); - const gasLimits = { - send: 160000, - }; - const client = new SigningCosmosClient( - launchpad.endpoint, - faucet.address0, - wallet, - gasPrice, - gasLimits, - ); - const openedClient = client as unknown as PrivateSigningCosmosClient; - expect(openedClient.fees).toEqual({ - send: { - amount: [ - { - amount: "502400", // 3.14 * 160_000 - denom: "utest", - }, - ], - gas: "160000", - }, - }); - }); - }); - - describe("getHeight", () => { - it("always uses authAccount implementation", async () => { - pendingWithoutLaunchpad(); - const wallet = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic); - const client = new SigningCosmosClient(launchpad.endpoint, faucet.address0, wallet); - - const openedClient = client as unknown as PrivateCosmosClient; - const blockLatestSpy = spyOn(openedClient.lcdClient, "blocksLatest").and.callThrough(); - const authAccountsSpy = spyOn(openedClient.lcdClient.auth, "account").and.callThrough(); - - const height = await client.getHeight(); - expect(height).toBeGreaterThan(0); - - expect(blockLatestSpy).toHaveBeenCalledTimes(0); - expect(authAccountsSpy).toHaveBeenCalledTimes(1); - }); - }); - - describe("sendTokens", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const wallet = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic); - const client = new SigningCosmosClient(launchpad.endpoint, faucet.address0, wallet); - - const amount = coins(7890, "ucosm"); - const beneficiaryAddress = makeRandomAddress(); - - // no tokens here - const before = await client.getAccount(beneficiaryAddress); - expect(before).toBeUndefined(); - - // send - const result = await client.sendTokens(beneficiaryAddress, amount, "for dinner"); - assertIsBroadcastTxSuccess(result); - const [firstLog] = result.logs; - expect(firstLog).toBeTruthy(); - - // got tokens - const after = await client.getAccount(beneficiaryAddress); - assert(after); - expect(after.balance).toEqual(amount); - }); - }); - - describe("signAndBroadcast", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const wallet = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic); - const client = new SigningCosmosClient(launchpad.endpoint, faucet.address0, wallet); - - const msg: MsgDelegate = { - type: "cosmos-sdk/MsgDelegate", - value: { - delegator_address: faucet.address0, - validator_address: launchpad.validator.address, - amount: coin(1234, "ustake"), - }, - }; - const fee = { - amount: coins(2000, "ucosm"), - gas: "180000", // 180k - }; - const result = await client.signAndBroadcast([msg], fee, "Use your power wisely"); - assertIsBroadcastTxSuccess(result); - }); - }); - - describe("sign", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const wallet = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic); - const client = new SigningCosmosClient(launchpad.endpoint, faucet.address0, wallet); - - const msg1: MsgDelegate = { - type: "cosmos-sdk/MsgDelegate", - value: { - delegator_address: faucet.address0, - validator_address: launchpad.validator.address, - amount: coin(1234, "ustake"), - }, - }; - const msg2: MsgSend = { - type: "cosmos-sdk/MsgSend", - value: { - from_address: faucet.address0, - to_address: makeRandomAddress(), - amount: coins(1234567, "ucosm"), - }, - }; - const fee = { - amount: coins(2000, "ucosm"), - gas: "180000", // 180k - }; - const memo = "Use your power wisely"; - - const signed = await client.sign([msg1, msg2], fee, memo); - expect(signed.msg).toEqual([msg1, msg2]); - expect(signed.fee).toEqual(fee); - expect(signed.memo).toEqual(memo); - expect(signed.signatures).toEqual([ - { - pub_key: faucet.pubkey0, - signature: jasmine.stringMatching(base64Matcher), - }, - ]); - // Ensure signed transaction is valid - const broadcastResult = await client.broadcastTx(signed); - assertIsBroadcastTxSuccess(broadcastResult); - }); - }); - - describe("appendSignature", () => { - it("works", async () => { - pendingWithoutLaunchpad(); - const wallet0 = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic, { - hdPaths: [makeCosmoshubPath(0)], - }); - const wallet1 = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic, { - hdPaths: [makeCosmoshubPath(1)], - }); - const client0 = new SigningCosmosClient(launchpad.endpoint, faucet.address0, wallet0); - const client1 = new SigningCosmosClient(launchpad.endpoint, faucet.address1, wallet1); - - const msg1: MsgSend = { - type: "cosmos-sdk/MsgSend", - value: { - from_address: faucet.address0, - to_address: makeRandomAddress(), - amount: coins(1234567, "ucosm"), - }, - }; - const msg2: MsgSend = { - type: "cosmos-sdk/MsgSend", - value: { - from_address: faucet.address1, - to_address: makeRandomAddress(), - amount: coins(1234567, "ucosm"), - }, - }; - const fee = { - amount: coins(2000, "ucosm"), - gas: "160000", // 2*80k - }; - const memo = "This must be authorized by the two of us"; - - const signed = await client0.sign([msg1, msg2], fee, memo); - - const cosigned = await client1.appendSignature(signed); - expect(cosigned.msg).toEqual([msg1, msg2]); - expect(cosigned.fee).toEqual(fee); - expect(cosigned.memo).toEqual(memo); - expect(cosigned.signatures).toEqual([ - { - pub_key: faucet.pubkey0, - signature: jasmine.stringMatching(base64Matcher), - }, - { - pub_key: faucet.pubkey1, - signature: jasmine.stringMatching(base64Matcher), - }, - ]); - // Ensure signed transaction is valid - const broadcastResult = await client0.broadcastTx(cosigned); - assertIsBroadcastTxSuccess(broadcastResult); - }); - }); -}); diff --git a/packages/launchpad/src/signingcosmosclient.ts b/packages/launchpad/src/signingcosmosclient.ts deleted file mode 100644 index 42c6e4c9ff..0000000000 --- a/packages/launchpad/src/signingcosmosclient.ts +++ /dev/null @@ -1,128 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { AminoMsg, Coin, makeSignDoc, makeStdTx, OfflineAminoSigner, StdFee, StdTx } from "@cosmjs/amino"; -import equals from "fast-deep-equal"; - -import { Account, BroadcastTxResult, CosmosClient, GetSequenceResult } from "./cosmosclient"; -import { buildFeeTable, FeeTable, GasLimits, GasPrice } from "./fee"; -import { BroadcastMode } from "./lcdapi"; -import { MsgSend } from "./msgs"; - -/** - * These fees are used by the higher level methods of SigningCosmosClient - */ -export interface CosmosFeeTable extends FeeTable { - readonly send: StdFee; -} - -const defaultGasPrice = GasPrice.fromString("0.025ucosm"); -const defaultGasLimits: GasLimits = { send: 80000 }; - -/** Use for testing only */ -export interface PrivateSigningCosmosClient { - readonly fees: CosmosFeeTable; -} - -export class SigningCosmosClient extends CosmosClient { - public readonly fees: CosmosFeeTable; - public readonly signerAddress: string; - - private readonly signer: OfflineAminoSigner; - - /** - * Creates a new client with signing capability to interact with a Cosmos SDK blockchain. This is the bigger brother of CosmosClient. - * - * This instance does a lot of caching. In order to benefit from that you should try to use one instance - * for the lifetime of your application. When switching backends, a new instance must be created. - * - * @param apiUrl The URL of a Cosmos SDK light client daemon API (sometimes called REST server or REST API) - * @param signerAddress The address that will sign transactions using this instance. The `signer` must be able to sign with this address. - * @param signer An implementation of OfflineAminoSigner which can provide signatures for transactions, potentially requiring user input. - * @param gasPrice The price paid per unit of gas - * @param gasLimits Custom overrides for gas limits related to specific transaction types - * @param broadcastMode Defines at which point of the transaction processing the broadcastTx method returns - */ - public constructor( - apiUrl: string, - signerAddress: string, - signer: OfflineAminoSigner, - gasPrice: GasPrice = defaultGasPrice, - gasLimits: Partial> = {}, - broadcastMode = BroadcastMode.Block, - ) { - super(apiUrl, broadcastMode); - this.anyValidAddress = signerAddress; - this.signerAddress = signerAddress; - this.signer = signer; - this.fees = buildFeeTable(gasPrice, defaultGasLimits, gasLimits); - } - - public override async getSequence(address?: string): Promise { - return super.getSequence(address || this.signerAddress); - } - - public override async getAccount(address?: string): Promise { - return super.getAccount(address || this.signerAddress); - } - - public async sendTokens( - recipientAddress: string, - amount: readonly Coin[], - memo = "", - ): Promise { - const sendMsg: MsgSend = { - type: "cosmos-sdk/MsgSend", - value: { - from_address: this.signerAddress, - to_address: recipientAddress, - amount: amount, - }, - }; - return this.signAndBroadcast([sendMsg], this.fees.send, memo); - } - - /** - * Gets account number and sequence from the API, creates a sign doc, - * creates a single signature, assembles the signed transaction and broadcasts it. - */ - public async signAndBroadcast( - msgs: readonly AminoMsg[], - fee: StdFee, - memo = "", - ): Promise { - const signedTx = await this.sign(msgs, fee, memo); - return this.broadcastTx(signedTx); - } - - /** - * Gets account number and sequence from the API, creates a sign doc, - * creates a single signature and assembles the signed transaction. - */ - public async sign(msgs: readonly AminoMsg[], fee: StdFee, memo = ""): Promise { - const { accountNumber, sequence } = await this.getSequence(); - const chainId = await this.getChainId(); - const signDoc = makeSignDoc(msgs, fee, chainId, memo, accountNumber, sequence); - const { signed, signature } = await this.signer.signAmino(this.signerAddress, signDoc); - return makeStdTx(signed, signature); - } - - /** - * Gets account number and sequence from the API, creates a sign doc, - * creates a single signature and appends it to the existing signatures. - */ - public async appendSignature(signedTx: StdTx): Promise { - const { msg: msgs, fee, memo } = signedTx; - const { accountNumber, sequence } = await this.getSequence(); - const chainId = await this.getChainId(); - const signDoc = makeSignDoc(msgs, fee, chainId, memo, accountNumber, sequence); - const { signed, signature: additionalSignature } = await this.signer.signAmino( - this.signerAddress, - signDoc, - ); - if (!equals(signDoc, signed)) { - throw new Error( - "The signed document differs from the one of the original transaction. This is not allowed since the resulting transaction will be invalid.", - ); - } - return makeStdTx(signed, [...signedTx.signatures, additionalSignature]); - } -} diff --git a/packages/launchpad/src/testdata/cosmoshub.json b/packages/launchpad/src/testdata/cosmoshub.json deleted file mode 100644 index cb33539c18..0000000000 --- a/packages/launchpad/src/testdata/cosmoshub.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "//source": "https://hubble.figment.network/cosmos/chains/cosmoshub-3/blocks/415777/transactions/2BD600EA6090FC75FD844CA73542CC90A828770F4C01C5B483C3C1C43CCB65F4?format=json", - "tx": { - "type": "cosmos-sdk/StdTx", - "value": { - "msg": [ - { - "type": "cosmos-sdk/MsgSend", - "value": { - "from_address": "cosmos1txqfn5jmcts0x0q7krdxj8tgf98tj0965vqlmq", - "to_address": "cosmos1nynns8ex9fq6sjjfj8k79ymkdz4sqth06xexae", - "amount": [ - { - "denom": "uatom", - "amount": "35997500" - } - ] - } - } - ], - "fee": { - "amount": [ - { - "denom": "uatom", - "amount": "2500" - } - ], - "gas": "100000" - }, - "signatures": [ - { - "pub_key": { - "type": "tendermint/PubKeySecp256k1", - "value": "A5qFcJBJvEK/fOmEAY0DHNWwSRZ9TEfNZyH8VoVvDtAq" - }, - "signature": "NK1Oy4EUGAsoC03c1wi9GG03JC/39LEdautC5Jk643oIbEPqeXHMwaqbdvO/Jws0X/NAXaN8SAy2KNY5Qml+5Q==" - } - ], - "memo": "" - } - }, - "tx_data": "ygEoKBapCkOoo2GaChRZgJnSW8Lg8zwesNppHWhJTrk8uhIUmSc4HyYqQahKSZHt4pN2aKsALu8aEQoFdWF0b20SCDM1OTk3NTAwEhMKDQoFdWF0b20SBDI1MDAQoI0GGmoKJuta6YchA5qFcJBJvEK/fOmEAY0DHNWwSRZ9TEfNZyH8VoVvDtAqEkA0rU7LgRQYCygLTdzXCL0YbTckL/f0sR1q60LkmTrjeghsQ+p5cczBqpt2878nCzRf80Bdo3xIDLYo1jlCaX7l", - "id": "2BD600EA6090FC75FD844CA73542CC90A828770F4C01C5B483C3C1C43CCB65F4" -} diff --git a/packages/launchpad/src/testdata/txresponse1.json b/packages/launchpad/src/testdata/txresponse1.json deleted file mode 100644 index 703ea696d7..0000000000 --- a/packages/launchpad/src/testdata/txresponse1.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "height": "15888", - "txhash": "672DEDE8EF4DE8B5818959F417CCA357079D4D7A19C4B65443C7FBF8176AABF9", - "raw_log": "[{\"msg_index\":0,\"log\":\"\",\"events\":[{\"type\":\"message\",\"attributes\":[{\"key\":\"action\",\"value\":\"send\"},{\"key\":\"sender\",\"value\":\"cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6\"},{\"key\":\"module\",\"value\":\"bank\"}]},{\"type\":\"transfer\",\"attributes\":[{\"key\":\"recipient\",\"value\":\"cosmos1t70qnpr0az8tf7py83m4ue5y89w58lkjmx0yq2\"},{\"key\":\"amount\",\"value\":\"75000ucosm\"}]}]}]", - "logs": [ - { - "msg_index": 0, - "log": "", - "events": [ - { - "type": "message", - "attributes": [ - { "key": "action", "value": "send" }, - { "key": "sender", "value": "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6" }, - { "key": "module", "value": "bank" } - ] - }, - { - "type": "transfer", - "attributes": [ - { "key": "recipient", "value": "cosmos1t70qnpr0az8tf7py83m4ue5y89w58lkjmx0yq2" }, - { "key": "amount", "value": "75000ucosm" } - ] - } - ] - } - ], - "gas_wanted": "200000", - "gas_used": "65407", - "tx": { - "type": "cosmos-sdk/StdTx", - "value": { - "msg": [ - { - "type": "cosmos-sdk/MsgSend", - "value": { - "from_address": "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", - "to_address": "cosmos1t70qnpr0az8tf7py83m4ue5y89w58lkjmx0yq2", - "amount": [{ "denom": "ucosm", "amount": "75000" }] - } - } - ], - "fee": { "amount": [{ "denom": "ucosm", "amount": "5000" }], "gas": "200000" }, - "signatures": [ - { - "pub_key": { - "type": "tendermint/PubKeySecp256k1", - "value": "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ" - }, - "signature": "US7oH8S/8TxVrtBQkOhHxAM+oDB2spNAEawgh6H8CCFLRMOJK+uvQZZ6ceUgUsvDbxwCz7re1RU272fymMYRZQ==" - } - ], - "memo": "My first payment" - } - }, - "timestamp": "2020-02-14T11:25:55Z" -} diff --git a/packages/launchpad/src/testdata/txresponse2.json b/packages/launchpad/src/testdata/txresponse2.json deleted file mode 100644 index 0d1a37f932..0000000000 --- a/packages/launchpad/src/testdata/txresponse2.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "height": "16456", - "txhash": "7BFE4B93AF190F60132C62D08FDF50BE462FBCE374EB13D3FD0C32461E771EC0", - "raw_log": "[{\"msg_index\":0,\"log\":\"\",\"events\":[{\"type\":\"message\",\"attributes\":[{\"key\":\"action\",\"value\":\"send\"},{\"key\":\"sender\",\"value\":\"cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6\"},{\"key\":\"module\",\"value\":\"bank\"}]},{\"type\":\"transfer\",\"attributes\":[{\"key\":\"recipient\",\"value\":\"cosmos1t70qnpr0az8tf7py83m4ue5y89w58lkjmx0yq2\"},{\"key\":\"amount\",\"value\":\"75000ucosm\"}]}]}]", - "logs": [ - { - "msg_index": 0, - "log": "", - "events": [ - { - "type": "message", - "attributes": [ - { "key": "action", "value": "send" }, - { "key": "sender", "value": "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6" }, - { "key": "module", "value": "bank" } - ] - }, - { - "type": "transfer", - "attributes": [ - { "key": "recipient", "value": "cosmos1t70qnpr0az8tf7py83m4ue5y89w58lkjmx0yq2" }, - { "key": "amount", "value": "75000ucosm" } - ] - } - ] - } - ], - "gas_wanted": "200000", - "gas_used": "65407", - "tx": { - "type": "cosmos-sdk/StdTx", - "value": { - "msg": [ - { - "type": "cosmos-sdk/MsgSend", - "value": { - "from_address": "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", - "to_address": "cosmos1t70qnpr0az8tf7py83m4ue5y89w58lkjmx0yq2", - "amount": [{ "denom": "ucosm", "amount": "75000" }] - } - } - ], - "fee": { "amount": [{ "denom": "ucosm", "amount": "5000" }], "gas": "200000" }, - "signatures": [ - { - "pub_key": { - "type": "tendermint/PubKeySecp256k1", - "value": "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ" - }, - "signature": "ltvd9Rb3RF4zjbUVrpDpkok34g+py7XR8ZcM0tZUYRxxVdcMEin010x+ZFd/mOuutPj9fDmSENnienc/yi4msw==" - } - ], - "memo": "My first payment" - } - }, - "timestamp": "2020-02-14T11:35:41Z" -} diff --git a/packages/launchpad/src/testdata/txresponse3.json b/packages/launchpad/src/testdata/txresponse3.json deleted file mode 100644 index 8ffd07279a..0000000000 --- a/packages/launchpad/src/testdata/txresponse3.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "height": "20730", - "txhash": "625BC75E697F73DA037387C34002BB2F682E7ACDCC4E015D3E90420516C6D0C8", - "raw_log": "[{\"msg_index\":0,\"log\":\"\",\"events\":[{\"type\":\"message\",\"attributes\":[{\"key\":\"action\",\"value\":\"send\"},{\"key\":\"sender\",\"value\":\"cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6\"},{\"key\":\"module\",\"value\":\"bank\"}]},{\"type\":\"transfer\",\"attributes\":[{\"key\":\"recipient\",\"value\":\"cosmos1t70qnpr0az8tf7py83m4ue5y89w58lkjmx0yq2\"},{\"key\":\"amount\",\"value\":\"75000ucosm\"}]}]}]", - "logs": [ - { - "msg_index": 0, - "log": "", - "events": [ - { - "type": "message", - "attributes": [ - { "key": "action", "value": "send" }, - { "key": "sender", "value": "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6" }, - { "key": "module", "value": "bank" } - ] - }, - { - "type": "transfer", - "attributes": [ - { "key": "recipient", "value": "cosmos1t70qnpr0az8tf7py83m4ue5y89w58lkjmx0yq2" }, - { "key": "amount", "value": "75000ucosm" } - ] - } - ] - } - ], - "gas_wanted": "200000", - "gas_used": "65407", - "tx": { - "type": "cosmos-sdk/StdTx", - "value": { - "msg": [ - { - "type": "cosmos-sdk/MsgSend", - "value": { - "from_address": "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", - "to_address": "cosmos1t70qnpr0az8tf7py83m4ue5y89w58lkjmx0yq2", - "amount": [{ "denom": "ucosm", "amount": "75000" }] - } - } - ], - "fee": { "amount": [{ "denom": "ucosm", "amount": "5000" }], "gas": "200000" }, - "signatures": [ - { - "pub_key": { - "type": "tendermint/PubKeySecp256k1", - "value": "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ" - }, - "signature": "eOFGl1tIHDMv3JdCK9fRSikVbYUD8+B0ksb3dJFya8MPYgpEpdSA7zZc+5n/cW6LR/BJdib4nqmJQv1yD9lm3g==" - } - ], - "memo": "My first payment" - } - }, - "timestamp": "2020-02-14T12:48:56Z" -} diff --git a/packages/launchpad/src/testutils.spec.ts b/packages/launchpad/src/testutils.spec.ts deleted file mode 100644 index 41bd378f17..0000000000 --- a/packages/launchpad/src/testutils.spec.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { Random } from "@cosmjs/crypto"; -import { Bech32 } from "@cosmjs/encoding"; - -export function makeRandomAddress(): string { - return Bech32.encode("cosmos", Random.getBytes(20)); -} - -export const nonNegativeIntegerMatcher = /^[0-9]+$/; -/** Matches decimals < 1.0 */ -export const smallDecimalMatcher = /^0\.[0-9]+$/; -/** Matches decimals >= 1.0 */ -export const bigDecimalMatcher = /^[1-9][0-9]*\.[0-9]+$/; -export const tendermintIdMatcher = /^[0-9A-F]{64}$/; -export const tendermintOptionalIdMatcher = /^([0-9A-F]{64}|)$/; -export const tendermintAddressMatcher = /^[0-9A-F]{40}$/; -export const tendermintShortHashMatcher = /^[0-9a-f]{40}$/; -export const dateTimeStampMatcher = /^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(?:\.[0-9]+)?Z$/; -export const semverMatcher = /^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/; -/** @see https://rgxdb.com/r/1NUN74O6 */ -export const base64Matcher = - /^(?:[a-zA-Z0-9+/]{4})*(?:|(?:[a-zA-Z0-9+/]{3}=)|(?:[a-zA-Z0-9+/]{2}==)|(?:[a-zA-Z0-9+/]{1}===))$/; -export const hexMatcher = /^([0-9a-fA-F][0-9a-fA-F])*$/; - -// https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#bech32 -export const bech32AddressMatcher = /^[\x21-\x7e]{1,83}1[02-9ac-hj-np-z]{38}$/; - -export const launchpad = { - endpoint: "http://localhost:1317", - chainId: "testing", - moniker: "node001", - commissionUpdateTime: "2020-10-08T10:18:11.2275025Z", - validator: { - pubkey: "cosmosvalconspub1zcjduepqf62c9h86qqn4g9s4khcng86quanw8rn5mm6lf69c99vxff0302ksv2ljyl", - address: "cosmosvaloper1yfkkk04ve8a0sugj4fe6q6zxuvmvza8r3arurr", - delegatorAddress: "cosmos1yfkkk04ve8a0sugj4fe6q6zxuvmvza8r5fhf0s", - }, -}; - -export const faucet = { - mnemonic: - "economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone", - pubkey0: { - type: "tendermint/PubKeySecp256k1", - value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ", - }, - pubkey1: { - type: "tendermint/PubKeySecp256k1", - value: "AiDosfIbBi54XJ1QjCeApumcy/FjdtF+YhywPf3DKTx7", - }, - pubkey2: { - type: "tendermint/PubKeySecp256k1", - value: "AzQg33JZqH7vSsm09esZY5bZvmzYwE/SY78cA0iLxpD7", - }, - pubkey3: { - type: "tendermint/PubKeySecp256k1", - value: "A3gOAlB6aiRTCPvWMQg2+ZbGYNsLd8qlvV28m8p2UhY2", - }, - pubkey4: { - type: "tendermint/PubKeySecp256k1", - value: "Aum2063ub/ErUnIUB36sK55LktGUStgcbSiaAnL1wadu", - }, - address0: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", - address1: "cosmos10dyr9899g6t0pelew4nvf4j5c3jcgv0r73qga5", - address2: "cosmos1xy4yqngt0nlkdcenxymg8tenrghmek4nmqm28k", - address3: "cosmos142u9fgcjdlycfcez3lw8x6x5h7rfjlnfhpw2lx", - address4: "cosmos1hsm76p4ahyhl5yh3ve9ur49r5kemhp2r0dcjvx", -}; - -/** Unused account */ -export const unused = { - pubkey: { - type: "tendermint/PubKeySecp256k1", - value: "ArkCaFUJ/IH+vKBmNRCdUVl3mCAhbopk9jjW4Ko4OfRQ", - }, - address: "cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u", - accountNumber: 19, - sequence: 0, -}; - -export function launchpadEnabled(): boolean { - return !!process.env.LAUNCHPAD_ENABLED; -} - -export function pendingWithoutLaunchpad(): void { - if (!launchpadEnabled()) { - return pending("Set LAUNCHPAD_ENABLED to enable Launchpad-based tests"); - } -} - -/** Returns first element. Throws if array has a different length than 1. */ -export function fromOneElementArray(elements: ArrayLike): T { - if (elements.length !== 1) throw new Error(`Expected exactly one element but got ${elements.length}`); - return elements[0]; -} diff --git a/packages/launchpad/src/tx.ts b/packages/launchpad/src/tx.ts deleted file mode 100644 index 16f97072aa..0000000000 --- a/packages/launchpad/src/tx.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { isStdTx, StdTx } from "@cosmjs/amino"; - -/** - * An Amino JSON wrapper around the Tx interface - */ -export interface WrappedTx { - readonly type: string; - readonly value: any; -} - -/** - * An Amino JSON wrapper around StdTx - */ -export interface WrappedStdTx extends WrappedTx { - readonly type: "cosmos-sdk/StdTx"; - readonly value: StdTx; -} - -export function isWrappedStdTx(wrapped: WrappedTx): wrapped is WrappedStdTx { - return (wrapped as WrappedStdTx).type === "cosmos-sdk/StdTx" && isStdTx(wrapped.value); -} - -/** @deprecated use WrappedStdTx */ -export type CosmosSdkTx = WrappedStdTx; diff --git a/packages/launchpad/tsconfig.eslint.json b/packages/launchpad/tsconfig.eslint.json deleted file mode 100644 index 9a9f3b5704..0000000000 --- a/packages/launchpad/tsconfig.eslint.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - // extend your base config so you don't have to redefine your compilerOptions - "extends": "./tsconfig.json", - "include": [ - "src/**/*", - "*.js", - ".eslintrc.js" - ] -} diff --git a/packages/launchpad/tsconfig.json b/packages/launchpad/tsconfig.json deleted file mode 100644 index df66add1d8..0000000000 --- a/packages/launchpad/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "baseUrl": ".", - "outDir": "build", - "rootDir": "src" - }, - "include": [ - "src/**/*" - ] -} diff --git a/packages/launchpad/typedoc.js b/packages/launchpad/typedoc.js deleted file mode 100644 index ffe4be645a..0000000000 --- a/packages/launchpad/typedoc.js +++ /dev/null @@ -1,11 +0,0 @@ -const packageJson = require("./package.json"); - -module.exports = { - entryPoints: ["./src"], - out: "docs", - exclude: "**/*.spec.ts", - name: `${packageJson.name} Documentation`, - readme: "README.md", - excludeExternals: true, - excludePrivate: true, -}; diff --git a/packages/launchpad/webpack.web.config.js b/packages/launchpad/webpack.web.config.js deleted file mode 100644 index d4f02a42d7..0000000000 --- a/packages/launchpad/webpack.web.config.js +++ /dev/null @@ -1,35 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -const glob = require("glob"); -const path = require("path"); -const webpack = require("webpack"); - -const target = "web"; -const distdir = path.join(__dirname, "dist", "web"); - -module.exports = [ - { - // bundle used for Karma tests - target: target, - entry: glob.sync("./build/**/*.spec.js"), - output: { - path: distdir, - filename: "tests.js", - }, - plugins: [ - new webpack.EnvironmentPlugin({ LAUNCHPAD_ENABLED: "" }), - new webpack.ProvidePlugin({ - Buffer: ["buffer", "Buffer"], - }), - ], - resolve: { - fallback: { - buffer: false, - crypto: false, - events: false, - path: false, - stream: require.resolve("stream-browserify"), - string_decoder: false, - }, - }, - }, -]; diff --git a/packages/ledger-amino/package.json b/packages/ledger-amino/package.json index 547a07373d..9fd9d564e9 100644 --- a/packages/ledger-amino/package.json +++ b/packages/ledger-amino/package.json @@ -46,7 +46,6 @@ "semver": "^7.3.2" }, "devDependencies": { - "@cosmjs/launchpad": "workspace:packages/launchpad", "@cosmjs/stargate": "workspace:packages/stargate", "@istanbuljs/nyc-config-typescript": "^1.0.1", "@ledgerhq/hw-transport": "^5.25.0", diff --git a/packages/ledger-amino/src/ledgersigner.spec.ts b/packages/ledger-amino/src/ledgersigner.spec.ts index af57942750..d9bf56a8c5 100644 --- a/packages/ledger-amino/src/ledgersigner.spec.ts +++ b/packages/ledger-amino/src/ledgersigner.spec.ts @@ -9,10 +9,6 @@ import { } from "@cosmjs/amino"; import { Secp256k1, Secp256k1Signature, sha256 } from "@cosmjs/crypto"; import { fromBase64 } from "@cosmjs/encoding"; -import { - assertIsBroadcastTxSuccess as assertIsBroadcastTxSuccessLaunchpad, - SigningCosmosClient, -} from "@cosmjs/launchpad"; import { assertIsDeliverTxSuccess as assertIsDeliverTxSuccessStargate, calculateFee, @@ -24,9 +20,7 @@ import Transport from "@ledgerhq/hw-transport"; import { LedgerSigner } from "./ledgersigner"; import { faucet, - launchpad, ledgerEnabled, - pendingWithoutLaunchpad, pendingWithoutLedger, pendingWithoutSimapp, simapp, @@ -166,24 +160,6 @@ describe("LedgerSigner", () => { interactiveTimeout, ); - it( - "creates signature accepted by Launchpad backend", - async () => { - pendingWithoutLedger(); - pendingWithoutLaunchpad(); - const signer = new LedgerSigner(transport, { - testModeAllowed: true, - hdPaths: [makeCosmoshubPath(0), makeCosmoshubPath(1), makeCosmoshubPath(10)], - }); - const [firstAccount] = await signer.getAccounts(); - - const client = new SigningCosmosClient(launchpad.endpoint, firstAccount.address, signer); - const result = await client.sendTokens(defaultLedgerAddress, coins(1234567, "ucosm")); - assertIsBroadcastTxSuccessLaunchpad(result); - }, - interactiveTimeout, - ); - it( "creates signature accepted by Stargate backend", async () => { diff --git a/packages/ledger-amino/src/testutils.spec.ts b/packages/ledger-amino/src/testutils.spec.ts index ce2d9151d9..49dfd157a7 100644 --- a/packages/ledger-amino/src/testutils.spec.ts +++ b/packages/ledger-amino/src/testutils.spec.ts @@ -18,16 +18,6 @@ export function pendingWithoutLedger(): void { } } -export function launchpadEnabled(): boolean { - return !!process.env.LAUNCHPAD_ENABLED; -} - -export function pendingWithoutLaunchpad(): void { - if (!launchpadEnabled()) { - return pending("Set LAUNCHPAD_ENABLED to enable Launchpad-based tests"); - } -} - export function simappEnabled(): boolean { return !!process.env.SIMAPP42_ENABLED || !!process.env.SIMAPP44_ENABLED; } @@ -38,11 +28,6 @@ export function pendingWithoutSimapp(): void { } } -export const launchpad = { - endpoint: "http://localhost:1317", - chainId: "testing", -}; - export const simapp = { endpoint: "ws://localhost:26658", chainId: "simd-testing", diff --git a/packages/proto-signing/src/coins.ts b/packages/proto-signing/src/coins.ts index f086677ec0..0a8a7bac68 100644 --- a/packages/proto-signing/src/coins.ts +++ b/packages/proto-signing/src/coins.ts @@ -4,7 +4,7 @@ import { Uint64 } from "@cosmjs/math"; /** * Takes a coins list like "819966000ucosm,700000000ustake" and parses it. * - * This is a Stargate ready version of parseCoins from @cosmjs/amino and @cosmjs/launchpad. + * This is a Stargate ready version of parseCoins from @cosmjs/amino. * It supports more denoms. */ export function parseCoins(input: string): Coin[] { diff --git a/packages/proto-signing/src/registry.ts b/packages/proto-signing/src/registry.ts index 90dbf12708..13b72f778a 100644 --- a/packages/proto-signing/src/registry.ts +++ b/packages/proto-signing/src/registry.ts @@ -81,27 +81,21 @@ export class Registry { * actual implementations. Those implementations are typically generated with ts-proto * but we also support protobuf.js as a type generator. * - * By default, a `new Registry()` constains amost no types. `Coin` and `MsgSend` are in there - * for historic reasons but this does not make a lot of sense. + * If there is no parameter given, a `new Registry()` adds the types `Coin` and `MsgSend` + * for historic reasons. Those can be overriden by customTypes. * * There are currently two methods for adding new types: - * 1. Using the `register()` method - * 2. Passing custom types to the constructor. - * This only creates confusion for users. The reason here is historical. - * Using `register()` is recommended and 2. is deprecated because its behaviour - * will change in https://github.com/cosmos/cosmjs/issues/994. - * - * There is currently no way to unregister/override the default types. We should - * change the `customTypes` argument to override the default types if set. - * See https://github.com/cosmos/cosmjs/issues/994 + * 1. Passing types to the constructor. + * 2. Using the `register()` method */ - public constructor(customTypes: Iterable<[string, GeneratedType]> = []) { + public constructor(customTypes?: Iterable<[string, GeneratedType]>) { const { cosmosCoin, cosmosMsgSend } = defaultTypeUrls; - this.types = new Map([ - [cosmosCoin, Coin], - [cosmosMsgSend, MsgSend], - ...customTypes, - ]); + this.types = customTypes + ? new Map([...customTypes]) + : new Map([ + [cosmosCoin, Coin], + [cosmosMsgSend, MsgSend], + ]); } public register(typeUrl: string, type: GeneratedType): void { diff --git a/packages/proto-signing/src/signer.ts b/packages/proto-signing/src/signer.ts index 321588a7f1..42ff2a8b46 100644 --- a/packages/proto-signing/src/signer.ts +++ b/packages/proto-signing/src/signer.ts @@ -1,14 +1,7 @@ import { OfflineAminoSigner, StdSignature } from "@cosmjs/amino"; import { SignDoc } from "cosmjs-types/cosmos/tx/v1beta1/tx"; -/** - * This is the same as Algo from @cosmjs/launchpad but those might diverge in the future. - */ export type Algo = "secp256k1" | "ed25519" | "sr25519"; - -/** - * This is the same as AccountData from @cosmjs/launchpad but those might diverge in the future. - */ export interface AccountData { /** A printable address (typically bech32 encoded) */ readonly address: string; diff --git a/packages/stargate/package.json b/packages/stargate/package.json index 68d5746326..6145f323d2 100644 --- a/packages/stargate/package.json +++ b/packages/stargate/package.json @@ -38,7 +38,7 @@ "pack-web": "yarn build-or-skip && webpack --mode development --config webpack.web.config.js" }, "dependencies": { - "@confio/ics23": "^0.6.3", + "@confio/ics23": "^0.6.8", "@cosmjs/amino": "workspace:packages/amino", "@cosmjs/encoding": "workspace:packages/encoding", "@cosmjs/math": "workspace:packages/math", diff --git a/packages/stargate/src/aminotypes.spec.ts b/packages/stargate/src/aminotypes.spec.ts index 14529fe83c..18f3fe48ea 100644 --- a/packages/stargate/src/aminotypes.spec.ts +++ b/packages/stargate/src/aminotypes.spec.ts @@ -41,6 +41,79 @@ import { import { AminoTypes } from "./aminotypes"; describe("AminoTypes", () => { + describe("constructor", () => { + const msg: MsgDelegate = { + delegatorAddress: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", + validatorAddress: "cosmos10dyr9899g6t0pelew4nvf4j5c3jcgv0r73qga5", + amount: coin(1234, "ucosm"), + }; + + it("can override type by type URL", () => { + const types = new AminoTypes({ + prefix: "cosmos", + additions: { + "/cosmos.staking.v1beta1.MsgDelegate": { + aminoType: "my-override/MsgDelegate", + toAmino: (m: MsgDelegate): { readonly foo: string } => ({ + foo: m.delegatorAddress ?? "", + }), + fromAmino: () => ({ + bar: 123, + }), + }, + }, + }); + + const aminoMsg = types.toAmino({ + typeUrl: "/cosmos.staking.v1beta1.MsgDelegate", + value: msg, + }); + expect(aminoMsg).toEqual({ + type: "my-override/MsgDelegate", + value: { + foo: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", + }, + }); + expect(types.fromAmino(aminoMsg)).toEqual({ + typeUrl: "/cosmos.staking.v1beta1.MsgDelegate", + value: { + bar: 123, + }, + }); + }); + + it("can override type with Amino type collision", () => { + const types = new AminoTypes({ + prefix: "cosmos", + additions: { + "/cosmos.staking.otherVersion456.MsgDelegate": { + aminoType: "cosmos-sdk/MsgDelegate", + toAmino: (m: MsgDelegate): { readonly foo: string } => ({ + foo: m.delegatorAddress ?? "", + }), + fromAmino: () => ({ + bar: 123, + }), + }, + }, + }); + + const aminoMsg = types.toAmino({ + typeUrl: "/cosmos.staking.otherVersion456.MsgDelegate", + value: msg, + }); + expect(aminoMsg).toEqual({ + type: "cosmos-sdk/MsgDelegate", + value: { + foo: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", + }, + }); + expect(() => types.fromAmino(aminoMsg)).toThrowError( + "Multiple types are registered with Amino type identifier 'cosmos-sdk/MsgDelegate': '/cosmos.staking.otherVersion456.MsgDelegate', '/cosmos.staking.v1beta1.MsgDelegate'. Thus fromAmino cannot be performed.", + ); + }); + }); + describe("toAmino", () => { // bank @@ -975,12 +1048,12 @@ describe("AminoTypes", () => { }); }); - it("works with overridden type url", () => { + it("works with overridden type URL", () => { const msg = new AminoTypes({ prefix: "cosmos", additions: { - "/my.OverrideType": { - aminoType: "cosmos-sdk/MsgDelegate", + "/cosmos.staking.v1beta1.MsgDelegate": { + aminoType: "cosmos-sdk/MsgDelegate2", toAmino: () => {}, fromAmino: ({ foo }: { readonly foo: string }): MsgDelegate => ({ delegatorAddress: foo, @@ -990,20 +1063,19 @@ describe("AminoTypes", () => { }, }, }).fromAmino({ - type: "cosmos-sdk/MsgDelegate", + type: "cosmos-sdk/MsgDelegate2", value: { foo: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", }, }); - const expected: { readonly typeUrl: "/my.OverrideType"; readonly value: MsgDelegate } = { - typeUrl: "/my.OverrideType", + expect(msg).toEqual({ + typeUrl: "/cosmos.staking.v1beta1.MsgDelegate", value: { delegatorAddress: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", validatorAddress: "cosmos10dyr9899g6t0pelew4nvf4j5c3jcgv0r73qga5", amount: coin(1234, "ucosm"), }, - }; - expect(msg).toEqual(expected); + }); }); it("throws for types which are not on chain yet", () => { diff --git a/packages/stargate/src/aminotypes.ts b/packages/stargate/src/aminotypes.ts index 673f387ad8..ac0fafa1ea 100644 --- a/packages/stargate/src/aminotypes.ts +++ b/packages/stargate/src/aminotypes.ts @@ -63,12 +63,12 @@ function omitDefault(input: T): T | undefined throw new Error(`Got unsupported type '${typeof input}'`); } -function createDefaultTypes(prefix: string): Record { +function createDefaultTypes(prefix: string): Record { return { // authz - "/cosmos.authz.v1beta1.MsgGrant": "not_implemented_on_chain", - "/cosmos.authz.v1beta1.MsgExec": "not_implemented_on_chain", - "/cosmos.authz.v1beta1.MsgRevoke": "not_implemented_on_chain", + "/cosmos.authz.v1beta1.MsgGrant": "not_supported_by_chain", + "/cosmos.authz.v1beta1.MsgExec": "not_supported_by_chain", + "/cosmos.authz.v1beta1.MsgRevoke": "not_supported_by_chain", // bank "/cosmos.bank.v1beta1.MsgSend": { @@ -512,8 +512,8 @@ function createDefaultTypes(prefix: string): Record; + // The map type here ensures uniqueness of the protobuf type URL in the key. + // There is no uniqueness guarantee of the Amino type identifier in the type + // system or constructor. Instead it's the user's responsibility to ensure + // there is no overlap when fromAmino is called. + private readonly register: Record; public constructor({ prefix, additions = {} }: AminoTypesOptions) { - const additionalAminoTypes = Object.values(additions); - const filteredDefaultTypes = Object.entries(createDefaultTypes(prefix)).reduce( - (acc, [key, value]) => - additionalAminoTypes.find(({ aminoType }) => { - if (value !== "not_implemented_on_chain") { - return value.aminoType === aminoType; - } - return false; - }) - ? acc - : { ...acc, [key]: value }, - {}, - ); - this.register = { ...filteredDefaultTypes, ...additions }; + const defaultTypes = createDefaultTypes(prefix); + this.register = { ...defaultTypes, ...additions }; } public toAmino({ typeUrl, value }: EncodeObject): AminoMsg { const converter = this.register[typeUrl]; - if (converter === "not_implemented_on_chain") { + if (converter === "not_supported_by_chain") { throw new Error( - `The message type '${typeUrl}' cannot be signed using the Amino JSON sign mode because this is not implemented on-chain.`, + `The message type '${typeUrl}' cannot be signed using the Amino JSON sign mode because this is not supported by chain.`, ); } if (!converter) { @@ -576,22 +568,34 @@ export class AminoTypes { } public fromAmino({ type, value }: AminoMsg): EncodeObject { - const result = Object.entries(this.register) + const matches = Object.entries(this.register) .filter(isAminoConverter) - .find((x) => x[1].aminoType === type); + .filter(([_typeUrl, { aminoType }]) => aminoType === type); - if (!result) { - throw new Error( - `Amino type identifier '${type}' does not exist in the Amino message type register. ` + - "If you need support for this message type, you can pass in additional entries to the AminoTypes constructor. " + - "If you think this message type should be included by default, please open an issue at https://github.com/cosmos/cosmjs/issues.", - ); + switch (matches.length) { + case 0: { + throw new Error( + `Amino type identifier '${type}' does not exist in the Amino message type register. ` + + "If you need support for this message type, you can pass in additional entries to the AminoTypes constructor. " + + "If you think this message type should be included by default, please open an issue at https://github.com/cosmos/cosmjs/issues.", + ); + } + case 1: { + const [typeUrl, converter] = matches[0]; + return { + typeUrl: typeUrl, + value: converter.fromAmino(value), + }; + } + default: + throw new Error( + `Multiple types are registered with Amino type identifier '${type}': '` + + matches + .map(([key, _value]) => key) + .sort() + .join("', '") + + "'. Thus fromAmino cannot be performed.", + ); } - const [typeUrl, converter] = result; - - return { - typeUrl: typeUrl, - value: converter.fromAmino(value), - }; } } diff --git a/packages/stargate/src/fee.ts b/packages/stargate/src/fee.ts index d531e2a7b0..55fb70a933 100644 --- a/packages/stargate/src/fee.ts +++ b/packages/stargate/src/fee.ts @@ -17,8 +17,6 @@ function checkDenom(denom: string): void { /** * A gas price, i.e. the price of a single unit of gas. This is typically a fraction of * the smallest fee token unit, such as 0.012utoken. - * - * This is the same as GasPrice from @cosmjs/launchpad but those might diverge in the future. */ export class GasPrice { public readonly amount: Decimal; diff --git a/packages/stargate/src/signingstargateclient.ts b/packages/stargate/src/signingstargateclient.ts index 0d34e1c758..f485fc29bd 100644 --- a/packages/stargate/src/signingstargateclient.ts +++ b/packages/stargate/src/signingstargateclient.ts @@ -14,7 +14,8 @@ import { } from "@cosmjs/proto-signing"; import { Tendermint34Client } from "@cosmjs/tendermint-rpc"; import { assert, assertDefined } from "@cosmjs/utils"; -import { MsgMultiSend } from "cosmjs-types/cosmos/bank/v1beta1/tx"; +import { MsgExec, MsgGrant, MsgRevoke } from "cosmjs-types/cosmos/authz/v1beta1/tx"; +import { MsgMultiSend, MsgSend } from "cosmjs-types/cosmos/bank/v1beta1/tx"; import { Coin } from "cosmjs-types/cosmos/base/v1beta1/coin"; import { MsgFundCommunityPool, @@ -22,6 +23,7 @@ import { MsgWithdrawDelegatorReward, MsgWithdrawValidatorCommission, } from "cosmjs-types/cosmos/distribution/v1beta1/tx"; +import { MsgGrantAllowance, MsgRevokeAllowance } from "cosmjs-types/cosmos/feegrant/v1beta1/tx"; import { MsgDeposit, MsgSubmitProposal, MsgVote } from "cosmjs-types/cosmos/gov/v1beta1/tx"; import { MsgBeginRedelegate, @@ -72,11 +74,18 @@ import { calculateFee, GasPrice } from "./fee"; import { DeliverTxResponse, StargateClient } from "./stargateclient"; export const defaultRegistryTypes: ReadonlyArray<[string, GeneratedType]> = [ + ["/cosmos.authz.v1beta1.MsgExec", MsgExec], + ["/cosmos.authz.v1beta1.MsgGrant", MsgGrant], + ["/cosmos.authz.v1beta1.MsgRevoke", MsgRevoke], ["/cosmos.bank.v1beta1.MsgMultiSend", MsgMultiSend], + ["/cosmos.bank.v1beta1.MsgSend", MsgSend], + ["/cosmos.base.v1beta1.Coin", Coin], ["/cosmos.distribution.v1beta1.MsgFundCommunityPool", MsgFundCommunityPool], ["/cosmos.distribution.v1beta1.MsgSetWithdrawAddress", MsgSetWithdrawAddress], ["/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward", MsgWithdrawDelegatorReward], ["/cosmos.distribution.v1beta1.MsgWithdrawValidatorCommission", MsgWithdrawValidatorCommission], + ["/cosmos.feegrant.v1beta1.MsgGrantAllowance", MsgGrantAllowance], + ["/cosmos.feegrant.v1beta1.MsgRevokeAllowance", MsgRevokeAllowance], ["/cosmos.gov.v1beta1.MsgDeposit", MsgDeposit], ["/cosmos.gov.v1beta1.MsgSubmitProposal", MsgSubmitProposal], ["/cosmos.gov.v1beta1.MsgVote", MsgVote], @@ -85,25 +94,25 @@ export const defaultRegistryTypes: ReadonlyArray<[string, GeneratedType]> = [ ["/cosmos.staking.v1beta1.MsgDelegate", MsgDelegate], ["/cosmos.staking.v1beta1.MsgEditValidator", MsgEditValidator], ["/cosmos.staking.v1beta1.MsgUndelegate", MsgUndelegate], - ["/ibc.core.channel.v1.MsgChannelOpenInit", MsgChannelOpenInit], - ["/ibc.core.channel.v1.MsgChannelOpenTry", MsgChannelOpenTry], + ["/ibc.applications.transfer.v1.MsgTransfer", MsgTransfer], + ["/ibc.core.channel.v1.MsgAcknowledgement", MsgAcknowledgement], + ["/ibc.core.channel.v1.MsgChannelCloseConfirm", MsgChannelCloseConfirm], + ["/ibc.core.channel.v1.MsgChannelCloseInit", MsgChannelCloseInit], ["/ibc.core.channel.v1.MsgChannelOpenAck", MsgChannelOpenAck], ["/ibc.core.channel.v1.MsgChannelOpenConfirm", MsgChannelOpenConfirm], - ["/ibc.core.channel.v1.MsgChannelCloseInit", MsgChannelCloseInit], - ["/ibc.core.channel.v1.MsgChannelCloseConfirm", MsgChannelCloseConfirm], + ["/ibc.core.channel.v1.MsgChannelOpenInit", MsgChannelOpenInit], + ["/ibc.core.channel.v1.MsgChannelOpenTry", MsgChannelOpenTry], ["/ibc.core.channel.v1.MsgRecvPacket", MsgRecvPacket], ["/ibc.core.channel.v1.MsgTimeout", MsgTimeout], ["/ibc.core.channel.v1.MsgTimeoutOnClose", MsgTimeoutOnClose], - ["/ibc.core.channel.v1.MsgAcknowledgement", MsgAcknowledgement], ["/ibc.core.client.v1.MsgCreateClient", MsgCreateClient], + ["/ibc.core.client.v1.MsgSubmitMisbehaviour", MsgSubmitMisbehaviour], ["/ibc.core.client.v1.MsgUpdateClient", MsgUpdateClient], ["/ibc.core.client.v1.MsgUpgradeClient", MsgUpgradeClient], - ["/ibc.core.client.v1.MsgSubmitMisbehaviour", MsgSubmitMisbehaviour], - ["/ibc.core.connection.v1.MsgConnectionOpenInit", MsgConnectionOpenInit], - ["/ibc.core.connection.v1.MsgConnectionOpenTry", MsgConnectionOpenTry], ["/ibc.core.connection.v1.MsgConnectionOpenAck", MsgConnectionOpenAck], ["/ibc.core.connection.v1.MsgConnectionOpenConfirm", MsgConnectionOpenConfirm], - ["/ibc.applications.transfer.v1.MsgTransfer", MsgTransfer], + ["/ibc.core.connection.v1.MsgConnectionOpenInit", MsgConnectionOpenInit], + ["/ibc.core.connection.v1.MsgConnectionOpenTry", MsgConnectionOpenTry], ]; function createDefaultRegistry(): Registry { diff --git a/packages/stargate/src/stargateclient.ts b/packages/stargate/src/stargateclient.ts index 3fc9ef795d..a5a7710888 100644 --- a/packages/stargate/src/stargateclient.ts +++ b/packages/stargate/src/stargateclient.ts @@ -35,9 +35,6 @@ export class TimeoutError extends Error { } } -/** - * This is the same as BlockHeader from @cosmjs/launchpad but those might diverge in the future. - */ export interface BlockHeader { readonly version: { readonly block: string; @@ -49,9 +46,6 @@ export interface BlockHeader { readonly time: string; } -/** - * This is the same as Block from @cosmjs/launchpad but those might diverge in the future. - */ export interface Block { /** The ID is a hash of the block header (uppercase hex) */ readonly id: string; diff --git a/packages/stargate/src/testutils.spec.ts b/packages/stargate/src/testutils.spec.ts index 5970efbb00..6935c6cb17 100644 --- a/packages/stargate/src/testutils.spec.ts +++ b/packages/stargate/src/testutils.spec.ts @@ -64,7 +64,7 @@ export function fromOneElementArray(elements: ArrayLike): T { } export const defaultGasPrice = GasPrice.fromString("0.025ucosm"); -export const defaultSendFee = calculateFee(80_000, defaultGasPrice); +export const defaultSendFee = calculateFee(100_000, defaultGasPrice); export const simapp = { tendermintUrl: "localhost:26658", diff --git a/packages/tendermint-rpc/src/tendermint34/adaptor/responses.ts b/packages/tendermint-rpc/src/tendermint34/adaptor/responses.ts index b8784188a0..b2255d99d2 100644 --- a/packages/tendermint-rpc/src/tendermint34/adaptor/responses.ts +++ b/packages/tendermint-rpc/src/tendermint34/adaptor/responses.ts @@ -757,7 +757,7 @@ function decodeBlock(data: RpcBlock): responses.Block { txs: data.data.txs ? assertArray(data.data.txs).map(fromBase64) : [], // Lift up .evidence.evidence to just .evidence // See https://github.com/tendermint/tendermint/issues/7697 - evidence: data.evidence?.evidence, + evidence: data.evidence?.evidence ?? [], }; } diff --git a/packages/tendermint-rpc/src/tendermint34/responses.ts b/packages/tendermint-rpc/src/tendermint34/responses.ts index c7648f6907..fbbb058d0d 100644 --- a/packages/tendermint-rpc/src/tendermint34/responses.ts +++ b/packages/tendermint-rpc/src/tendermint34/responses.ts @@ -227,8 +227,7 @@ export interface Block { */ readonly lastCommit: Commit | null; readonly txs: readonly Uint8Array[]; - // This field becomes non-optional in 0.28 (https://github.com/cosmos/cosmjs/issues/1011) - readonly evidence?: readonly Evidence[]; + readonly evidence: readonly Evidence[]; } /** diff --git a/scripts/launchpad/README.md b/scripts/launchpad/README.md deleted file mode 100644 index dc141b751a..0000000000 --- a/scripts/launchpad/README.md +++ /dev/null @@ -1,152 +0,0 @@ -# Local Launchpad development network with CosmWasm support - -## Starting the blockchain - -Run the following: - -``` -cd scripts/launchpad -./start.sh && ./init.sh -``` - -## CLI - -Docker-friendly access to `wasmcli` is provided. Just use the `./cli.sh` script. -For example: - -``` -./cli.sh status -``` - -This should give you output similar to the following if your blockchain is -running: - -```json -{ - "node_info": { - "protocol_version": { "p2p": "7", "block": "10", "app": "0" }, - "id": "223aedddd9442bcf16641858ca85837f27997d0d", - "listen_addr": "tcp://0.0.0.0:26656", - "network": "testing", - "version": "0.32.2", - "channels": "4020212223303800", - "moniker": "testing", - "other": { "tx_index": "on", "rpc_address": "tcp://127.0.0.1:26657" } - }, - "sync_info": { - "latest_block_hash": "3E3BEBCFA4E47BC67C7DE44DD4E83D8D42235DE75DA942A6BECD1F0F5A6246E4", - "latest_app_hash": "73A3641BDEFBB728B1B48FB87B510F3E76E3B4519BC4954C6E1060738FCE8B14", - "latest_block_height": "1217", - "latest_block_time": "2019-09-26T15:44:13.0111312Z", - "catching_up": false - }, - "validator_info": { - "address": "3A7EBE1A9E333146AE5D9FCB765B88BDD4D2859A", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "3ZYx1HKwT/llXzYC2yVeWEiWHd6uBQ7Bi7jiDFczx28=" - }, - "voting_power": "100" - } -} -``` - -## Adding the validator key to your keybase - -The Cosmos test network is initialised with a validator (see -`.gaiad/config/genesis.json`). This validator has the following mnemonic: - -``` -economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone -``` - -To add the validator key to your local keybase run the following, choose an -encryption passphrase (e.g. `testing123`) and enter the above mnemonic when -prompted: - -``` -./cli.sh keys add validator --recover -``` - -You should get output matching the following: - -``` -- name: validator - type: local - address: cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6 - pubkey: cosmospub1addwnpepqd8sgxq7aw348ydctp3n5ajufgxp395hksxjzc6565yfp56scupfqhlgyg5 - mnemonic: "" - threshold: 0 - pubkeys: [] -``` - -## Preset accounts - -1. **Faucet**
- economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone
- Address 0: cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6
- Address 1: cosmos10dyr9899g6t0pelew4nvf4j5c3jcgv0r73qga5
- Address 2: cosmos1xy4yqngt0nlkdcenxymg8tenrghmek4nmqm28k
- Address 3: cosmos142u9fgcjdlycfcez3lw8x6x5h7rfjlnfhpw2lx
- Address 4: cosmos1hsm76p4ahyhl5yh3ve9ur49r5kemhp2r0dcjvx
- Pubkey 0: A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ
- Pubkey 1: AiDosfIbBi54XJ1QjCeApumcy/FjdtF+YhywPf3DKTx7
- Pubkey 2: AzQg33JZqH7vSsm09esZY5bZvmzYwE/SY78cA0iLxpD7
- Pubkey 3: A3gOAlB6aiRTCPvWMQg2+ZbGYNsLd8qlvV28m8p2UhY2
- Pubkey 4: Aum2063ub/ErUnIUB36sK55LktGUStgcbSiaAnL1wadu -2. **Alice**: Test account for the cosmwasm package that can run in parallel with faucet without sequence conflicts
- enlist hip relief stomach skate base shallow young switch frequent cry park
- Address 0: cosmos14qemq0vw6y3gc3u3e0aty2e764u4gs5le3hada
- Address 1: cosmos1hhg2rlu9jscacku2wwckws7932qqqu8x3gfgw0
- Address 2: cosmos1xv9tklw7d82sezh9haa573wufgy59vmwe6xxe5
- Address 3: cosmos17yg9mssjenmc3jkqth6ulcwj9cxujrxxzezwta
- Address 4: cosmos1f7j7ryulwjfe9ljplvhtcaxa6wqgula3etktce
- Pubkey 0: A9cXhWb8ZpqCzkA8dQCPV29KdeRLV3rUYxrkHudLbQtS
- Pubkey 1: A4XluzvcUx0ViLF0DjYW5/noArGwpltDstoUUZo+g1b0
- Pubkey 2: A5TKr1NKc/MKRJ7+EHDD9PlzmGaPD/di/6hzZyBwxoy5
- Pubkey 3: A/HSABDUqMB2qDy+PA7fiuuuA+hfrco2VwwiThMiTzUx
- Pubkey 4: A7usTiqgqfxL/WKhoephDUSCHBQlLagtwI/qTmEteTRM -3. **Bob**: Test account (unused for now)
- remain fragile remove stamp quiz bus country dress critic mammal office need
- Address 0: cosmos1lvrwcvrqlc5ktzp2c4t22xgkx29q3y83lktgzl
- Address 1: cosmos1vkv9sfwaak76weyamqx0flmng2vuquxqcuqukh
- Address 2: cosmos106jwym4s9aujcmes26myzzwqsccw09sdm0v5au
- Address 3: cosmos1c7wpeen2uv8thayf7g8q2rgpm29clj0dgrdtzw
- Address 4: cosmos1mjxpv9ft30wer7ma7kwfxhm42l379xutplrdk6
- Pubkey 0: A0d/GxY+UALE+miWJP0qyq4/EayG1G6tsg24v+cbD6By
- Pubkey 1: Agqd6njsVEQD1CR+F2aqEb8hil5NXZ06mjKgetaNC12t
- Pubkey 2: A6e9ElvKaM0DKWh1bIdK3bgB14dyEDgIXYMA0Lbs1GoQ
- Pubkey 3: AkAK5PQaucieWMb0+tTRY01feYI+upRnoNK556eD0Ibb
- Pubkey 4: A5HMVEAJsupdQWItbZv5Z1xZifDixQi6tjU/hJpZY1bF -4. **Unused**: for testing account state; this account never changes balances or sequences
- oyster design unusual machine spread century engine gravity focus cave carry slot
- ArkCaFUJ/IH+vKBmNRCdUVl3mCAhbopk9jjW4Ko4OfRQ
- cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u -5. **Guest**: account for manual testing
- degree tackle suggest window test behind mesh extra cover prepare oak script
- Am/+YV0LaeqQPu7BDJuDHV7J8y68ptkGs10YS+9s71Nq
- cosmos17d0jcz59jf68g52vq38tuuncmwwjk42u6mcxej -6. **Ledger**: accounts for Ledger based demos and tests
- example indicate trick cereal hub fix civil host kiss version bird dash
- Address 0: cosmos1p6xs63q4g7np99ttv5nd3yzkt8n4qxa47w8aea
- Address 1: cosmos1meeu3jl268txxytwmmrsljk8rawh6n2majstn2
- Address 2: cosmos1cak6lnpfxs035xd88sq8e4zujsm8g2g97dxu5c
- Address 3: cosmos1x3x8kyypx8z6q7fx3gw65x29mhl5gg8qp4ynlr
- Address 4: cosmos18c27m2rj4lg74md03ujralvt562c097n8zpdf9
- Address 5: cosmos1q2y53e6x7s5mlddtd2qkcjr3nwr4dszv6fr9rt
- Address 6: cosmos1paa2gstlk7c98n27dw2g6tp6fyqvf32mm67qz3
- Address 7: cosmos1rvxjd8k6xvssz2eerfzemvat35pttfgr67yyzd
- Address 8: cosmos12zejt8d9xl70jd2333p4p265m2nr9h8gsaewk0
- Address 9: cosmos1exctm2036jtwyc9v3ftqfzmgnv9tdhj26v87uh
- Address 10: cosmos1f3pws3ztnp3s4nn5zxqdrl9vlqv5avkqmlrus4
- Pubkey 0: A66JoCNaNSXDsyj4qW7JgqXPTz5rOnfE6EKEArf4jJEK
- Pubkey 1: AtvmGuZvEN3NwL05BQdxl3XygUf+Vl/930fhFMt1HTyU
- Pubkey 2: A58dfmfVoKoTCteEzTHBC0OLJIBgzejGDVVEb8YW9vtJ
- Pubkey 3: A1wA01EixwcWJkdhI69ckGuQDX0NimhLCYdrQCegkOJF
- Pubkey 4: A9juq+VbP26qtVh71ANlwwJQ+ABTWIyHEKYrVwjmbYE6
- Pubkey 5: Ar4VUqiRYl75+TF3AExX8at3deeLj2O9mNMtBq2aVpym
- Pubkey 6: Ak/JoSXzu6+Rp2W0wT6CqfZfzlDOwebl7xVF/zmKX99Y
- Pubkey 7: AtmLZZGHeCiNuroPAzBK2NKeXKT68SwioLj4I8Oj35Mn
- Pubkey 8: AuaUr9GEMUBKeZrJD/dv9QL/zJmMxX7OA/sjRrvBFXS2
- Pubkey 9: AiV5uMzvzoD7hlF+GhYuRCnf8tP+0AlPMbtfVoYv3InI
- Pubkey 10: A2ZnLEcbpyjS30H5UF1vezq29aBcT9oo5EARATIW9Cpj diff --git a/scripts/launchpad/cli.sh b/scripts/launchpad/cli.sh deleted file mode 100755 index 42afceeaa3..0000000000 --- a/scripts/launchpad/cli.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -set -o errexit -o nounset -o pipefail -command -v shellcheck >/dev/null && shellcheck "$0" - -SCRIPT_DIR="$(realpath "$(dirname "$0")")" -# shellcheck source=./env -# shellcheck disable=SC1091 -source "$SCRIPT_DIR"/env - -# TODO: make this run as UID? Does this matter? -HOME_DIR="/root" - -docker run \ - --rm \ - -it \ - --mount type=volume,source=launchpad_cli_data,target=/root/.wasmcli \ - -w "$HOME_DIR" \ - --env "HOME=$HOME_DIR" \ - --net "container:$CONTAINER_NAME" \ - "$REPOSITORY:$VERSION" \ - wasmcli "$@" diff --git a/scripts/launchpad/env b/scripts/launchpad/env deleted file mode 100644 index 93cfe42558..0000000000 --- a/scripts/launchpad/env +++ /dev/null @@ -1,5 +0,0 @@ -# Choose from https://hub.docker.com/r/cosmwasm/wasmd/tags -REPOSITORY="cosmwasm/wasmd" -VERSION="v0.11.1" - -CONTAINER_NAME="launchpad" diff --git a/scripts/launchpad/generate_template.sh b/scripts/launchpad/generate_template.sh deleted file mode 100755 index 15caedbfc8..0000000000 --- a/scripts/launchpad/generate_template.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash -set -o errexit -o nounset -o pipefail -command -v shellcheck >/dev/null && shellcheck "$0" - -SCRIPT_DIR="$(realpath "$(dirname "$0")")" -# shellcheck source=./env -# shellcheck disable=SC1091 -source "$SCRIPT_DIR"/env - -rm -rf "$SCRIPT_DIR/template" -mkdir "$SCRIPT_DIR/template" - -# The usage of the accounts below is documented in README.md of this directory -docker run --rm \ - -e PASSWORD=my-secret-password \ - --mount type=bind,source="$SCRIPT_DIR/template",target=/root \ - "$REPOSITORY:$VERSION" \ - ./setup_wasmd.sh \ - cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6 cosmos10dyr9899g6t0pelew4nvf4j5c3jcgv0r73qga5 cosmos1xy4yqngt0nlkdcenxymg8tenrghmek4nmqm28k cosmos142u9fgcjdlycfcez3lw8x6x5h7rfjlnfhpw2lx cosmos1hsm76p4ahyhl5yh3ve9ur49r5kemhp2r0dcjvx \ - cosmos14qemq0vw6y3gc3u3e0aty2e764u4gs5le3hada cosmos1hhg2rlu9jscacku2wwckws7932qqqu8x3gfgw0 cosmos1xv9tklw7d82sezh9haa573wufgy59vmwe6xxe5 cosmos17yg9mssjenmc3jkqth6ulcwj9cxujrxxzezwta cosmos1f7j7ryulwjfe9ljplvhtcaxa6wqgula3etktce \ - cosmos1lvrwcvrqlc5ktzp2c4t22xgkx29q3y83lktgzl cosmos1vkv9sfwaak76weyamqx0flmng2vuquxqcuqukh cosmos106jwym4s9aujcmes26myzzwqsccw09sdm0v5au cosmos1c7wpeen2uv8thayf7g8q2rgpm29clj0dgrdtzw cosmos1mjxpv9ft30wer7ma7kwfxhm42l379xutplrdk6 \ - cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u \ - cosmos17d0jcz59jf68g52vq38tuuncmwwjk42u6mcxej \ - cosmos1p6xs63q4g7np99ttv5nd3yzkt8n4qxa47w8aea cosmos1meeu3jl268txxytwmmrsljk8rawh6n2majstn2 cosmos1cak6lnpfxs035xd88sq8e4zujsm8g2g97dxu5c cosmos1x3x8kyypx8z6q7fx3gw65x29mhl5gg8qp4ynlr cosmos18c27m2rj4lg74md03ujralvt562c097n8zpdf9 cosmos1q2y53e6x7s5mlddtd2qkcjr3nwr4dszv6fr9rt cosmos1paa2gstlk7c98n27dw2g6tp6fyqvf32mm67qz3 cosmos1rvxjd8k6xvssz2eerfzemvat35pttfgr67yyzd cosmos12zejt8d9xl70jd2333p4p265m2nr9h8gsaewk0 cosmos1exctm2036jtwyc9v3ftqfzmgnv9tdhj26v87uh cosmos1f3pws3ztnp3s4nn5zxqdrl9vlqv5avkqmlrus4 - -# The ./template folder is created by the docker daemon's user (root on Linux, current user -# when using Docker Desktop on macOS), let's make it ours if needed -if [ ! -x "$SCRIPT_DIR/template/.wasmd/config/gentx" ]; then - sudo chown -R "$(id -u):$(id -g)" "$SCRIPT_DIR/template" -fi - -function inline_jq() { - IN_OUT_PATH="$1" - shift - TMP_DIR=$(mktemp -d "${TMPDIR:-/tmp}/inline_jq.XXXXXXXXX") - TMP_FILE="$TMP_DIR/$(basename "$IN_OUT_PATH")" - jq "$@" <"$IN_OUT_PATH" >"$TMP_FILE" - if ! mv "$TMP_FILE" "$IN_OUT_PATH"; then - echo >&2 "Temp file '$TMP_FILE' could not be deleted. If it contains sensitive data, you might want to delete it manually." - exit 3 - fi -} - -inline_jq "$SCRIPT_DIR/template/.wasmd/config/genesis.json" -S diff --git a/scripts/launchpad/init.sh b/scripts/launchpad/init.sh deleted file mode 100755 index ecf47e006a..0000000000 --- a/scripts/launchpad/init.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -set -o errexit -o nounset -o pipefail -command -v shellcheck >/dev/null && shellcheck "$0" - -echo "Waiting for blockchain and REST server to be available ..." -timeout 60 bash -c "until curl -s http://localhost:1317/node_info > /dev/null; do sleep 0.5; done" -# The chain is unreliable in the first second of its existence (https://gist.github.com/webmaster128/8175692d4af5e6c572fddda7a9ef437c) -sleep 1 -echo "Okay, thank you for your patience." - -SCRIPT_DIR="$(realpath "$(dirname "$0")")" - -# -# Cosmos SDK init -# -"$SCRIPT_DIR/send_first.js" diff --git a/scripts/launchpad/manual_start.sh b/scripts/launchpad/manual_start.sh deleted file mode 100755 index 4bfa00c13e..0000000000 --- a/scripts/launchpad/manual_start.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash -set -o errexit -o nounset -o pipefail -command -v shellcheck >/dev/null && shellcheck "$0" - -## This is like start.sh but using local binaries, not docker images -SCRIPT_DIR="$(realpath "$(dirname "$0")")" - -TMP_DIR=$(mktemp -d "${TMPDIR:-/tmp}/gaia.XXXXXXXXX") -chmod 777 "$TMP_DIR" -echo "Using temporary dir $TMP_DIR" -WASMD_LOGFILE="$TMP_DIR/wasmd.log" -REST_SERVER_LOGFILE="$TMP_DIR/rest-server.log" - -# move the template into our temporary home -cp -r "$SCRIPT_DIR"/template/.wasm* "$TMP_DIR" - -wasmd start \ - --home "$TMP_DIR/.wasmd" \ - --trace \ - --rpc.laddr tcp://0.0.0.0:26657 \ - >"$WASMD_LOGFILE" & - -echo "wasmd running and logging into $WASMD_LOGFILE" - -sleep 10 -cat "$WASMD_LOGFILE" - -wasmcli rest-server \ - --home "$TMP_DIR/.wasmcli" \ - --node tcp://localhost:26657 \ - --trust-node \ - --laddr tcp://0.0.0.0:1317 \ - >"$REST_SERVER_LOGFILE" & - -echo "rest server running on http://localhost:1317 and logging into $REST_SERVER_LOGFILE" - -# Debug rest server start -sleep 3 -cat "$REST_SERVER_LOGFILE" - -tail -f "$WASMD_LOGFILE" diff --git a/scripts/launchpad/priv_validator_state.template.json b/scripts/launchpad/priv_validator_state.template.json deleted file mode 100644 index 0967ef424b..0000000000 --- a/scripts/launchpad/priv_validator_state.template.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/scripts/launchpad/send_first.js b/scripts/launchpad/send_first.js deleted file mode 100755 index 1966ff460b..0000000000 --- a/scripts/launchpad/send_first.js +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env -S yarn node - -/* eslint-disable @typescript-eslint/naming-convention */ -const { coins, Secp256k1HdWallet } = require("@cosmjs/amino"); -const { Random } = require("@cosmjs/crypto"); -const { Bech32 } = require("@cosmjs/encoding"); -const { SigningCosmosClient, assertIsBroadcastTxSuccess } = require("@cosmjs/launchpad"); - -const httpUrl = "http://localhost:1317"; -const faucet = { - mnemonic: - "economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone", - address0: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", -}; - -async function main() { - const wallet = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic); - const client = new SigningCosmosClient(httpUrl, faucet.address0, wallet); - const recipient = Bech32.encode("cosmos", Random.getBytes(20)); - const amount = coins(226644, "ucosm"); - const memo = "Ensure chain has my pubkey"; - const sendResult = await client.sendTokens(recipient, amount, memo); - assertIsBroadcastTxSuccess(sendResult); -} - -main().then( - () => process.exit(0), - (error) => { - console.error(error); - process.exit(1); - }, -); diff --git a/scripts/launchpad/start.sh b/scripts/launchpad/start.sh deleted file mode 100755 index 0c753e2dc1..0000000000 --- a/scripts/launchpad/start.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/bash -set -o errexit -o nounset -o pipefail -command -v shellcheck >/dev/null && shellcheck "$0" - -# Please keep this in sync with the Ports overview in HACKING.md -# Tendermint port (26657) and p2p port (26656) are not exposed since we don't need them for testing -LCD_API_PORT_GUEST="1317" -LCD_API_PORT_HOST="1317" - -SCRIPT_DIR="$(realpath "$(dirname "$0")")" -# shellcheck source=./env -# shellcheck disable=SC1091 -source "$SCRIPT_DIR"/env - -TMP_DIR=$(mktemp -d "${TMPDIR:-/tmp}/wasmd.XXXXXXXXX") -chmod 777 "$TMP_DIR" -echo "Using temporary dir $TMP_DIR" -WASMD_LOGFILE="$TMP_DIR/wasmd.log" -REST_SERVER_LOGFILE="$TMP_DIR/rest-server.log" - -# Use a fresh volume for every start -docker volume rm -f launchpad_data - -# This starts up wasmd -docker run --rm \ - --name "$CONTAINER_NAME" \ - -p "$LCD_API_PORT_HOST":"$LCD_API_PORT_GUEST" \ - --mount type=bind,source="$SCRIPT_DIR/template",target=/template \ - --mount type=volume,source=launchpad_data,target=/root \ - "$REPOSITORY:$VERSION" \ - ./run_wasmd.sh /template \ - >"$WASMD_LOGFILE" & - -echo "wasmd running and logging into $WASMD_LOGFILE" - -# Debug chain start -# sleep 3 && cat "$WASMD_LOGFILE" - -# Use a large timeout because of potentially long image download in `docker run` -if ! timeout 180 bash -c "until [ \"\$( docker container inspect -f '{{.State.Status}}' \"$CONTAINER_NAME\" 2> /dev/null )\" = \"running\" ]; do sleep 0.5; done"; then - echo "Container named '$CONTAINER_NAME' not running. We cannot continue." \ - "This can happen when 'docker run' needs too long to download and start." \ - "It might be worth retrying this step once the image is in the local docker cache." - docker kill "$CONTAINER_NAME" - exit 1 -fi - -docker exec "$CONTAINER_NAME" \ - wasmcli rest-server \ - --node tcp://localhost:26657 \ - --trust-node \ - --unsafe-cors \ - --laddr "tcp://0.0.0.0:$LCD_API_PORT_GUEST" \ - >"$REST_SERVER_LOGFILE" & - -echo "rest server running on http://localhost:$LCD_API_PORT_HOST and logging into $REST_SERVER_LOGFILE" - -if [ -n "${CI:-}" ]; then - # Give process some time to come alive. No idea why this helps. Needed for CI. - sleep 0.5 - - # Follow the logs in CI's background job - tail -f "$WASMD_LOGFILE" -fi - -# Debug rest server start -# sleep 3 && cat "$REST_SERVER_LOGFILE" diff --git a/scripts/launchpad/stop.sh b/scripts/launchpad/stop.sh deleted file mode 100755 index e29cbac1eb..0000000000 --- a/scripts/launchpad/stop.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -set -o errexit -o nounset -o pipefail -command -v shellcheck >/dev/null && shellcheck "$0" - -SCRIPT_DIR="$(realpath "$(dirname "$0")")" -# shellcheck source=./env -# shellcheck disable=SC1091 -source "$SCRIPT_DIR"/env - -echo "Killing Cosmos container..." -docker container kill "$CONTAINER_NAME" diff --git a/scripts/launchpad/template/.wasmcli/cosmos1yfkkk04ve8a0sugj4fe6q6zxuvmvza8r5fhf0s.address b/scripts/launchpad/template/.wasmcli/cosmos1yfkkk04ve8a0sugj4fe6q6zxuvmvza8r5fhf0s.address deleted file mode 100644 index ccf00c308c..0000000000 --- a/scripts/launchpad/template/.wasmcli/cosmos1yfkkk04ve8a0sugj4fe6q6zxuvmvza8r5fhf0s.address +++ /dev/null @@ -1 +0,0 @@ -eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjcmVhdGVkIjoiMjAyMC0xMC0wOCAxMDoxODoxMS41Nzk5MTc2ICswMDAwIFVUQyBtPSswLjIwODQ1NTkwMSIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjgxOTIsInAycyI6IlBtZXB4NExXMlk4bFM2cXEifQ.NgxU8Oa0GROusbronyRkzPRHIngrFnnfNKxCVCYtsQX6rhKU8eQrig.SXfPznlVJlsFGvPi.jSjG-b9uurXrTRdXHbCi14O_XwOV-ob6cRbmWNwIcSxoib2X-zByj20XRyHzJbpJ2S7CBq-Xop0tiY6x3AIgrUSlpMdUYxEr1pHsB1pVtWVJ9QNym3KN4DFL0zDrIXKQGZZLSZddfTTe9HP7iVqApqA2uK0DSMVEAUYLe_GWqpgaIkbrZYO1YUhCaVWgZkXO7d9OLknmWtIrhE5SpC0evSkbsWlfbPulsYhEflxQA5d77-dogshyys0F4h-L410.GudaoqjS4Tzj8E4JwTXM9Q \ No newline at end of file diff --git a/scripts/launchpad/template/.wasmcli/keyhash b/scripts/launchpad/template/.wasmcli/keyhash deleted file mode 100755 index 2f80e64284..0000000000 --- a/scripts/launchpad/template/.wasmcli/keyhash +++ /dev/null @@ -1 +0,0 @@ -$2a$10$YzaMyzpLWAscnjy9KQ7ujORZSelnaBAVF9WpTjrG/7L2ylc9iaEjC \ No newline at end of file diff --git a/scripts/launchpad/template/.wasmcli/validator.info b/scripts/launchpad/template/.wasmcli/validator.info deleted file mode 100644 index 56941699f4..0000000000 --- a/scripts/launchpad/template/.wasmcli/validator.info +++ /dev/null @@ -1 +0,0 @@ -eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjcmVhdGVkIjoiMjAyMC0xMC0wOCAxMDoxODoxMS41NTkzMjQgKzAwMDAgVVRDIG09KzAuMTg3ODYwODAxIiwiZW5jIjoiQTI1NkdDTSIsInAyYyI6ODE5MiwicDJzIjoiV19XUWlpakllT2VNakNGSiJ9.yszrRkA7Z1aAjKwPPyQebxsMEB57B_OXryuMuZnR2cIeAfchu5x4Rg.W4qQ-Kc7TkvjH7Gr.yPYQV6Wlb-M_spbO5o2CTYMwdJUxWkUpEEZ9a72zoR3AzH3AKdv34vPHDB5bYbNXdt-f0qPWnpr2B-UsoBXSIbpY4ZjD68ry2Ct6X9cMZMN1XOCXqpN4qBG7W8Il_qcIKVMt_S9Ct1utMwhnht7uvItW3AQmp6CIj35f4mk8R3U5u3pSczI8gnuiAhrVWgjWghznsVLG2fArOs1akGIMJaQm7FaldU7gsvW_vOwD8h9zVnAGypmI37J1XDJWZVhNQAupOdaIWtzJkJSW8cEAjTIF9GhA_ysLk11nw5jXc8NR6r9Bqk3sfDph0_NFC5uSmAUCqMuGePdjmgPaQWBlmRkOzG4AXB6_PI-D83ZtRZ215PPe.UyvabgVuUaaHQWcHigiK2g \ No newline at end of file diff --git a/scripts/launchpad/template/.wasmd/config/app.toml b/scripts/launchpad/template/.wasmd/config/app.toml deleted file mode 100644 index 2f5408824a..0000000000 --- a/scripts/launchpad/template/.wasmd/config/app.toml +++ /dev/null @@ -1,36 +0,0 @@ -# This is a TOML config file. -# For more information, see https://github.com/toml-lang/toml - -##### main base config options ##### - -# The minimum gas prices a validator is willing to accept for processing a -# transaction. A transaction's fees must meet the minimum of any denomination -# specified in this config (e.g. 0.25token1;0.0001token2). -minimum-gas-prices = "" - -# default: the last 100 states are kept in addition to every 500th state; pruning at 10 block intervals -# nothing: all historic states will be saved, nothing will be deleted (i.e. archiving node) -# everything: all saved states will be deleted, storing only the current state; pruning at 10 block intervals -# custom: allow pruning options to be manually specified through 'pruning-keep-recent', 'pruning-keep-every', and 'pruning-interval' -pruning = "default" - -# These are applied if and only if the pruning strategy is custom. -pruning-keep-recent = "0" -pruning-keep-every = "0" -pruning-interval = "0" - -# HaltHeight contains a non-zero block height at which a node will gracefully -# halt and shutdown that can be used to assist upgrades and testing. -# -# Note: Commitment of state will be attempted on the corresponding block. -halt-height = 0 - -# HaltTime contains a non-zero minimum block time (in Unix seconds) at which -# a node will gracefully halt and shutdown that can be used to assist upgrades -# and testing. -# -# Note: Commitment of state will be attempted on the corresponding block. -halt-time = 0 - -# InterBlockCache enables inter-block caching. -inter-block-cache = true diff --git a/scripts/launchpad/template/.wasmd/config/config.toml b/scripts/launchpad/template/.wasmd/config/config.toml deleted file mode 100644 index 1fe3ac843d..0000000000 --- a/scripts/launchpad/template/.wasmd/config/config.toml +++ /dev/null @@ -1,335 +0,0 @@ -# This is a TOML config file. -# For more information, see https://github.com/toml-lang/toml - -# NOTE: Any path below can be absolute (e.g. "/var/myawesomeapp/data") or -# relative to the home directory (e.g. "data"). The home directory is -# "$HOME/.tendermint" by default, but could be changed via $TMHOME env variable -# or --home cmd flag. - -##### main base config options ##### - -# TCP or UNIX socket address of the ABCI application, -# or the name of an ABCI application compiled in with the Tendermint binary -proxy_app = "tcp://127.0.0.1:26658" - -# A custom human readable name for this node -moniker = "node001" - -# If this node is many blocks behind the tip of the chain, FastSync -# allows them to catchup quickly by downloading blocks in parallel -# and verifying their commits -fast_sync = true - -# Database backend: goleveldb | cleveldb | boltdb | rocksdb -# * goleveldb (github.com/syndtr/goleveldb - most popular implementation) -# - pure go -# - stable -# * cleveldb (uses levigo wrapper) -# - fast -# - requires gcc -# - use cleveldb build tag (go build -tags cleveldb) -# * boltdb (uses etcd's fork of bolt - github.com/etcd-io/bbolt) -# - EXPERIMENTAL -# - may be faster is some use-cases (random reads - indexer) -# - use boltdb build tag (go build -tags boltdb) -# * rocksdb (uses github.com/tecbot/gorocksdb) -# - EXPERIMENTAL -# - requires gcc -# - use rocksdb build tag (go build -tags rocksdb) -db_backend = "goleveldb" - -# Database directory -db_dir = "data" - -# Output level for logging, including package level options -log_level = "main:info,state:info,*:error" - -# Output format: 'plain' (colored text) or 'json' -log_format = "plain" - -##### additional base config options ##### - -# Path to the JSON file containing the initial validator set and other meta data -genesis_file = "config/genesis.json" - -# Path to the JSON file containing the private key to use as a validator in the consensus protocol -priv_validator_key_file = "config/priv_validator_key.json" - -# Path to the JSON file containing the last sign state of a validator -priv_validator_state_file = "data/priv_validator_state.json" - -# TCP or UNIX socket address for Tendermint to listen on for -# connections from an external PrivValidator process -priv_validator_laddr = "" - -# Path to the JSON file containing the private key to use for node authentication in the p2p protocol -node_key_file = "config/node_key.json" - -# Mechanism to connect to the ABCI application: socket | grpc -abci = "socket" - -# TCP or UNIX socket address for the profiling server to listen on -prof_laddr = "localhost:6060" - -# If true, query the ABCI app on connecting to a new peer -# so the app can decide if we should keep the connection or not -filter_peers = false - -##### advanced configuration options ##### - -##### rpc server configuration options ##### -[rpc] - -# TCP or UNIX socket address for the RPC server to listen on -laddr = "tcp://127.0.0.1:26657" - -# A list of origins a cross-domain request can be executed from -# Default value '[]' disables cors support -# Use '["*"]' to allow any origin -cors_allowed_origins = [] - -# A list of methods the client is allowed to use with cross-domain requests -cors_allowed_methods = ["HEAD", "GET", "POST", ] - -# A list of non simple headers the client is allowed to use with cross-domain requests -cors_allowed_headers = ["Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time", ] - -# TCP or UNIX socket address for the gRPC server to listen on -# NOTE: This server only supports /broadcast_tx_commit -grpc_laddr = "" - -# Maximum number of simultaneous connections. -# Does not include RPC (HTTP&WebSocket) connections. See max_open_connections -# If you want to accept a larger number than the default, make sure -# you increase your OS limits. -# 0 - unlimited. -# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files} -# 1024 - 40 - 10 - 50 = 924 = ~900 -grpc_max_open_connections = 900 - -# Activate unsafe RPC commands like /dial_seeds and /unsafe_flush_mempool -unsafe = false - -# Maximum number of simultaneous connections (including WebSocket). -# Does not include gRPC connections. See grpc_max_open_connections -# If you want to accept a larger number than the default, make sure -# you increase your OS limits. -# 0 - unlimited. -# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files} -# 1024 - 40 - 10 - 50 = 924 = ~900 -max_open_connections = 900 - -# Maximum number of unique clientIDs that can /subscribe -# If you're using /broadcast_tx_commit, set to the estimated maximum number -# of broadcast_tx_commit calls per block. -max_subscription_clients = 100 - -# Maximum number of unique queries a given client can /subscribe to -# If you're using GRPC (or Local RPC client) and /broadcast_tx_commit, set to -# the estimated # maximum number of broadcast_tx_commit calls per block. -max_subscriptions_per_client = 5 - -# How long to wait for a tx to be committed during /broadcast_tx_commit. -# WARNING: Using a value larger than 10s will result in increasing the -# global HTTP write timeout, which applies to all connections and endpoints. -# See https://github.com/tendermint/tendermint/issues/3435 -timeout_broadcast_tx_commit = "10s" - -# Maximum size of request body, in bytes -max_body_bytes = 1000000 - -# Maximum size of request header, in bytes -max_header_bytes = 1048576 - -# The path to a file containing certificate that is used to create the HTTPS server. -# Migth be either absolute path or path related to tendermint's config directory. -# If the certificate is signed by a certificate authority, -# the certFile should be the concatenation of the server's certificate, any intermediates, -# and the CA's certificate. -# NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server. -# Otherwise, HTTP server is run. -tls_cert_file = "" - -# The path to a file containing matching private key that is used to create the HTTPS server. -# Migth be either absolute path or path related to tendermint's config directory. -# NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server. -# Otherwise, HTTP server is run. -tls_key_file = "" - -##### peer to peer configuration options ##### -[p2p] - -# Address to listen for incoming connections -laddr = "tcp://0.0.0.0:26656" - -# Address to advertise to peers for them to dial -# If empty, will use the same port as the laddr, -# and will introspect on the listener or use UPnP -# to figure out the address. -external_address = "" - -# Comma separated list of seed nodes to connect to -seeds = "" - -# Comma separated list of nodes to keep persistent connections to -persistent_peers = "" - -# UPNP port forwarding -upnp = false - -# Path to address book -addr_book_file = "config/addrbook.json" - -# Set true for strict address routability rules -# Set false for private or local networks -addr_book_strict = true - -# Maximum number of inbound peers -max_num_inbound_peers = 40 - -# Maximum number of outbound peers to connect to, excluding persistent peers -max_num_outbound_peers = 10 - -# List of node IDs, to which a connection will be (re)established ignoring any existing limits -unconditional_peer_ids = "" - -# Maximum pause when redialing a persistent peer (if zero, exponential backoff is used) -persistent_peers_max_dial_period = "0s" - -# Time to wait before flushing messages out on the connection -flush_throttle_timeout = "100ms" - -# Maximum size of a message packet payload, in bytes -max_packet_msg_payload_size = 1024 - -# Rate at which packets can be sent, in bytes/second -send_rate = 5120000 - -# Rate at which packets can be received, in bytes/second -recv_rate = 5120000 - -# Set true to enable the peer-exchange reactor -pex = true - -# Seed mode, in which node constantly crawls the network and looks for -# peers. If another node asks it for addresses, it responds and disconnects. -# -# Does not work if the peer-exchange reactor is disabled. -seed_mode = false - -# Comma separated list of peer IDs to keep private (will not be gossiped to other peers) -private_peer_ids = "" - -# Toggle to disable guard against peers connecting from the same ip. -allow_duplicate_ip = false - -# Peer connection configuration. -handshake_timeout = "20s" -dial_timeout = "3s" - -##### mempool configuration options ##### -[mempool] - -recheck = true -broadcast = true -wal_dir = "" - -# Maximum number of transactions in the mempool -size = 5000 - -# Limit the total size of all txs in the mempool. -# This only accounts for raw transactions (e.g. given 1MB transactions and -# max_txs_bytes=5MB, mempool will only accept 5 transactions). -max_txs_bytes = 1073741824 - -# Size of the cache (used to filter transactions we saw earlier) in transactions -cache_size = 10000 - -# Maximum size of a single transaction. -# NOTE: the max size of a tx transmitted over the network is {max_tx_bytes} + {amino overhead}. -max_tx_bytes = 1048576 - -##### fast sync configuration options ##### -[fastsync] - -# Fast Sync version to use: -# 1) "v0" (default) - the legacy fast sync implementation -# 2) "v1" - refactor of v0 version for better testability -# 3) "v2" - refactor of v1 version for better usability -version = "v0" - -##### consensus configuration options ##### -[consensus] - -wal_file = "data/cs.wal/wal" - -timeout_propose = "300ms" -timeout_propose_delta = "100ms" -timeout_prevote = "300ms" -timeout_prevote_delta = "100ms" -timeout_precommit = "300ms" -timeout_precommit_delta = "100ms" -timeout_commit = "1s" - -# Make progress as soon as we have all the precommits (as if TimeoutCommit = 0) -skip_timeout_commit = false - -# EmptyBlocks mode and possible interval between empty blocks -create_empty_blocks = true -create_empty_blocks_interval = "0s" - -# Reactor sleep duration parameters -peer_gossip_sleep_duration = "100ms" -peer_query_maj23_sleep_duration = "2s" - -##### transactions indexer configuration options ##### -[tx_index] - -# What indexer to use for transactions -# -# Options: -# 1) "null" -# 2) "kv" (default) - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend). -indexer = "kv" - -# Comma-separated list of compositeKeys to index (by default the only key is "tx.hash") -# Remember that Event has the following structure: type.key -# type: [ -# key: value, -# ... -# ] -# -# You can also index transactions by height by adding "tx.height" key here. -# -# It's recommended to index only a subset of keys due to possible memory -# bloat. This is, of course, depends on the indexer's DB and the volume of -# transactions. -index_keys = "" - -# When set to true, tells indexer to index all compositeKeys (predefined keys: -# "tx.hash", "tx.height" and all keys from DeliverTx responses). -# -# Note this may be not desirable (see the comment above). IndexKeys has a -# precedence over IndexAllKeys (i.e. when given both, IndexKeys will be -# indexed). -index_all_keys = true - -##### instrumentation configuration options ##### -[instrumentation] - -# When true, Prometheus metrics are served under /metrics on -# PrometheusListenAddr. -# Check out the documentation for the list of available metrics. -prometheus = false - -# Address to listen for Prometheus collector(s) connections -prometheus_listen_addr = ":26660" - -# Maximum number of simultaneous connections. -# If you want to accept a larger number than the default, make sure -# you increase your OS limits. -# 0 - unlimited. -max_open_connections = 3 - -# Instrumentation namespace -namespace = "tendermint" diff --git a/scripts/launchpad/template/.wasmd/config/genesis.json b/scripts/launchpad/template/.wasmd/config/genesis.json deleted file mode 100644 index dc116a2c37..0000000000 --- a/scripts/launchpad/template/.wasmd/config/genesis.json +++ /dev/null @@ -1,746 +0,0 @@ -{ - "app_hash": "", - "app_state": { - "auth": { - "accounts": [ - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos1yfkkk04ve8a0sugj4fe6q6zxuvmvza8r5fhf0s", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos10dyr9899g6t0pelew4nvf4j5c3jcgv0r73qga5", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos1xy4yqngt0nlkdcenxymg8tenrghmek4nmqm28k", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos142u9fgcjdlycfcez3lw8x6x5h7rfjlnfhpw2lx", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos1hsm76p4ahyhl5yh3ve9ur49r5kemhp2r0dcjvx", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos14qemq0vw6y3gc3u3e0aty2e764u4gs5le3hada", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos1hhg2rlu9jscacku2wwckws7932qqqu8x3gfgw0", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos1xv9tklw7d82sezh9haa573wufgy59vmwe6xxe5", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos17yg9mssjenmc3jkqth6ulcwj9cxujrxxzezwta", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos1f7j7ryulwjfe9ljplvhtcaxa6wqgula3etktce", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos1lvrwcvrqlc5ktzp2c4t22xgkx29q3y83lktgzl", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos1vkv9sfwaak76weyamqx0flmng2vuquxqcuqukh", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos106jwym4s9aujcmes26myzzwqsccw09sdm0v5au", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos1c7wpeen2uv8thayf7g8q2rgpm29clj0dgrdtzw", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos1mjxpv9ft30wer7ma7kwfxhm42l379xutplrdk6", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos17d0jcz59jf68g52vq38tuuncmwwjk42u6mcxej", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos1p6xs63q4g7np99ttv5nd3yzkt8n4qxa47w8aea", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos1meeu3jl268txxytwmmrsljk8rawh6n2majstn2", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos1cak6lnpfxs035xd88sq8e4zujsm8g2g97dxu5c", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos1x3x8kyypx8z6q7fx3gw65x29mhl5gg8qp4ynlr", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos18c27m2rj4lg74md03ujralvt562c097n8zpdf9", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos1q2y53e6x7s5mlddtd2qkcjr3nwr4dszv6fr9rt", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos1paa2gstlk7c98n27dw2g6tp6fyqvf32mm67qz3", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos1rvxjd8k6xvssz2eerfzemvat35pttfgr67yyzd", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos12zejt8d9xl70jd2333p4p265m2nr9h8gsaewk0", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos1exctm2036jtwyc9v3ftqfzmgnv9tdhj26v87uh", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - }, - { - "type": "cosmos-sdk/Account", - "value": { - "account_number": "0", - "address": "cosmos1f3pws3ztnp3s4nn5zxqdrl9vlqv5avkqmlrus4", - "coins": [ - { - "amount": "1000000000", - "denom": "ucosm" - }, - { - "amount": "1000000000", - "denom": "ustake" - } - ], - "public_key": null, - "sequence": "0" - } - } - ], - "params": { - "max_memo_characters": "256", - "sig_verify_cost_ed25519": "590", - "sig_verify_cost_secp256k1": "1000", - "tx_sig_limit": "7", - "tx_size_cost_per_byte": "10" - } - }, - "bank": { - "send_enabled": true - }, - "crisis": { - "constant_fee": { - "amount": "1000", - "denom": "ustake" - } - }, - "distribution": { - "delegator_starting_infos": [], - "delegator_withdraw_infos": [], - "fee_pool": { - "community_pool": [] - }, - "outstanding_rewards": [], - "params": { - "base_proposer_reward": "0.010000000000000000", - "bonus_proposer_reward": "0.040000000000000000", - "community_tax": "0.020000000000000000", - "withdraw_addr_enabled": true - }, - "previous_proposer": "", - "validator_accumulated_commissions": [], - "validator_current_rewards": [], - "validator_historical_rewards": [], - "validator_slash_events": [] - }, - "evidence": { - "evidence": [], - "params": { - "max_evidence_age": "120000000000" - } - }, - "genutil": { - "gentxs": [ - { - "type": "cosmos-sdk/StdTx", - "value": { - "fee": { - "amount": [], - "gas": "200000" - }, - "memo": "aaf7eb061829f888de02b377eeb64009317c330d@172.17.0.2:26656", - "msg": [ - { - "type": "cosmos-sdk/MsgCreateValidator", - "value": { - "commission": { - "max_change_rate": "0.010000000000000000", - "max_rate": "0.200000000000000000", - "rate": "0.100000000000000000" - }, - "delegator_address": "cosmos1yfkkk04ve8a0sugj4fe6q6zxuvmvza8r5fhf0s", - "description": { - "details": "", - "identity": "", - "moniker": "node001", - "security_contact": "", - "website": "" - }, - "min_self_delegation": "1", - "pubkey": "cosmosvalconspub1zcjduepqf62c9h86qqn4g9s4khcng86quanw8rn5mm6lf69c99vxff0302ksv2ljyl", - "validator_address": "cosmosvaloper1yfkkk04ve8a0sugj4fe6q6zxuvmvza8r3arurr", - "value": { - "amount": "250000000", - "denom": "ustake" - } - } - } - ], - "signatures": [ - { - "pub_key": { - "type": "tendermint/PubKeySecp256k1", - "value": "Atm7XWIgFRE+ONf4mOD15/1f8hst97O8efn8b6o2nP6Q" - }, - "signature": "nc7CR9iYk1QrQX/gRkBIXh2T2/7Os0IxegsFsVuZBL1pDO4KdzjyokuS2pNdxCiL3+v9pJqVsEJ2LVhSqwGqQQ==" - } - ] - } - } - ] - }, - "gov": { - "deposit_params": { - "max_deposit_period": "172800000000000", - "min_deposit": [ - { - "amount": "10000000", - "denom": "ustake" - } - ] - }, - "deposits": null, - "proposals": null, - "starting_proposal_id": "1", - "tally_params": { - "quorum": "0.334000000000000000", - "threshold": "0.500000000000000000", - "veto": "0.334000000000000000" - }, - "votes": null, - "voting_params": { - "voting_period": "172800000000000" - } - }, - "mint": { - "minter": { - "annual_provisions": "0.000000000000000000", - "inflation": "0.130000000000000000" - }, - "params": { - "blocks_per_year": "6311520", - "goal_bonded": "0.670000000000000000", - "inflation_max": "0.200000000000000000", - "inflation_min": "0.070000000000000000", - "inflation_rate_change": "0.130000000000000000", - "mint_denom": "ustake" - } - }, - "params": null, - "slashing": { - "missed_blocks": {}, - "params": { - "downtime_jail_duration": "600000000000", - "min_signed_per_window": "0.500000000000000000", - "signed_blocks_window": "100", - "slash_fraction_double_sign": "0.050000000000000000", - "slash_fraction_downtime": "0.010000000000000000" - }, - "signing_infos": {} - }, - "staking": { - "delegations": null, - "exported": false, - "last_total_power": "0", - "last_validator_powers": null, - "params": { - "bond_denom": "ustake", - "historical_entries": 0, - "max_entries": 7, - "max_validators": 100, - "unbonding_time": "1814400000000000" - }, - "redelegations": null, - "unbonding_delegations": null, - "validators": null - }, - "supply": { - "supply": [] - }, - "upgrade": {}, - "wasm": { - "params": { - "code_upload_access": { - "permission": "Everybody" - }, - "instantiate_default_permission": "Everybody" - } - } - }, - "chain_id": "testing", - "consensus_params": { - "block": { - "max_bytes": "22020096", - "max_gas": "-1", - "time_iota_ms": "1000" - }, - "evidence": { - "max_age_duration": "172800000000000", - "max_age_num_blocks": "100000" - }, - "validator": { - "pub_key_types": [ - "ed25519" - ] - } - }, - "genesis_time": "2020-10-08T10:18:11.2275025Z" -} diff --git a/scripts/launchpad/template/.wasmd/config/gentx/gentx-aaf7eb061829f888de02b377eeb64009317c330d.json b/scripts/launchpad/template/.wasmd/config/gentx/gentx-aaf7eb061829f888de02b377eeb64009317c330d.json deleted file mode 100644 index 1903c8a65e..0000000000 --- a/scripts/launchpad/template/.wasmd/config/gentx/gentx-aaf7eb061829f888de02b377eeb64009317c330d.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"cosmos-sdk/StdTx","value":{"msg":[{"type":"cosmos-sdk/MsgCreateValidator","value":{"description":{"moniker":"node001","identity":"","website":"","security_contact":"","details":""},"commission":{"rate":"0.100000000000000000","max_rate":"0.200000000000000000","max_change_rate":"0.010000000000000000"},"min_self_delegation":"1","delegator_address":"cosmos1yfkkk04ve8a0sugj4fe6q6zxuvmvza8r5fhf0s","validator_address":"cosmosvaloper1yfkkk04ve8a0sugj4fe6q6zxuvmvza8r3arurr","pubkey":"cosmosvalconspub1zcjduepqf62c9h86qqn4g9s4khcng86quanw8rn5mm6lf69c99vxff0302ksv2ljyl","value":{"denom":"ustake","amount":"250000000"}}}],"fee":{"amount":[],"gas":"200000"},"signatures":[{"pub_key":{"type":"tendermint/PubKeySecp256k1","value":"Atm7XWIgFRE+ONf4mOD15/1f8hst97O8efn8b6o2nP6Q"},"signature":"nc7CR9iYk1QrQX/gRkBIXh2T2/7Os0IxegsFsVuZBL1pDO4KdzjyokuS2pNdxCiL3+v9pJqVsEJ2LVhSqwGqQQ=="}],"memo":"aaf7eb061829f888de02b377eeb64009317c330d@172.17.0.2:26656"}} diff --git a/scripts/launchpad/template/.wasmd/config/node_key.json b/scripts/launchpad/template/.wasmd/config/node_key.json deleted file mode 100644 index 88f3f21123..0000000000 --- a/scripts/launchpad/template/.wasmd/config/node_key.json +++ /dev/null @@ -1 +0,0 @@ -{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"rWvxJlMCesZt37kdUbHXzN/KDkDfivFFXhoHMR82inld5iugvAJDG+0NDWC0wHmUUhZ91qk1WMpaQ0ugyJ0gmg=="}} \ No newline at end of file diff --git a/scripts/launchpad/template/.wasmd/config/priv_validator_key.json b/scripts/launchpad/template/.wasmd/config/priv_validator_key.json deleted file mode 100644 index 7e1c28013b..0000000000 --- a/scripts/launchpad/template/.wasmd/config/priv_validator_key.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "address": "DFAB9AAA1D25B928D788C79D9002B6C17C99D338", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "TpWC3PoAJ1QWFbXxNB9A52bjjnTe9fTouClYZKXxeq0=" - }, - "priv_key": { - "type": "tendermint/PrivKeyEd25519", - "value": "LL3jL3sv9AdrNkFBrc3QmucjDC7W/xVUWsBsjnfkIx5OlYLc+gAnVBYVtfE0H0DnZuOOdN719Oi4KVhkpfF6rQ==" - } -} \ No newline at end of file diff --git a/scripts/launchpad/template/.wasmd/data/priv_validator_state.json b/scripts/launchpad/template/.wasmd/data/priv_validator_state.json deleted file mode 100644 index ca3ad2f746..0000000000 --- a/scripts/launchpad/template/.wasmd/data/priv_validator_state.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "height": "0", - "round": "0", - "step": 0 -} \ No newline at end of file diff --git a/scripts/wasmd/env b/scripts/wasmd/env index 8e350f38db..bc58d87798 100644 --- a/scripts/wasmd/env +++ b/scripts/wasmd/env @@ -1,5 +1,5 @@ # Choose from https://hub.docker.com/r/cosmwasm/wasmd/tags REPOSITORY="cosmwasm/wasmd" -VERSION="v0.21.0" +VERSION="v0.23.0" CONTAINER_NAME="wasmd" diff --git a/scripts/wasmd/send_first.js b/scripts/wasmd/send_first.js index 68998d9a6e..b6b10aa680 100755 --- a/scripts/wasmd/send_first.js +++ b/scripts/wasmd/send_first.js @@ -25,7 +25,7 @@ async function main() { const client = await SigningStargateClient.connectWithSigner(rpcUrl, wallet, { prefix: prefix }); const recipient = Bech32.encode(prefix, Random.getBytes(20)); const amount = coins(226644, "ucosm"); - const fee = calculateFee(80_000, "0.025ucosm"); + const fee = calculateFee(100_000, "0.025ucosm"); const memo = "Ensure chain has my pubkey"; const sendResult = await client.sendTokens(faucet.address0, recipient, amount, fee, memo); assertIsDeliverTxSuccess(sendResult); diff --git a/yarn.lock b/yarn.lock index af9095f817..c66081c589 100644 --- a/yarn.lock +++ b/yarn.lock @@ -283,15 +283,13 @@ __metadata: languageName: node linkType: hard -"@confio/ics23@npm:^0.6.3": - version: 0.6.5 - resolution: "@confio/ics23@npm:0.6.5" +"@confio/ics23@npm:^0.6.8": + version: 0.6.8 + resolution: "@confio/ics23@npm:0.6.8" dependencies: - js-sha512: ^0.8.0 + "@noble/hashes": ^1.0.0 protobufjs: ^6.8.8 - ripemd160: ^2.0.2 - sha.js: ^2.4.11 - checksum: dc658795ec67ef60e281985463848e9f46e6804a4fa9a96fbb39809bf646b98f7e0e38e3fa4a8c683fd96e1a7e14a29cad5c14e8b3685da2cab3369ed66e7fe8 + checksum: 376d72f6440db60611b002b00a13e3a5bfd0d3503e7682358dbcf79641e74d8c26c234c321452fb4a758baf66eecef25d950e08bdea270486d9d03ee489e2960 languageName: node linkType: hard @@ -349,7 +347,6 @@ __metadata: "@cosmjs/crypto": "workspace:packages/crypto" "@cosmjs/encoding": "workspace:packages/encoding" "@cosmjs/faucet-client": "workspace:packages/faucet-client" - "@cosmjs/launchpad": "workspace:packages/launchpad" "@cosmjs/math": "workspace:packages/math" "@cosmjs/proto-signing": "workspace:packages/proto-signing" "@cosmjs/stargate": "workspace:packages/stargate" @@ -594,7 +591,6 @@ __metadata: dependencies: "@cosmjs/crypto": "workspace:packages/crypto" "@cosmjs/encoding": "workspace:packages/encoding" - "@cosmjs/launchpad": "workspace:packages/launchpad" "@cosmjs/math": "workspace:packages/math" "@cosmjs/proto-signing": "workspace:packages/proto-signing" "@cosmjs/stargate": "workspace:packages/stargate" @@ -672,56 +668,6 @@ __metadata: languageName: unknown linkType: soft -"@cosmjs/launchpad@workspace:packages/launchpad": - version: 0.0.0-use.local - resolution: "@cosmjs/launchpad@workspace:packages/launchpad" - dependencies: - "@cosmjs/amino": "workspace:packages/amino" - "@cosmjs/crypto": "workspace:packages/crypto" - "@cosmjs/encoding": "workspace:packages/encoding" - "@cosmjs/math": "workspace:packages/math" - "@cosmjs/utils": "workspace:packages/utils" - "@istanbuljs/nyc-config-typescript": ^1.0.1 - "@types/eslint-plugin-prettier": ^3 - "@types/jasmine": ^3.8 - "@types/karma-firefox-launcher": ^2 - "@types/karma-jasmine": ^4 - "@types/karma-jasmine-html-reporter": ^1 - "@types/node": ^15.0.1 - "@typescript-eslint/eslint-plugin": ^4.28 - "@typescript-eslint/parser": ^4.28 - axios: ^0.21.2 - eslint: ^7.5 - eslint-config-prettier: ^8.3.0 - eslint-import-resolver-node: ^0.3.4 - eslint-plugin-import: ^2.22.1 - eslint-plugin-prettier: ^3.4.0 - eslint-plugin-simple-import-sort: ^7.0.0 - esm: ^3.2.25 - fast-deep-equal: ^3.1.3 - glob: ^7.1.6 - jasmine: ^3.8 - jasmine-core: ^3.7.1 - jasmine-spec-reporter: ^6 - karma: ^6.1.1 - karma-chrome-launcher: ^3.1.0 - karma-firefox-launcher: ^2.1.0 - karma-jasmine: ^4.0.1 - karma-jasmine-html-reporter: ^1.5.4 - nyc: ^15.1.0 - prettier: ^2.4.1 - readonly-date: ^1.0.0 - ses: ^0.11.0 - source-map-support: ^0.5.19 - stream-browserify: ^3.0.0 - ts-node: ^8 - typedoc: ^0.22 - typescript: ~4.4 - webpack: ^5.32.0 - webpack-cli: ^4.6.0 - languageName: unknown - linkType: soft - "@cosmjs/ledger-amino@workspace:packages/ledger-amino": version: 0.0.0-use.local resolution: "@cosmjs/ledger-amino@workspace:packages/ledger-amino" @@ -729,7 +675,6 @@ __metadata: "@cosmjs/amino": "workspace:packages/amino" "@cosmjs/crypto": "workspace:packages/crypto" "@cosmjs/encoding": "workspace:packages/encoding" - "@cosmjs/launchpad": "workspace:packages/launchpad" "@cosmjs/math": "workspace:packages/math" "@cosmjs/stargate": "workspace:packages/stargate" "@cosmjs/utils": "workspace:packages/utils" @@ -912,7 +857,7 @@ __metadata: version: 0.0.0-use.local resolution: "@cosmjs/stargate@workspace:packages/stargate" dependencies: - "@confio/ics23": ^0.6.3 + "@confio/ics23": ^0.6.8 "@cosmjs/amino": "workspace:packages/amino" "@cosmjs/crypto": "workspace:packages/crypto" "@cosmjs/encoding": "workspace:packages/encoding" @@ -1244,7 +1189,7 @@ __metadata: languageName: node linkType: hard -"@noble/hashes@npm:^1": +"@noble/hashes@npm:^1, @noble/hashes@npm:^1.0.0": version: 1.0.0 resolution: "@noble/hashes@npm:1.0.0" checksum: bdf1c28a4b587e72ec6b0c504903239c6f96680b2c15a6d90d367512f468eeca12f2ee7bd25967a9529be2bedbf3f8d0a50c33368937f8dfef2a973d0661c7b5 @@ -2985,7 +2930,6 @@ __metadata: "@cosmjs/cosmwasm-stargate": "workspace:packages/cosmwasm-stargate" "@cosmjs/crypto": "workspace:packages/crypto" "@cosmjs/encoding": "workspace:packages/encoding" - "@cosmjs/launchpad": "workspace:packages/launchpad" "@cosmjs/proto-signing": "workspace:packages/proto-signing" "@cosmjs/stargate": "workspace:packages/stargate" eslint: ^7.5 @@ -3737,7 +3681,7 @@ __metadata: languageName: node linkType: hard -"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": +"fast-deep-equal@npm:^3.1.1": version: 3.1.3 resolution: "fast-deep-equal@npm:3.1.3" checksum: e21a9d8d84f53493b6aa15efc9cfd53dd5b714a1f23f67fb5dc8f574af80df889b3bce25dc081887c6d25457cce704e636395333abad896ccdec03abaf1f3f9d @@ -4836,13 +4780,6 @@ fsevents@~2.3.1: languageName: node linkType: hard -"js-sha512@npm:^0.8.0": - version: 0.8.0 - resolution: "js-sha512@npm:0.8.0" - checksum: 32ca371ebd14c6c5c83360fd8b036cad2211537bef546b199ac8b901917299cab4c68f7f7c26ae72f836bbce0349cb463df9a62cdb4c90e38090fdb4db89ee87 - languageName: node - linkType: hard - "js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" @@ -6659,7 +6596,7 @@ fsevents@~2.3.1: languageName: node linkType: hard -"sha.js@npm:^2.4.0, sha.js@npm:^2.4.11, sha.js@npm:^2.4.8": +"sha.js@npm:^2.4.0, sha.js@npm:^2.4.8": version: 2.4.11 resolution: "sha.js@npm:2.4.11" dependencies: @@ -6733,13 +6670,13 @@ fsevents@~2.3.1: linkType: hard "simple-get@npm:^3.0.3": - version: 3.1.0 - resolution: "simple-get@npm:3.1.0" + version: 3.1.1 + resolution: "simple-get@npm:3.1.1" dependencies: decompress-response: ^4.2.0 once: ^1.3.1 simple-concat: ^1.0.0 - checksum: cca91a9ab2b532fa8d367757c196b54e2dfe3325aab0298d66a3e2a45a29a9d335d1a3fb41f036dad14000f78baddd4170fbf9621d72869791d2912baf9469aa + checksum: 80195e70bf171486e75c31e28e5485468195cc42f85940f8b45c4a68472160144d223eb4d07bc82ef80cb974b7c401db021a540deb2d34ac4b3b8883da2d6401 languageName: node linkType: hard