diff --git a/packages/cosmwasm/.eslintignore b/packages/cosmwasm/.eslintignore new file mode 120000 index 00000000..86039baf --- /dev/null +++ b/packages/cosmwasm/.eslintignore @@ -0,0 +1 @@ +../../.eslintignore \ No newline at end of file diff --git a/packages/cosmwasm/.gitignore b/packages/cosmwasm/.gitignore new file mode 100644 index 00000000..68bf3735 --- /dev/null +++ b/packages/cosmwasm/.gitignore @@ -0,0 +1,3 @@ +build/ +dist/ +docs/ diff --git a/packages/cosmwasm/README.md b/packages/cosmwasm/README.md new file mode 100644 index 00000000..ab2208fb --- /dev/null +++ b/packages/cosmwasm/README.md @@ -0,0 +1,12 @@ +# @cosmwasm/cosmwasm + +[![npm version](https://img.shields.io/npm/v/@cosmwasm/cosmwasm.svg)](https://www.npmjs.com/package/@cosmwasm/cosmwasm) + +An SDK to build CosmWasm clients. + +## License + +This package is part of the cosmwasm-js repository, licensed under the Apache +License 2.0 (see +[NOTICE](https://github.com/confio/cosmwasm-js/blob/master/NOTICE) and +[LICENSE](https://github.com/confio/cosmwasm-js/blob/master/LICENSE)). diff --git a/packages/cosmwasm/jasmine-testrunner.js b/packages/cosmwasm/jasmine-testrunner.js new file mode 100755 index 00000000..9fada59b --- /dev/null +++ b/packages/cosmwasm/jasmine-testrunner.js @@ -0,0 +1,26 @@ +#!/usr/bin/env node + +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 }); + +// initialize and execute +jasmine.env.clearReporters(); +jasmine.addReporter(reporter); +jasmine.execute(); diff --git a/packages/cosmwasm/karma.conf.js b/packages/cosmwasm/karma.conf.js new file mode 100644 index 00000000..e68db403 --- /dev/null +++ b/packages/cosmwasm/karma.conf.js @@ -0,0 +1,54 @@ +module.exports = function (config) { + config.set({ + // base path that will be used to resolve all patterns (eg. files, exclude) + basePath: ".", + + // 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, + + customLaunchers: { + ChromeHeadlessInsecure: { + base: "ChromeHeadless", + flags: ["--disable-web-security"], + }, + }, + }); +}; diff --git a/packages/cosmwasm/nonces/README.txt b/packages/cosmwasm/nonces/README.txt new file mode 100644 index 00000000..092fe732 --- /dev/null +++ b/packages/cosmwasm/nonces/README.txt @@ -0,0 +1 @@ +Directory used to trigger lerna package updates for all packages diff --git a/packages/cosmwasm/package.json b/packages/cosmwasm/package.json new file mode 100644 index 00000000..082cca20 --- /dev/null +++ b/packages/cosmwasm/package.json @@ -0,0 +1,51 @@ +{ + "name": "@cosmwasm/cosmwasm", + "version": "0.8.0", + "description": "CosmWasm SDK", + "author": "Ethan Frey ", + "license": "Apache-2.0", + "main": "build/index.js", + "types": "types/index.d.ts", + "files": [ + "build/", + "types/", + "*.md", + "!*.spec.*", + "!**/testdata/" + ], + "repository": { + "type": "git", + "url": "https://github.com/confio/cosmwasm-js/tree/master/packages/cosmwasm" + }, + "publishConfig": { + "access": "public" + }, + "scripts": { + "docs": "shx rm -rf docs && typedoc --options typedoc.js", + "format": "prettier --write --loglevel warn \"./src/**/*.ts\"", + "lint": "eslint --max-warnings 0 \"**/*.{js,ts}\"", + "lint-fix": "eslint --max-warnings 0 \"**/*.{js,ts}\" --fix", + "move-types": "shx rm -rf ./types/* && shx mv build/types/* ./types && rm -rf ./types/testdata && shx rm -f ./types/*.spec.d.ts", + "format-types": "prettier --write --loglevel warn \"./types/**/*.d.ts\"", + "build": "shx rm -rf ./build && tsc && yarn move-types && yarn format-types", + "build-or-skip": "[ -n \"$SKIP_BUILD\" ] || yarn build", + "test-node": "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 ChromeHeadlessInsecure", + "test": "yarn build-or-skip && yarn test-node", + "pack-web": "yarn build-or-skip && webpack --mode development --config webpack.web.config.js" + }, + "dependencies": { + "@cosmwasm/sdk38": "^0.8.0", + "@iov/crypto": "^2.1.0", + "@iov/encoding": "^2.1.0", + "@iov/utils": "^2.0.2", + "axios": "^0.19.0", + "fast-deep-equal": "^3.1.1", + "pako": "^1.0.11" + }, + "devDependencies": { + "@types/pako": "^1.0.1", + "readonly-date": "^1.0.0" + } +} diff --git a/packages/cosmwasm/src/builder.spec.ts b/packages/cosmwasm/src/builder.spec.ts new file mode 100644 index 00000000..20926f4c --- /dev/null +++ b/packages/cosmwasm/src/builder.spec.ts @@ -0,0 +1,63 @@ +import { isValidBuilder } from "./builder"; + +describe("builder", () => { + describe("isValidBuilder", () => { + // Valid cases + + it("returns true for simple examples", () => { + expect(isValidBuilder("myorg/super-optimizer:0.1.2")).toEqual(true); + expect(isValidBuilder("myorg/super-optimizer:42")).toEqual(true); + }); + + it("supports images with multi level names", () => { + expect(isValidBuilder("myorg/department-x/office-y/technology-z/super-optimizer:0.1.2")).toEqual(true); + }); + + it("returns true for tags with lower and upper chars", () => { + expect(isValidBuilder("myorg/super-optimizer:0.1.2-alpha")).toEqual(true); + expect(isValidBuilder("myorg/super-optimizer:0.1.2-Alpha")).toEqual(true); + }); + + // Invalid cases + + it("returns false for missing or empty tag", () => { + expect(isValidBuilder("myorg/super-optimizer")).toEqual(false); + expect(isValidBuilder("myorg/super-optimizer:")).toEqual(false); + }); + + it("returns false for name components starting or ending with a separator", () => { + expect(isValidBuilder(".myorg/super-optimizer:42")).toEqual(false); + expect(isValidBuilder("-myorg/super-optimizer:42")).toEqual(false); + expect(isValidBuilder("_myorg/super-optimizer:42")).toEqual(false); + expect(isValidBuilder("myorg./super-optimizer:42")).toEqual(false); + expect(isValidBuilder("myorg-/super-optimizer:42")).toEqual(false); + expect(isValidBuilder("myorg_/super-optimizer:42")).toEqual(false); + expect(isValidBuilder("myorg/.super-optimizer:42")).toEqual(false); + expect(isValidBuilder("myorg/-super-optimizer:42")).toEqual(false); + expect(isValidBuilder("myorg/_super-optimizer:42")).toEqual(false); + expect(isValidBuilder("myorg/super-optimizer.:42")).toEqual(false); + expect(isValidBuilder("myorg/super-optimizer-:42")).toEqual(false); + expect(isValidBuilder("myorg/super-optimizer_:42")).toEqual(false); + }); + + it("returns false for upper case character in name component", () => { + expect(isValidBuilder("mYorg/super-optimizer:42")).toEqual(false); + expect(isValidBuilder("myorg/super-Optimizer:42")).toEqual(false); + }); + + it("returns false for long images", () => { + expect( + isValidBuilder( + "myorgisnicenicenicenicenicenicenicenicenicenicenicenicenicenicenicenicenicenicenicenicenicenicenicenicenicenice/super-optimizer:42", + ), + ).toEqual(false); + }); + + it("returns false for images with no organization", () => { + // Those are valid dockerhub images from https://hub.docker.com/_/ubuntu and https://hub.docker.com/_/rust + // but not valid in the context of CosmWasm Verify + expect(isValidBuilder("ubuntu:xenial-20200212")).toEqual(false); + expect(isValidBuilder("rust:1.40.0")).toEqual(false); + }); + }); +}); diff --git a/packages/cosmwasm/src/builder.ts b/packages/cosmwasm/src/builder.ts new file mode 100644 index 00000000..31a790c7 --- /dev/null +++ b/packages/cosmwasm/src/builder.ts @@ -0,0 +1,20 @@ +// A docker image regexp. We remove support for non-standard registries for simplicity. +// https://docs.docker.com/engine/reference/commandline/tag/#extended-description +// +// An image name is made up of slash-separated name components (optionally prefixed by a registry hostname). +// Name components may contain lowercase characters, digits and separators. +// A separator is defined as a period, one or two underscores, or one or more dashes. A name component may not start or end with a separator. +// +// A tag name must be valid ASCII and may contain lowercase and uppercase letters, digits, underscores, periods and dashes. +// A tag name may not start with a period or a dash and may contain a maximum of 128 characters. +const dockerImagePattern = new RegExp( + "^[a-z0-9][a-z0-9._-]*[a-z0-9](/[a-z0-9][a-z0-9._-]*[a-z0-9])+:[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,127}$", +); + +/** Max length in bytes/characters (regexp enforces all ASCII, even if that is not required by the standard) */ +const builderMaxLength = 128; + +export function isValidBuilder(builder: string): boolean { + if (builder.length > builderMaxLength) return false; + return !!builder.match(dockerImagePattern); +} diff --git a/packages/cosmwasm/src/cosmwasmclient.searchtx.spec.ts b/packages/cosmwasm/src/cosmwasmclient.searchtx.spec.ts new file mode 100644 index 00000000..1b92ecba --- /dev/null +++ b/packages/cosmwasm/src/cosmwasmclient.searchtx.spec.ts @@ -0,0 +1,465 @@ +/* eslint-disable @typescript-eslint/camelcase */ +import { Coin, Secp256k1Pen, makeSignBytes } from "@cosmwasm/sdk38"; +import { assert, sleep } from "@iov/utils"; + +import { CosmWasmClient } from "./cosmwasmclient"; +import { RestClient } from "./restclient"; +import { SigningCosmWasmClient } from "./signingcosmwasmclient"; +import { + deployedErc20, + faucet, + fromOneElementArray, + makeRandomAddress, + pendingWithoutWasmd, + wasmd, + wasmdEnabled, +} from "./testutils.spec"; +import { CosmosSdkTx, isMsgExecuteContract, isMsgInstantiateContract, isMsgSend, MsgSend } from "./types"; + +describe("CosmWasmClient.searchTx", () => { + let sendSuccessful: + | { + readonly sender: string; + readonly recipient: string; + readonly hash: string; + readonly height: number; + readonly tx: CosmosSdkTx; + } + | undefined; + let sendUnsuccessful: + | { + readonly sender: string; + readonly recipient: string; + readonly hash: string; + readonly height: number; + readonly tx: CosmosSdkTx; + } + | undefined; + let postedExecute: + | { + readonly sender: string; + readonly contract: string; + readonly hash: string; + readonly height: number; + readonly tx: CosmosSdkTx; + } + | undefined; + + beforeAll(async () => { + if (wasmdEnabled()) { + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); + const client = new SigningCosmWasmClient(wasmd.endpoint, faucet.address, (signBytes) => + pen.sign(signBytes), + ); + + { + const recipient = makeRandomAddress(); + const transferAmount: Coin = { + denom: "ucosm", + amount: "1234567", + }; + const result = await client.sendTokens(recipient, [transferAmount]); + await sleep(50); // wait until tx is indexed + const txDetails = await new RestClient(wasmd.endpoint).txById(result.transactionHash); + sendSuccessful = { + sender: faucet.address, + recipient: recipient, + hash: result.transactionHash, + height: Number.parseInt(txDetails.height, 10), + tx: txDetails.tx, + }; + } + + { + const memo = "Sending more than I can afford"; + const recipient = makeRandomAddress(); + const transferAmount = [ + { + denom: "ucosm", + amount: "123456700000000", + }, + ]; + const sendMsg: MsgSend = { + type: "cosmos-sdk/MsgSend", + value: { + // eslint-disable-next-line @typescript-eslint/camelcase + from_address: faucet.address, + // eslint-disable-next-line @typescript-eslint/camelcase + to_address: recipient, + amount: transferAmount, + }, + }; + const fee = { + amount: [ + { + denom: "ucosm", + amount: "2000", + }, + ], + gas: "80000", // 80k + }; + const { accountNumber, sequence } = await client.getNonce(); + const chainId = await client.getChainId(); + const signBytes = makeSignBytes([sendMsg], fee, chainId, memo, accountNumber, sequence); + const signature = await pen.sign(signBytes); + const tx: CosmosSdkTx = { + type: "cosmos-sdk/StdTx", + value: { + msg: [sendMsg], + fee: fee, + memo: memo, + signatures: [signature], + }, + }; + const transactionId = await client.getIdentifier(tx); + const heightBeforeThis = await client.getHeight(); + try { + await client.postTx(tx.value); + } catch (error) { + // postTx() throws on execution failures, which is a questionable design. Ignore for now. + // console.log(error); + } + sendUnsuccessful = { + sender: faucet.address, + recipient: recipient, + hash: transactionId, + height: heightBeforeThis + 1, + tx: tx, + }; + } + + { + const hashInstance = deployedErc20.instances[0]; + const msg = { + approve: { + spender: makeRandomAddress(), + amount: "12", + }, + }; + const result = await client.execute(hashInstance, msg); + await sleep(50); // wait until tx is indexed + const txDetails = await new RestClient(wasmd.endpoint).txById(result.transactionHash); + postedExecute = { + sender: faucet.address, + contract: hashInstance, + hash: result.transactionHash, + height: Number.parseInt(txDetails.height, 10), + tx: txDetails.tx, + }; + } + } + }); + + describe("with SearchByIdQuery", () => { + it("can search successful tx by ID", async () => { + pendingWithoutWasmd(); + assert(sendSuccessful, "value must be set in beforeAll()"); + const client = new CosmWasmClient(wasmd.endpoint); + const result = await client.searchTx({ id: sendSuccessful.hash }); + expect(result.length).toEqual(1); + expect(result[0]).toEqual( + jasmine.objectContaining({ + height: sendSuccessful.height, + hash: sendSuccessful.hash, + code: 0, + tx: sendSuccessful.tx, + }), + ); + }); + + it("can search unsuccessful tx by ID", async () => { + pendingWithoutWasmd(); + assert(sendUnsuccessful, "value must be set in beforeAll()"); + const client = new CosmWasmClient(wasmd.endpoint); + const result = await client.searchTx({ id: sendUnsuccessful.hash }); + expect(result.length).toEqual(1); + expect(result[0]).toEqual( + jasmine.objectContaining({ + height: sendUnsuccessful.height, + hash: sendUnsuccessful.hash, + code: 5, + tx: sendUnsuccessful.tx, + }), + ); + }); + + it("can search by ID (non existent)", async () => { + pendingWithoutWasmd(); + const client = new CosmWasmClient(wasmd.endpoint); + const nonExistentId = "0000000000000000000000000000000000000000000000000000000000000000"; + const result = await client.searchTx({ id: nonExistentId }); + expect(result.length).toEqual(0); + }); + + it("can search by ID and filter by minHeight", async () => { + pendingWithoutWasmd(); + assert(sendSuccessful); + const client = new CosmWasmClient(wasmd.endpoint); + const query = { id: sendSuccessful.hash }; + + { + 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); + } + }); + }); + + describe("with SearchByHeightQuery", () => { + it("can search successful tx by height", async () => { + pendingWithoutWasmd(); + assert(sendSuccessful, "value must be set in beforeAll()"); + const client = new CosmWasmClient(wasmd.endpoint); + const result = await client.searchTx({ height: sendSuccessful.height }); + expect(result.length).toEqual(1); + expect(result[0]).toEqual( + jasmine.objectContaining({ + height: sendSuccessful.height, + hash: sendSuccessful.hash, + code: 0, + tx: sendSuccessful.tx, + }), + ); + }); + + it("can search unsuccessful tx by height", async () => { + pendingWithoutWasmd(); + assert(sendUnsuccessful, "value must be set in beforeAll()"); + const client = new CosmWasmClient(wasmd.endpoint); + const result = await client.searchTx({ height: sendUnsuccessful.height }); + expect(result.length).toEqual(1); + expect(result[0]).toEqual( + jasmine.objectContaining({ + height: sendUnsuccessful.height, + hash: sendUnsuccessful.hash, + code: 5, + tx: sendUnsuccessful.tx, + }), + ); + }); + }); + + describe("with SearchBySentFromOrToQuery", () => { + it("can search by sender", async () => { + pendingWithoutWasmd(); + assert(sendSuccessful, "value must be set in beforeAll()"); + const client = new CosmWasmClient(wasmd.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 () => { + pendingWithoutWasmd(); + assert(sendSuccessful, "value must be set in beforeAll()"); + const client = new CosmWasmClient(wasmd.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 () => { + pendingWithoutWasmd(); + assert(sendSuccessful); + const client = new CosmWasmClient(wasmd.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 () => { + pendingWithoutWasmd(); + assert(sendSuccessful); + const client = new CosmWasmClient(wasmd.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 () => { + pendingWithoutWasmd(); + assert(sendSuccessful, "value must be set in beforeAll()"); + const client = new CosmWasmClient(wasmd.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, + }), + ); + }); + + it("can search by message.contract_address", async () => { + pendingWithoutWasmd(); + assert(postedExecute, "value must be set in beforeAll()"); + const client = new CosmWasmClient(wasmd.endpoint); + const results = await client.searchTx({ + tags: [{ key: "message.contract_address", value: postedExecute.contract }], + }); + expect(results.length).toBeGreaterThanOrEqual(1); + + // Check basic structure of all results + for (const result of results) { + const msg = fromOneElementArray(result.tx.value.msg); + assert( + isMsgExecuteContract(msg) || isMsgInstantiateContract(msg), + `${result.hash} (at ${result.height}) not an execute or instantiate msg`, + ); + } + + // Check that the first result is the instantiation + const first = fromOneElementArray(results[0].tx.value.msg); + assert(isMsgInstantiateContract(first), "First contract search result must be an instantiation"); + expect(first).toEqual({ + type: "wasm/instantiate", + value: { + sender: faucet.address, + code_id: deployedErc20.codeId.toString(), + label: "HASH", + init_msg: jasmine.objectContaining({ symbol: "HASH" }), + init_funds: [], + }, + }); + + // Check details of most recent result + expect(results[results.length - 1]).toEqual( + jasmine.objectContaining({ + height: postedExecute.height, + hash: postedExecute.hash, + tx: postedExecute.tx, + }), + ); + }); + + it("can search by message.contract_address + message.action", async () => { + pendingWithoutWasmd(); + assert(postedExecute, "value must be set in beforeAll()"); + const client = new CosmWasmClient(wasmd.endpoint); + const results = await client.searchTx({ + tags: [ + { key: "message.contract_address", value: postedExecute.contract }, + { key: "message.action", value: "execute" }, + ], + }); + expect(results.length).toBeGreaterThanOrEqual(1); + + // Check basic structure of all results + for (const result of results) { + const msg = fromOneElementArray(result.tx.value.msg); + assert(isMsgExecuteContract(msg), `${result.hash} (at ${result.height}) not an execute msg`); + expect(msg.value.contract).toEqual(postedExecute.contract); + } + + // Check details of most recent result + expect(results[results.length - 1]).toEqual( + jasmine.objectContaining({ + height: postedExecute.height, + hash: postedExecute.hash, + tx: postedExecute.tx, + }), + ); + }); + }); +}); diff --git a/packages/cosmwasm/src/cosmwasmclient.spec.ts b/packages/cosmwasm/src/cosmwasmclient.spec.ts new file mode 100644 index 00000000..7c4904ed --- /dev/null +++ b/packages/cosmwasm/src/cosmwasmclient.spec.ts @@ -0,0 +1,466 @@ +/* eslint-disable @typescript-eslint/camelcase */ +import { Secp256k1Pen, makeSignBytes } from "@cosmwasm/sdk38"; +import { Sha256 } from "@iov/crypto"; +import { Bech32, Encoding } from "@iov/encoding"; +import { assert, sleep } from "@iov/utils"; +import { ReadonlyDate } from "readonly-date"; + +import { Code, CosmWasmClient, PrivateCosmWasmClient } from "./cosmwasmclient"; +import { findAttribute } from "./logs"; +import { SigningCosmWasmClient } from "./signingcosmwasmclient"; +import cosmoshub from "./testdata/cosmoshub.json"; +import { + deployedErc20, + faucet, + getHackatom, + makeRandomAddress, + pendingWithoutWasmd, + tendermintIdMatcher, + unused, + wasmd, + wasmdEnabled, +} from "./testutils.spec"; +import { MsgSend, StdFee } from "./types"; + +const { fromHex, fromUtf8, toAscii, toBase64 } = Encoding; + +const guest = { + address: "cosmos17d0jcz59jf68g52vq38tuuncmwwjk42u6mcxej", +}; + +interface HackatomInstance { + readonly initMsg: { + readonly verifier: string; + readonly beneficiary: string; + }; + readonly address: string; +} + +describe("CosmWasmClient", () => { + describe("makeReadOnly", () => { + it("can be constructed", () => { + const client = new CosmWasmClient(wasmd.endpoint); + expect(client).toBeTruthy(); + }); + }); + + describe("getChainId", () => { + it("works", async () => { + pendingWithoutWasmd(); + const client = new CosmWasmClient(wasmd.endpoint); + expect(await client.getChainId()).toEqual(wasmd.chainId); + }); + + it("caches chain ID", async () => { + pendingWithoutWasmd(); + const client = new CosmWasmClient(wasmd.endpoint); + const openedClient = (client as unknown) as PrivateCosmWasmClient; + const getCodeSpy = spyOn(openedClient.restClient, "nodeInfo").and.callThrough(); + + expect(await client.getChainId()).toEqual(wasmd.chainId); // from network + expect(await client.getChainId()).toEqual(wasmd.chainId); // from cache + + expect(getCodeSpy).toHaveBeenCalledTimes(1); + }); + }); + + describe("getHeight", () => { + it("gets height via last block", async () => { + pendingWithoutWasmd(); + const client = new CosmWasmClient(wasmd.endpoint); + const openedClient = (client as unknown) as PrivateCosmWasmClient; + const blockLatestSpy = spyOn(openedClient.restClient, "blocksLatest").and.callThrough(); + + const height1 = await client.getHeight(); + expect(height1).toBeGreaterThan(0); + await sleep(1_000); + const height2 = await client.getHeight(); + expect(height2).toEqual(height1 + 1); + + expect(blockLatestSpy).toHaveBeenCalledTimes(2); + }); + + it("gets height via authAccount once an address is known", async () => { + pendingWithoutWasmd(); + const client = new CosmWasmClient(wasmd.endpoint); + + const openedClient = (client as unknown) as PrivateCosmWasmClient; + const blockLatestSpy = spyOn(openedClient.restClient, "blocksLatest").and.callThrough(); + const authAccountsSpy = spyOn(openedClient.restClient, "authAccounts").and.callThrough(); + + const height1 = await client.getHeight(); + expect(height1).toBeGreaterThan(0); + + await client.getCodes(); // warm up the client + + const height2 = await client.getHeight(); + expect(height2).toBeGreaterThan(0); + await sleep(1_000); + const height3 = await client.getHeight(); + expect(height3).toEqual(height2 + 1); + + expect(blockLatestSpy).toHaveBeenCalledTimes(1); + expect(authAccountsSpy).toHaveBeenCalledTimes(2); + }); + }); + + describe("getNonce", () => { + it("works", async () => { + pendingWithoutWasmd(); + const client = new CosmWasmClient(wasmd.endpoint); + expect(await client.getNonce(unused.address)).toEqual({ + accountNumber: unused.accountNumber, + sequence: unused.sequence, + }); + }); + + it("throws for missing accounts", async () => { + pendingWithoutWasmd(); + const client = new CosmWasmClient(wasmd.endpoint); + const missing = makeRandomAddress(); + await client.getNonce(missing).then( + () => fail("this must not succeed"), + (error) => expect(error).toMatch(/account does not exist on chain/i), + ); + }); + }); + + describe("getAccount", () => { + it("works", async () => { + pendingWithoutWasmd(); + const client = new CosmWasmClient(wasmd.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 () => { + pendingWithoutWasmd(); + const client = new CosmWasmClient(wasmd.endpoint); + const missing = makeRandomAddress(); + expect(await client.getAccount(missing)).toBeUndefined(); + }); + }); + + describe("getBlock", () => { + it("works for latest block", async () => { + pendingWithoutWasmd(); + const client = new CosmWasmClient(wasmd.endpoint); + const response = await client.getBlock(); + + // id + expect(response.id).toMatch(tendermintIdMatcher); + + // header + expect(response.header.height).toBeGreaterThanOrEqual(1); + expect(response.header.chainId).toEqual(await client.getChainId()); + expect(new ReadonlyDate(response.header.time).getTime()).toBeLessThan(ReadonlyDate.now()); + expect(new ReadonlyDate(response.header.time).getTime()).toBeGreaterThanOrEqual( + ReadonlyDate.now() - 5_000, + ); + + // txs + expect(Array.isArray(response.txs)).toEqual(true); + }); + + it("works for block by height", async () => { + pendingWithoutWasmd(); + const client = new CosmWasmClient(wasmd.endpoint); + const height = (await client.getBlock()).header.height; + const response = await client.getBlock(height - 1); + + // id + expect(response.id).toMatch(tendermintIdMatcher); + + // header + expect(response.header.height).toEqual(height - 1); + expect(response.header.chainId).toEqual(await client.getChainId()); + expect(new ReadonlyDate(response.header.time).getTime()).toBeLessThan(ReadonlyDate.now()); + expect(new ReadonlyDate(response.header.time).getTime()).toBeGreaterThanOrEqual( + ReadonlyDate.now() - 5_000, + ); + + // txs + expect(Array.isArray(response.txs)).toEqual(true); + }); + }); + + describe("getIdentifier", () => { + it("works", async () => { + pendingWithoutWasmd(); + const client = new CosmWasmClient(wasmd.endpoint); + expect(await client.getIdentifier(cosmoshub.tx)).toEqual(cosmoshub.id); + }); + }); + + describe("postTx", () => { + it("works", async () => { + pendingWithoutWasmd(); + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); + const client = new CosmWasmClient(wasmd.endpoint); + + const memo = "My first contract on chain"; + const sendMsg: MsgSend = { + type: "cosmos-sdk/MsgSend", + value: { + from_address: faucet.address, + 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.getNonce(faucet.address); + const signBytes = makeSignBytes([sendMsg], fee, chainId, memo, accountNumber, sequence); + const signature = await pen.sign(signBytes); + const signedTx = { + msg: [sendMsg], + fee: fee, + memo: memo, + signatures: [signature], + }; + const { logs, transactionHash } = await client.postTx(signedTx); + const amountAttr = findAttribute(logs, "transfer", "amount"); + expect(amountAttr.value).toEqual("1234567ucosm"); + expect(transactionHash).toMatch(/^[0-9A-F]{64}$/); + }); + }); + + describe("getCodes", () => { + it("works", async () => { + pendingWithoutWasmd(); + const client = new CosmWasmClient(wasmd.endpoint); + const result = await client.getCodes(); + expect(result.length).toBeGreaterThanOrEqual(1); + const [first] = result; + expect(first).toEqual({ + id: deployedErc20.codeId, + source: deployedErc20.source, + builder: deployedErc20.builder, + checksum: deployedErc20.checksum, + creator: faucet.address, + }); + }); + }); + + describe("getCodeDetails", () => { + it("works", async () => { + pendingWithoutWasmd(); + const client = new CosmWasmClient(wasmd.endpoint); + const result = await client.getCodeDetails(1); + + const expectedInfo: Code = { + id: deployedErc20.codeId, + source: deployedErc20.source, + builder: deployedErc20.builder, + checksum: deployedErc20.checksum, + creator: faucet.address, + }; + + // check info + expect(result).toEqual(jasmine.objectContaining(expectedInfo)); + // check data + expect(new Sha256(result.data).digest()).toEqual(fromHex(expectedInfo.checksum)); + }); + + it("caches downloads", async () => { + pendingWithoutWasmd(); + const client = new CosmWasmClient(wasmd.endpoint); + const openedClient = (client as unknown) as PrivateCosmWasmClient; + const getCodeSpy = spyOn(openedClient.restClient, "getCode").and.callThrough(); + + const result1 = await client.getCodeDetails(deployedErc20.codeId); // from network + const result2 = await client.getCodeDetails(deployedErc20.codeId); // from cache + expect(result2).toEqual(result1); + + expect(getCodeSpy).toHaveBeenCalledTimes(1); + }); + }); + + describe("getContracts", () => { + it("works", async () => { + pendingWithoutWasmd(); + const client = new CosmWasmClient(wasmd.endpoint); + const result = await client.getContracts(1); + expect(result.length).toBeGreaterThanOrEqual(3); + const [hash, isa, jade] = result; + expect(hash).toEqual({ + address: "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5", + codeId: 1, + creator: faucet.address, + label: "HASH", + }); + expect(isa).toEqual({ + address: "cosmos1hqrdl6wstt8qzshwc6mrumpjk9338k0lr4dqxd", + codeId: 1, + creator: faucet.address, + label: "ISA", + }); + expect(jade).toEqual({ + address: "cosmos18r5szma8hm93pvx6lwpjwyxruw27e0k5uw835c", + codeId: 1, + creator: faucet.address, + label: "JADE", + }); + }); + }); + + describe("getContract", () => { + it("works for HASH instance", async () => { + pendingWithoutWasmd(); + const client = new CosmWasmClient(wasmd.endpoint); + const hash = await client.getContract("cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5"); + expect(hash).toEqual({ + address: "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5", + codeId: 1, + creator: faucet.address, + label: "HASH", + initMsg: { + decimals: 5, + name: "Hash token", + symbol: "HASH", + initial_balances: jasmine.arrayContaining([ + { + address: faucet.address, + amount: "11", + }, + { + address: unused.address, + amount: "12812345", + }, + { + address: guest.address, + amount: "22004000000", + }, + ]), + }, + }); + }); + }); + + describe("queryContractRaw", () => { + const configKey = toAscii("config"); + const otherKey = toAscii("this_does_not_exist"); + let contract: HackatomInstance | undefined; + + beforeAll(async () => { + if (wasmdEnabled()) { + pendingWithoutWasmd(); + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); + const client = new SigningCosmWasmClient(wasmd.endpoint, faucet.address, (signBytes) => + pen.sign(signBytes), + ); + const { codeId } = await client.upload(getHackatom()); + const initMsg = { verifier: makeRandomAddress(), beneficiary: makeRandomAddress() }; + const { contractAddress } = await client.instantiate(codeId, initMsg, "random hackatom"); + contract = { initMsg: initMsg, address: contractAddress }; + } + }); + + it("can query existing key", async () => { + pendingWithoutWasmd(); + assert(contract); + + const client = new CosmWasmClient(wasmd.endpoint); + const raw = await client.queryContractRaw(contract.address, configKey); + assert(raw, "must get result"); + expect(JSON.parse(fromUtf8(raw))).toEqual({ + verifier: toBase64(Bech32.decode(contract.initMsg.verifier).data), + beneficiary: toBase64(Bech32.decode(contract.initMsg.beneficiary).data), + funder: toBase64(Bech32.decode(faucet.address).data), + }); + }); + + it("can query non-existent key", async () => { + pendingWithoutWasmd(); + assert(contract); + + const client = new CosmWasmClient(wasmd.endpoint); + const raw = await client.queryContractRaw(contract.address, otherKey); + expect(raw).toBeNull(); + }); + + it("errors for non-existent contract", async () => { + pendingWithoutWasmd(); + assert(contract); + + const nonExistentAddress = makeRandomAddress(); + const client = new CosmWasmClient(wasmd.endpoint); + await client.queryContractRaw(nonExistentAddress, configKey).then( + () => fail("must not succeed"), + (error) => expect(error).toMatch(`No contract found at address "${nonExistentAddress}"`), + ); + }); + }); + + describe("queryContractSmart", () => { + let contract: HackatomInstance | undefined; + + beforeAll(async () => { + if (wasmdEnabled()) { + pendingWithoutWasmd(); + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); + const client = new SigningCosmWasmClient(wasmd.endpoint, faucet.address, (signBytes) => + pen.sign(signBytes), + ); + const { codeId } = await client.upload(getHackatom()); + const initMsg = { verifier: makeRandomAddress(), beneficiary: makeRandomAddress() }; + const { contractAddress } = await client.instantiate(codeId, initMsg, "a different hackatom"); + contract = { initMsg: initMsg, address: contractAddress }; + } + }); + + it("works", async () => { + pendingWithoutWasmd(); + assert(contract); + + const client = new CosmWasmClient(wasmd.endpoint); + const resultDocument = await client.queryContractSmart(contract.address, { verifier: {} }); + expect(resultDocument).toEqual({ verifier: contract.initMsg.verifier }); + }); + + it("errors for malformed query message", async () => { + pendingWithoutWasmd(); + assert(contract); + + const client = new CosmWasmClient(wasmd.endpoint); + await client.queryContractSmart(contract.address, { broken: {} }).then( + () => fail("must not succeed"), + (error) => expect(error).toMatch(/query wasm contract failed: parsing hackatom::contract::QueryMsg/i), + ); + }); + + it("errors for non-existent contract", async () => { + pendingWithoutWasmd(); + + const nonExistentAddress = makeRandomAddress(); + const client = new CosmWasmClient(wasmd.endpoint); + await client.queryContractSmart(nonExistentAddress, { verifier: {} }).then( + () => fail("must not succeed"), + (error) => expect(error).toMatch(`No contract found at address "${nonExistentAddress}"`), + ); + }); + }); +}); diff --git a/packages/cosmwasm/src/cosmwasmclient.ts b/packages/cosmwasm/src/cosmwasmclient.ts new file mode 100644 index 00000000..04c30d3c --- /dev/null +++ b/packages/cosmwasm/src/cosmwasmclient.ts @@ -0,0 +1,439 @@ +import { Coin } from "@cosmwasm/sdk38"; +import { Sha256 } from "@iov/crypto"; +import { Encoding } from "@iov/encoding"; + +import { Log, parseLogs } from "./logs"; +import { decodeBech32Pubkey } from "./pubkey"; +import { BroadcastMode, RestClient } from "./restclient"; +import { CosmosSdkTx, JsonObject, PubKey, StdTx } from "./types"; + +export interface GetNonceResult { + readonly accountNumber: number; + readonly sequence: number; +} + +export interface Account { + /** Bech32 account address */ + readonly address: string; + readonly balance: ReadonlyArray; + readonly pubkey: PubKey | undefined; + readonly accountNumber: number; + readonly sequence: number; +} + +export interface PostTxResult { + 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; +} + +export interface SearchByIdQuery { + readonly id: string; +} + +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: readonly { readonly key: string; readonly value: string }[]; +} + +export type SearchTxQuery = + | SearchByIdQuery + | SearchByHeightQuery + | SearchBySentFromOrToQuery + | SearchByTagsQuery; + +function isSearchByIdQuery(query: SearchTxQuery): query is SearchByIdQuery { + return (query as SearchByIdQuery).id !== undefined; +} + +function isSearchByHeightQuery(query: SearchTxQuery): query is SearchByHeightQuery { + return (query as SearchByHeightQuery).height !== undefined; +} + +function isSearchBySentFromOrToQuery(query: SearchTxQuery): query is SearchBySentFromOrToQuery { + return (query as SearchBySentFromOrToQuery).sentFromOrTo !== undefined; +} + +function isSearchByTagsQuery(query: SearchTxQuery): query is SearchByTagsQuery { + return (query as SearchByTagsQuery).tags !== undefined; +} + +export interface SearchTxFilter { + readonly minHeight?: number; + readonly maxHeight?: number; +} + +export interface Code { + readonly id: number; + /** Bech32 account address */ + readonly creator: string; + /** Hex-encoded sha256 hash of the code stored here */ + readonly checksum: string; + readonly source?: string; + readonly builder?: string; +} + +export interface CodeDetails extends Code { + /** The original wasm bytes */ + readonly data: Uint8Array; +} + +export interface Contract { + readonly address: string; + readonly codeId: number; + /** Bech32 account address */ + readonly creator: string; + readonly label: string; +} + +export interface ContractDetails extends Contract { + /** Argument passed on initialization of the contract */ + readonly initMsg: object; +} + +/** 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: CosmosSdkTx; + /** 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: ReadonlyArray; +} + +/** Use for testing only */ +export interface PrivateCosmWasmClient { + readonly restClient: RestClient; +} + +export class CosmWasmClient { + protected readonly restClient: RestClient; + /** Any address the chain considers valid (valid bech32 with proper prefix) */ + protected anyValidAddress: string | undefined; + + private readonly codesCache = new Map(); + 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 postTx method (i.e. transaction broadcasting) returns + */ + public constructor(apiUrl: string, broadcastMode = BroadcastMode.Block) { + this.restClient = new RestClient(apiUrl, broadcastMode); + } + + public async getChainId(): Promise { + if (!this.chainId) { + const response = await this.restClient.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.restClient.authAccounts(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.restClient.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: CosmosSdkTx): Promise { + // We consult the REST API because we don't have a local amino encoder + const bytes = await this.restClient.encodeTx(tx); + const hash = new Sha256(bytes).digest(); + return Encoding.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 getNonce(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 nonces.", + ); + } + return { + accountNumber: account.accountNumber, + sequence: account.sequence, + }; + } + + public async getAccount(address: string): Promise { + const account = await this.restClient.authAccounts(address); + const value = account.result.value; + if (value.address === "") { + return undefined; + } else { + this.anyValidAddress = value.address; + return { + address: value.address, + balance: value.coins, + pubkey: value.public_key ? decodeBech32Pubkey(value.public_key) : undefined, + accountNumber: value.account_number, + sequence: 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.restClient.blocks(height) : await this.restClient.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((encoded) => Encoding.fromBase64(encoded)), + }; + } + + 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 (isSearchByIdQuery(query)) { + txs = await this.txsQuery(`tx.hash=${query.id}`); + } else 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 postTx(tx: StdTx): Promise { + const result = await this.restClient.postTx(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"); + } + + if (result.code) { + throw new Error( + `Error when posting tx ${result.txhash}. Code: ${result.code}; Raw log: ${result.raw_log}`, + ); + } + + return { + logs: result.logs ? parseLogs(result.logs) : [], + rawLog: result.raw_log || "", + transactionHash: result.txhash, + }; + } + + public async getCodes(): Promise { + const result = await this.restClient.listCodeInfo(); + return result.map( + (entry): Code => { + this.anyValidAddress = entry.creator; + return { + id: entry.id, + creator: entry.creator, + checksum: Encoding.toHex(Encoding.fromHex(entry.data_hash)), + source: entry.source || undefined, + builder: entry.builder || undefined, + }; + }, + ); + } + + public async getCodeDetails(codeId: number): Promise { + const cached = this.codesCache.get(codeId); + if (cached) return cached; + + const getCodeResult = await this.restClient.getCode(codeId); + const codeDetails: CodeDetails = { + id: getCodeResult.id, + creator: getCodeResult.creator, + checksum: Encoding.toHex(Encoding.fromHex(getCodeResult.data_hash)), + source: getCodeResult.source || undefined, + builder: getCodeResult.builder || undefined, + data: Encoding.fromBase64(getCodeResult.data), + }; + this.codesCache.set(codeId, codeDetails); + return codeDetails; + } + + public async getContracts(codeId: number): Promise { + const result = await this.restClient.listContractsByCodeId(codeId); + return result.map( + (entry): Contract => ({ + address: entry.address, + codeId: entry.code_id, + creator: entry.creator, + label: entry.label, + }), + ); + } + + /** + * Throws an error if no contract was found at the address + */ + public async getContract(address: string): Promise { + const result = await this.restClient.getContractInfo(address); + if (!result) throw new Error(`No contract found at address "${address}"`); + return { + address: result.address, + codeId: result.code_id, + creator: result.creator, + label: result.label, + initMsg: result.init_msg, + }; + } + + /** + * Returns the data at the key if present (raw contract dependent storage data) + * or null if no data at this key. + * + * Promise is rejected when contract does not exist. + */ + public async queryContractRaw(address: string, key: Uint8Array): Promise { + // just test contract existence + const _info = await this.getContract(address); + + return this.restClient.queryContractRaw(address, key); + } + + /** + * Makes a smart query on the contract, returns the parsed JSON document. + * + * Promise is rejected when contract does not exist. + * Promise is rejected for invalid query format. + * Promise is rejected for invalid response format. + */ + public async queryContractSmart(address: string, queryMsg: object): Promise { + try { + return await this.restClient.queryContractSmart(address, queryMsg); + } catch (error) { + if (error instanceof Error) { + if (error.message.startsWith("not found: contract")) { + throw new Error(`No contract found at address "${address}"`); + } else { + throw error; + } + } else { + throw error; + } + } + } + + private async txsQuery(query: string): Promise { + // TODO: we need proper pagination support + const limit = 100; + const result = await this.restClient.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/cosmwasm/src/index.ts b/packages/cosmwasm/src/index.ts new file mode 100644 index 00000000..1a189237 --- /dev/null +++ b/packages/cosmwasm/src/index.ts @@ -0,0 +1,34 @@ +import * as logs from "./logs"; +import * as types from "./types"; +export { logs, types }; + +export { BroadcastMode, RestClient, TxsResponse } from "./restclient"; +export { + Account, + Block, + BlockHeader, + Code, + CodeDetails, + Contract, + ContractDetails, + CosmWasmClient, + GetNonceResult, + IndexedTx, + PostTxResult, + SearchByHeightQuery, + SearchByIdQuery, + SearchBySentFromOrToQuery, + SearchByTagsQuery, + SearchTxQuery, + SearchTxFilter, +} from "./cosmwasmclient"; +export { decodeBech32Pubkey, encodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey"; +export { + ExecuteResult, + FeeTable, + InstantiateResult, + SigningCallback, + SigningCosmWasmClient, + UploadMeta, + UploadResult, +} from "./signingcosmwasmclient"; diff --git a/packages/cosmwasm/src/logs.spec.ts b/packages/cosmwasm/src/logs.spec.ts new file mode 100644 index 00000000..584d9ef2 --- /dev/null +++ b/packages/cosmwasm/src/logs.spec.ts @@ -0,0 +1,165 @@ +/* eslint-disable @typescript-eslint/camelcase */ +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/cosmwasm/src/logs.ts b/packages/cosmwasm/src/logs.ts new file mode 100644 index 00000000..e1eaa1cb --- /dev/null +++ b/packages/cosmwasm/src/logs.ts @@ -0,0 +1,86 @@ +/* eslint-disable @typescript-eslint/camelcase */ +import { isNonNullObject } from "@iov/encoding"; + +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: "message" | "transfer", + 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/cosmwasm/src/pubkey.spec.ts b/packages/cosmwasm/src/pubkey.spec.ts new file mode 100644 index 00000000..cb344f7b --- /dev/null +++ b/packages/cosmwasm/src/pubkey.spec.ts @@ -0,0 +1,57 @@ +import { Encoding } from "@iov/encoding"; + +import { decodeBech32Pubkey, encodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey"; +import { PubKey } from "./types"; + +const { fromBase64 } = Encoding; + +describe("pubkey", () => { + describe("encodeSecp256k1Pubkey", () => { + it("encodes a compresed pubkey", () => { + const pubkey = fromBase64("AtQaCqFnshaZQp6rIkvAPyzThvCvXSDO+9AzbxVErqJP"); + expect(encodeSecp256k1Pubkey(pubkey)).toEqual({ + type: "tendermint/PubKeySecp256k1", + value: "AtQaCqFnshaZQp6rIkvAPyzThvCvXSDO+9AzbxVErqJP", + }); + }); + + it("throws for uncompressed public keys", () => { + const pubkey = fromBase64( + "BE8EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQE7WHpoHoNswYeoFkuYpYSKK4mzFzMV/dB0DVAy4lnNU=", + ); + expect(() => encodeSecp256k1Pubkey(pubkey)).toThrowError(/public key must be compressed secp256k1/i); + }); + }); + + describe("decodeBech32Pubkey", () => { + it("works", () => { + expect( + decodeBech32Pubkey("cosmospub1addwnpepqd8sgxq7aw348ydctp3n5ajufgxp395hksxjzc6565yfp56scupfqhlgyg5"), + ).toEqual({ + type: "tendermint/PubKeySecp256k1", + value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ", + }); + }); + + it("works for enigma pubkey", () => { + expect( + decodeBech32Pubkey("enigmapub1addwnpepqw5k9p439nw0zpg2aundx4umwx4nw233z5prpjqjv5anl5grmnchzp2xwvv"), + ).toEqual({ + type: "tendermint/PubKeySecp256k1", + value: "A6lihrEs3PEFCu8m01ebcas3KjEVAjDIEmU7P9ED3PFx", + }); + }); + }); + + describe("encodeBech32Pubkey", () => { + it("works for secp256k1", () => { + const pubkey: PubKey = { + type: "tendermint/PubKeySecp256k1", + value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ", + }; + expect(encodeBech32Pubkey(pubkey, "cosmospub")).toEqual( + "cosmospub1addwnpepqd8sgxq7aw348ydctp3n5ajufgxp395hksxjzc6565yfp56scupfqhlgyg5", + ); + }); + }); +}); diff --git a/packages/cosmwasm/src/pubkey.ts b/packages/cosmwasm/src/pubkey.ts new file mode 100644 index 00000000..8835b97a --- /dev/null +++ b/packages/cosmwasm/src/pubkey.ts @@ -0,0 +1,71 @@ +import { Bech32, Encoding } from "@iov/encoding"; +import equal from "fast-deep-equal"; + +import { PubKey, pubkeyType } from "./types"; + +export function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey { + if (pubkey.length !== 33 || (pubkey[0] !== 0x02 && pubkey[0] !== 0x03)) { + throw new Error("Public key must be compressed secp256k1, i.e. 33 bytes starting with 0x02 or 0x03"); + } + return { + type: pubkeyType.secp256k1, + value: Encoding.toBase64(pubkey), + }; +} + +// As discussed in https://github.com/binance-chain/javascript-sdk/issues/163 +// Prefixes listed here: https://github.com/tendermint/tendermint/blob/d419fffe18531317c28c29a292ad7d253f6cafdf/docs/spec/blockchain/encoding.md#public-key-cryptography +// Last bytes is varint-encoded length prefix +const pubkeyAminoPrefixSecp256k1 = Encoding.fromHex("eb5ae98721"); +const pubkeyAminoPrefixEd25519 = Encoding.fromHex("1624de6420"); +const pubkeyAminoPrefixSr25519 = Encoding.fromHex("0dfb1005"); +const pubkeyAminoPrefixLength = pubkeyAminoPrefixSecp256k1.length; + +export function decodeBech32Pubkey(bechEncoded: string): PubKey { + const { data } = Bech32.decode(bechEncoded); + + const aminoPrefix = data.slice(0, pubkeyAminoPrefixLength); + const rest = data.slice(pubkeyAminoPrefixLength); + if (equal(aminoPrefix, pubkeyAminoPrefixSecp256k1)) { + if (rest.length !== 33) { + throw new Error("Invalid rest data length. Expected 33 bytes (compressed secp256k1 pubkey)."); + } + return { + type: pubkeyType.secp256k1, + value: Encoding.toBase64(rest), + }; + } else if (equal(aminoPrefix, pubkeyAminoPrefixEd25519)) { + if (rest.length !== 32) { + throw new Error("Invalid rest data length. Expected 32 bytes (Ed25519 pubkey)."); + } + return { + type: pubkeyType.ed25519, + value: Encoding.toBase64(rest), + }; + } else if (equal(aminoPrefix, pubkeyAminoPrefixSr25519)) { + if (rest.length !== 32) { + throw new Error("Invalid rest data length. Expected 32 bytes (Sr25519 pubkey)."); + } + return { + type: pubkeyType.sr25519, + value: Encoding.toBase64(rest), + }; + } else { + throw new Error("Unsupported Pubkey type. Amino prefix: " + Encoding.toHex(aminoPrefix)); + } +} + +export function encodeBech32Pubkey(pubkey: PubKey, prefix: string): string { + let aminoPrefix: Uint8Array; + switch (pubkey.type) { + // Note: please don't add cases here without writing additional unit tests + case pubkeyType.secp256k1: + aminoPrefix = pubkeyAminoPrefixSecp256k1; + break; + default: + throw new Error("Unsupported pubkey type"); + } + + const data = new Uint8Array([...aminoPrefix, ...Encoding.fromBase64(pubkey.value)]); + return Bech32.encode(prefix, data); +} diff --git a/packages/cosmwasm/src/restclient.spec.ts b/packages/cosmwasm/src/restclient.spec.ts new file mode 100644 index 00000000..dfe67396 --- /dev/null +++ b/packages/cosmwasm/src/restclient.spec.ts @@ -0,0 +1,1375 @@ +/* eslint-disable @typescript-eslint/camelcase */ +import { Coin, makeCosmoshubPath, Pen, rawSecp256k1PubkeyToAddress, Secp256k1Pen, makeSignBytes } from "@cosmwasm/sdk38"; +import { Sha256 } from "@iov/crypto"; +import { Encoding } from "@iov/encoding"; +import { assert, sleep } from "@iov/utils"; +import { ReadonlyDate } from "readonly-date"; + +import { findAttribute, parseLogs } from "./logs"; +import { encodeBech32Pubkey } from "./pubkey"; +import { PostTxsResponse, RestClient, TxsResponse } from "./restclient"; +import { SigningCosmWasmClient } from "./signingcosmwasmclient"; +import cosmoshub from "./testdata/cosmoshub.json"; +import { + bech32AddressMatcher, + deployedErc20, + faucet, + fromOneElementArray, + getHackatom, + makeRandomAddress, + nonNegativeIntegerMatcher, + pendingWithoutWasmd, + semverMatcher, + tendermintAddressMatcher, + tendermintIdMatcher, + tendermintOptionalIdMatcher, + tendermintShortHashMatcher, + unused, + wasmd, + wasmdEnabled, +} from "./testutils.spec"; +import { + isMsgInstantiateContract, + isMsgStoreCode, + Msg, + MsgExecuteContract, + MsgInstantiateContract, + MsgSend, + MsgStoreCode, + StdFee, + StdSignature, + StdTx, +} from "./types"; + +const { fromAscii, fromBase64, fromHex, toAscii, toBase64, toHex } = Encoding; + +const emptyAddress = "cosmos1ltkhnmdcqemmd2tkhnx7qx66tq7e0wykw2j85k"; + +function makeSignedTx(firstMsg: Msg, fee: StdFee, memo: string, firstSignature: StdSignature): StdTx { + return { + msg: [firstMsg], + fee: fee, + memo: memo, + signatures: [firstSignature], + }; +} + +async function uploadCustomContract( + client: RestClient, + pen: Pen, + wasmCode: Uint8Array, +): Promise { + const memo = "My first contract on chain"; + const theMsg: MsgStoreCode = { + type: "wasm/store-code", + value: { + sender: faucet.address, + wasm_byte_code: toBase64(wasmCode), + source: "https://github.com/confio/cosmwasm/raw/0.7/lib/vm/testdata/contract_0.6.wasm", + builder: "confio/cosmwasm-opt:0.6.2", + }, + }; + const fee: StdFee = { + amount: [ + { + amount: "5000000", + denom: "ucosm", + }, + ], + gas: "89000000", + }; + + const { account_number, sequence } = (await client.authAccounts(faucet.address)).result.value; + const signBytes = makeSignBytes([theMsg], fee, wasmd.chainId, memo, account_number, sequence); + const signature = await pen.sign(signBytes); + const signedTx = makeSignedTx(theMsg, fee, memo, signature); + return client.postTx(signedTx); +} + +async function uploadContract(client: RestClient, pen: Pen): Promise { + return uploadCustomContract(client, pen, getHackatom()); +} + +async function instantiateContract( + client: RestClient, + pen: Pen, + codeId: number, + beneficiaryAddress: string, + transferAmount?: readonly Coin[], +): Promise { + const memo = "Create an escrow instance"; + const theMsg: MsgInstantiateContract = { + type: "wasm/instantiate", + value: { + sender: faucet.address, + code_id: codeId.toString(), + label: "my escrow", + init_msg: { + verifier: faucet.address, + beneficiary: beneficiaryAddress, + }, + init_funds: transferAmount || [], + }, + }; + const fee: StdFee = { + amount: [ + { + amount: "5000000", + denom: "ucosm", + }, + ], + gas: "89000000", + }; + + const { account_number, sequence } = (await client.authAccounts(faucet.address)).result.value; + const signBytes = makeSignBytes([theMsg], fee, wasmd.chainId, memo, account_number, sequence); + const signature = await pen.sign(signBytes); + const signedTx = makeSignedTx(theMsg, fee, memo, signature); + return client.postTx(signedTx); +} + +async function executeContract( + client: RestClient, + pen: Pen, + contractAddress: string, +): Promise { + const memo = "Time for action"; + const theMsg: MsgExecuteContract = { + type: "wasm/execute", + value: { + sender: faucet.address, + contract: contractAddress, + msg: { release: {} }, + sent_funds: [], + }, + }; + const fee: StdFee = { + amount: [ + { + amount: "5000000", + denom: "ucosm", + }, + ], + gas: "89000000", + }; + + const { account_number, sequence } = (await client.authAccounts(faucet.address)).result.value; + const signBytes = makeSignBytes([theMsg], fee, wasmd.chainId, memo, account_number, sequence); + const signature = await pen.sign(signBytes); + const signedTx = makeSignedTx(theMsg, fee, memo, signature); + return client.postTx(signedTx); +} + +describe("RestClient", () => { + it("can be constructed", () => { + const client = new RestClient(wasmd.endpoint); + expect(client).toBeTruthy(); + }); + + // The /auth endpoints + + describe("authAccounts", () => { + it("works for unused account without pubkey", async () => { + pendingWithoutWasmd(); + const client = new RestClient(wasmd.endpoint); + const { height, result } = await client.authAccounts(unused.address); + expect(height).toMatch(nonNegativeIntegerMatcher); + expect(result).toEqual({ + type: "cosmos-sdk/Account", + value: { + address: unused.address, + public_key: "", // not known to the chain + coins: [ + { + amount: "1000000000", + denom: "ucosm", + }, + { + amount: "1000000000", + denom: "ustake", + }, + ], + account_number: unused.accountNumber, + sequence: 0, + }, + }); + }); + + // This fails in the first test run if you forget to run `./scripts/wasmd/init.sh` + it("has correct pubkey for faucet", async () => { + pendingWithoutWasmd(); + const client = new RestClient(wasmd.endpoint); + const { result } = await client.authAccounts(faucet.address); + expect(result.value).toEqual( + jasmine.objectContaining({ + public_key: encodeBech32Pubkey(faucet.pubkey, "cosmospub"), + }), + ); + }); + + // This property is used by CosmWasmClient.getAccount + it("returns empty address for non-existent account", async () => { + pendingWithoutWasmd(); + const client = new RestClient(wasmd.endpoint); + const nonExistentAccount = makeRandomAddress(); + const { result } = await client.authAccounts(nonExistentAccount); + expect(result).toEqual({ + type: "cosmos-sdk/Account", + value: jasmine.objectContaining({ address: "" }), + }); + }); + }); + + // The /blocks endpoints + + describe("blocksLatest", () => { + it("works", async () => { + pendingWithoutWasmd(); + const client = new RestClient(wasmd.endpoint); + const response = await client.blocksLatest(); + + // id + expect(response.block_id.hash).toMatch(tendermintIdMatcher); + + // header + expect(response.block.header.version).toEqual({ block: "10", app: "0" }); + expect(parseInt(response.block.header.height, 10)).toBeGreaterThanOrEqual(1); + expect(response.block.header.chain_id).toEqual(wasmd.chainId); + expect(new ReadonlyDate(response.block.header.time).getTime()).toBeLessThan(ReadonlyDate.now()); + expect(new ReadonlyDate(response.block.header.time).getTime()).toBeGreaterThanOrEqual( + ReadonlyDate.now() - 5_000, + ); + expect(response.block.header.last_commit_hash).toMatch(tendermintIdMatcher); + expect(response.block.header.last_block_id.hash).toMatch(tendermintIdMatcher); + expect(response.block.header.data_hash).toMatch(tendermintOptionalIdMatcher); + expect(response.block.header.validators_hash).toMatch(tendermintIdMatcher); + expect(response.block.header.next_validators_hash).toMatch(tendermintIdMatcher); + expect(response.block.header.consensus_hash).toMatch(tendermintIdMatcher); + expect(response.block.header.app_hash).toMatch(tendermintIdMatcher); + expect(response.block.header.last_results_hash).toMatch(tendermintOptionalIdMatcher); + expect(response.block.header.evidence_hash).toMatch(tendermintOptionalIdMatcher); + expect(response.block.header.proposer_address).toMatch(tendermintAddressMatcher); + + // data + expect(response.block.data.txs === null || Array.isArray(response.block.data.txs)).toEqual(true); + }); + }); + + describe("blocks", () => { + it("works for block by height", async () => { + pendingWithoutWasmd(); + const client = new RestClient(wasmd.endpoint); + const height = parseInt((await client.blocksLatest()).block.header.height, 10); + const response = await client.blocks(height - 1); + + // id + expect(response.block_id.hash).toMatch(tendermintIdMatcher); + + // header + expect(response.block.header.version).toEqual({ block: "10", app: "0" }); + expect(response.block.header.height).toEqual(`${height - 1}`); + expect(response.block.header.chain_id).toEqual(wasmd.chainId); + expect(new ReadonlyDate(response.block.header.time).getTime()).toBeLessThan(ReadonlyDate.now()); + expect(new ReadonlyDate(response.block.header.time).getTime()).toBeGreaterThanOrEqual( + ReadonlyDate.now() - 5_000, + ); + expect(response.block.header.last_commit_hash).toMatch(tendermintIdMatcher); + expect(response.block.header.last_block_id.hash).toMatch(tendermintIdMatcher); + expect(response.block.header.data_hash).toMatch(tendermintOptionalIdMatcher); + expect(response.block.header.validators_hash).toMatch(tendermintIdMatcher); + expect(response.block.header.next_validators_hash).toMatch(tendermintIdMatcher); + expect(response.block.header.consensus_hash).toMatch(tendermintIdMatcher); + expect(response.block.header.app_hash).toMatch(tendermintIdMatcher); + expect(response.block.header.last_results_hash).toMatch(tendermintOptionalIdMatcher); + expect(response.block.header.evidence_hash).toMatch(tendermintOptionalIdMatcher); + expect(response.block.header.proposer_address).toMatch(tendermintAddressMatcher); + + // data + expect(response.block.data.txs === null || Array.isArray(response.block.data.txs)).toEqual(true); + }); + }); + + // The /node_info endpoint + + describe("nodeInfo", () => { + it("works", async () => { + pendingWithoutWasmd(); + const client = new RestClient(wasmd.endpoint); + const { node_info, application_version } = await client.nodeInfo(); + + expect(node_info).toEqual({ + protocol_version: { p2p: "7", block: "10", app: "0" }, + id: jasmine.stringMatching(tendermintShortHashMatcher), + listen_addr: "tcp://0.0.0.0:26656", + network: wasmd.chainId, + version: jasmine.stringMatching(/^0\.33\.[0-9]+$/), + channels: "4020212223303800", + moniker: wasmd.chainId, + other: { tx_index: "on", rpc_address: "tcp://0.0.0.0:26657" }, + }); + expect(application_version).toEqual({ + name: "wasm", + server_name: "wasmd", + client_name: "wasmcli", + version: jasmine.stringMatching(semverMatcher), + commit: jasmine.stringMatching(tendermintShortHashMatcher), + build_tags: "netgo,ledger", + go: jasmine.stringMatching(/^go version go1\.[0-9]+\.[0-9]+ linux\/amd64$/), + }); + }); + }); + + // 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 (wasmdEnabled()) { + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); + const client = new SigningCosmWasmClient(wasmd.endpoint, faucet.address, (signBytes) => + pen.sign(signBytes), + ); + + { + const recipient = makeRandomAddress(); + const transferAmount = { + denom: "ucosm", + amount: "1234567", + }; + const result = await client.sendTokens(recipient, [transferAmount]); + successful = { + sender: faucet.address, + recipient: recipient, + hash: result.transactionHash, + }; + } + + { + const memo = "Sending more than I can afford"; + const recipient = makeRandomAddress(); + const transferAmount = [ + { + denom: "ucosm", + amount: "123456700000000", + }, + ]; + const sendMsg: MsgSend = { + type: "cosmos-sdk/MsgSend", + value: { + // eslint-disable-next-line @typescript-eslint/camelcase + from_address: faucet.address, + // eslint-disable-next-line @typescript-eslint/camelcase + to_address: recipient, + amount: transferAmount, + }, + }; + const fee = { + amount: [ + { + denom: "ucosm", + amount: "2000", + }, + ], + gas: "80000", // 80k + }; + const { accountNumber, sequence } = await client.getNonce(); + const chainId = await client.getChainId(); + const signBytes = makeSignBytes([sendMsg], fee, chainId, memo, accountNumber, sequence); + const signature = await pen.sign(signBytes); + const signedTx = { + msg: [sendMsg], + fee: fee, + memo: memo, + signatures: [signature], + }; + const transactionId = await client.getIdentifier({ type: "cosmos-sdk/StdTx", value: signedTx }); + try { + await client.postTx(signedTx); + } catch (error) { + // postTx() throws on execution failures, which is a questionable design. Ignore for now. + // console.log(error); + } + unsuccessful = { + sender: faucet.address, + recipient: recipient, + hash: transactionId, + }; + } + + await sleep(50); // wait until transactions are indexed + } + }); + + it("works for successful transaction", async () => { + pendingWithoutWasmd(); + assert(successful); + const client = new RestClient(wasmd.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 () => { + pendingWithoutWasmd(); + assert(unsuccessful); + const client = new RestClient(wasmd.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 posted: + | { + readonly sender: string; + readonly recipient: string; + readonly hash: string; + readonly height: number; + readonly tx: TxsResponse; + } + | undefined; + + beforeAll(async () => { + if (wasmdEnabled()) { + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); + const client = new SigningCosmWasmClient(wasmd.endpoint, faucet.address, (signBytes) => + pen.sign(signBytes), + ); + + const recipient = makeRandomAddress(); + const transferAmount = [ + { + denom: "ucosm", + amount: "1234567", + }, + ]; + const result = await client.sendTokens(recipient, transferAmount); + + await sleep(50); // wait until tx is indexed + const txDetails = await new RestClient(wasmd.endpoint).txById(result.transactionHash); + posted = { + sender: faucet.address, + recipient: recipient, + hash: result.transactionHash, + height: Number.parseInt(txDetails.height, 10), + tx: txDetails, + }; + } + }); + + it("can query transactions by height", async () => { + pendingWithoutWasmd(); + assert(posted); + const client = new RestClient(wasmd.endpoint); + const result = await client.txsQuery(`tx.height=${posted.height}&limit=26`); + expect(result).toEqual({ + count: "1", + limit: "26", + page_number: "1", + page_total: "1", + total_count: "1", + txs: [posted.tx], + }); + }); + + it("can query transactions by ID", async () => { + pendingWithoutWasmd(); + assert(posted); + const client = new RestClient(wasmd.endpoint); + const result = await client.txsQuery(`tx.hash=${posted.hash}&limit=26`); + expect(result).toEqual({ + count: "1", + limit: "26", + page_number: "1", + page_total: "1", + total_count: "1", + txs: [posted.tx], + }); + }); + + it("can query transactions by sender", async () => { + pendingWithoutWasmd(); + assert(posted); + const client = new RestClient(wasmd.endpoint); + const result = await client.txsQuery(`message.sender=${posted.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(posted.tx); + }); + + it("can query transactions by recipient", async () => { + pendingWithoutWasmd(); + assert(posted); + const client = new RestClient(wasmd.endpoint); + const result = await client.txsQuery(`transfer.recipient=${posted.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(posted.tx); + }); + + it("can filter by tx.hash and tx.minheight", async () => { + pending("This combination is broken 🤷‍♂️. Handle client-side at higher level."); + pendingWithoutWasmd(); + assert(posted); + const client = new RestClient(wasmd.endpoint); + const hashQuery = `tx.hash=${posted.hash}`; + + { + const { count } = await client.txsQuery(`${hashQuery}&tx.minheight=0`); + expect(count).toEqual("1"); + } + + { + const { count } = await client.txsQuery(`${hashQuery}&tx.minheight=${posted.height - 1}`); + expect(count).toEqual("1"); + } + + { + const { count } = await client.txsQuery(`${hashQuery}&tx.minheight=${posted.height}`); + expect(count).toEqual("1"); + } + + { + const { count } = await client.txsQuery(`${hashQuery}&tx.minheight=${posted.height + 1}`); + expect(count).toEqual("0"); + } + }); + + it("can filter by recipient and tx.minheight", async () => { + pendingWithoutWasmd(); + assert(posted); + const client = new RestClient(wasmd.endpoint); + const recipientQuery = `transfer.recipient=${posted.recipient}`; + + { + const { count } = await client.txsQuery(`${recipientQuery}&tx.minheight=0`); + expect(count).toEqual("1"); + } + + { + const { count } = await client.txsQuery(`${recipientQuery}&tx.minheight=${posted.height - 1}`); + expect(count).toEqual("1"); + } + + { + const { count } = await client.txsQuery(`${recipientQuery}&tx.minheight=${posted.height}`); + expect(count).toEqual("1"); + } + + { + const { count } = await client.txsQuery(`${recipientQuery}&tx.minheight=${posted.height + 1}`); + expect(count).toEqual("0"); + } + }); + + it("can filter by recipient and tx.maxheight", async () => { + pendingWithoutWasmd(); + assert(posted); + const client = new RestClient(wasmd.endpoint); + const recipientQuery = `transfer.recipient=${posted.recipient}`; + + { + const { count } = await client.txsQuery(`${recipientQuery}&tx.maxheight=9999999999999`); + expect(count).toEqual("1"); + } + + { + const { count } = await client.txsQuery(`${recipientQuery}&tx.maxheight=${posted.height + 1}`); + expect(count).toEqual("1"); + } + + { + const { count } = await client.txsQuery(`${recipientQuery}&tx.maxheight=${posted.height}`); + expect(count).toEqual("1"); + } + + { + const { count } = await client.txsQuery(`${recipientQuery}&tx.maxheight=${posted.height - 1}`); + expect(count).toEqual("0"); + } + }); + + it("can query by tags (module + code_id)", async () => { + pendingWithoutWasmd(); + assert(posted); + const client = new RestClient(wasmd.endpoint); + const result = await client.txsQuery(`message.module=wasm&message.code_id=${deployedErc20.codeId}`); + expect(parseInt(result.count, 10)).toBeGreaterThanOrEqual(4); + + // Check first 4 results + const [store, hash, isa, jade] = result.txs.map((tx) => fromOneElementArray(tx.tx.value.msg)); + assert(isMsgStoreCode(store)); + assert(isMsgInstantiateContract(hash)); + assert(isMsgInstantiateContract(isa)); + assert(isMsgInstantiateContract(jade)); + expect(store.value).toEqual( + jasmine.objectContaining({ + sender: faucet.address, + source: deployedErc20.source, + builder: deployedErc20.builder, + }), + ); + expect(hash.value).toEqual({ + code_id: deployedErc20.codeId.toString(), + init_funds: [], + init_msg: jasmine.objectContaining({ + symbol: "HASH", + }), + label: "HASH", + sender: faucet.address, + }); + expect(isa.value).toEqual({ + code_id: deployedErc20.codeId.toString(), + init_funds: [], + init_msg: jasmine.objectContaining({ symbol: "ISA" }), + label: "ISA", + sender: faucet.address, + }); + expect(jade.value).toEqual({ + code_id: deployedErc20.codeId.toString(), + init_funds: [], + init_msg: jasmine.objectContaining({ symbol: "JADE" }), + label: "JADE", + sender: faucet.address, + }); + }); + + // Like previous test but filtered by message.action=store-code and message.action=instantiate + it("can query by tags (module + code_id + action)", async () => { + pendingWithoutWasmd(); + assert(posted); + const client = new RestClient(wasmd.endpoint); + + { + const uploads = await client.txsQuery( + `message.module=wasm&message.code_id=${deployedErc20.codeId}&message.action=store-code`, + ); + expect(parseInt(uploads.count, 10)).toEqual(1); + const store = fromOneElementArray(uploads.txs[0].tx.value.msg); + assert(isMsgStoreCode(store)); + expect(store.value).toEqual( + jasmine.objectContaining({ + sender: faucet.address, + source: deployedErc20.source, + builder: deployedErc20.builder, + }), + ); + } + + { + const instantiations = await client.txsQuery( + `message.module=wasm&message.code_id=${deployedErc20.codeId}&message.action=instantiate`, + ); + expect(parseInt(instantiations.count, 10)).toBeGreaterThanOrEqual(3); + const [hash, isa, jade] = instantiations.txs.map((tx) => fromOneElementArray(tx.tx.value.msg)); + assert(isMsgInstantiateContract(hash)); + assert(isMsgInstantiateContract(isa)); + assert(isMsgInstantiateContract(jade)); + expect(hash.value).toEqual({ + code_id: deployedErc20.codeId.toString(), + init_funds: [], + init_msg: jasmine.objectContaining({ + symbol: "HASH", + }), + label: "HASH", + sender: faucet.address, + }); + expect(isa.value).toEqual({ + code_id: deployedErc20.codeId.toString(), + init_funds: [], + init_msg: jasmine.objectContaining({ symbol: "ISA" }), + label: "ISA", + sender: faucet.address, + }); + expect(jade.value).toEqual({ + code_id: deployedErc20.codeId.toString(), + init_funds: [], + init_msg: jasmine.objectContaining({ symbol: "JADE" }), + label: "JADE", + sender: faucet.address, + }); + } + }); + }); + + describe("encodeTx", () => { + it("works for cosmoshub example", async () => { + pendingWithoutWasmd(); + const client = new RestClient(wasmd.endpoint); + expect(await client.encodeTx(cosmoshub.tx)).toEqual(fromBase64(cosmoshub.tx_data)); + }); + }); + + describe("postTx", () => { + it("can send tokens", async () => { + pendingWithoutWasmd(); + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); + + const memo = "My first contract on chain"; + const theMsg: MsgSend = { + type: "cosmos-sdk/MsgSend", + value: { + from_address: faucet.address, + to_address: emptyAddress, + amount: [ + { + denom: "ucosm", + amount: "1234567", + }, + ], + }, + }; + + const fee: StdFee = { + amount: [ + { + amount: "5000", + denom: "ucosm", + }, + ], + gas: "890000", + }; + + const client = new RestClient(wasmd.endpoint); + const { account_number, sequence } = (await client.authAccounts(faucet.address)).result.value; + + const signBytes = makeSignBytes([theMsg], fee, wasmd.chainId, memo, account_number, sequence); + const signature = await pen.sign(signBytes); + const signedTx = makeSignedTx(theMsg, fee, memo, signature); + const result = await client.postTx(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 () => { + pendingWithoutWasmd(); + const account1 = await Secp256k1Pen.fromMnemonic(faucet.mnemonic, makeCosmoshubPath(0)); + const account2 = await Secp256k1Pen.fromMnemonic(faucet.mnemonic, makeCosmoshubPath(1)); + const account3 = await Secp256k1Pen.fromMnemonic(faucet.mnemonic, makeCosmoshubPath(2)); + const address1 = rawSecp256k1PubkeyToAddress(account1.pubkey, "cosmos"); + const address2 = rawSecp256k1PubkeyToAddress(account2.pubkey, "cosmos"); + const address3 = rawSecp256k1PubkeyToAddress(account3.pubkey, "cosmos"); + + const memo = "My first contract on chain"; + const theMsg: MsgSend = { + type: "cosmos-sdk/MsgSend", + value: { + from_address: address1, + to_address: emptyAddress, + amount: [ + { + denom: "ucosm", + amount: "1234567", + }, + ], + }, + }; + + const fee: StdFee = { + amount: [ + { + amount: "5000", + denom: "ucosm", + }, + ], + gas: "890000", + }; + + const client = new RestClient(wasmd.endpoint); + const { account_number: an1, sequence: sequence1 } = (await client.authAccounts(address1)).result.value; + const { account_number: an2, sequence: sequence2 } = (await client.authAccounts(address2)).result.value; + const { account_number: an3, sequence: sequence3 } = (await client.authAccounts(address3)).result.value; + + const signBytes1 = makeSignBytes([theMsg], fee, wasmd.chainId, memo, an1, sequence1); + const signBytes2 = makeSignBytes([theMsg], fee, wasmd.chainId, memo, an2, sequence2); + const signBytes3 = makeSignBytes([theMsg], fee, wasmd.chainId, memo, an3, sequence3); + const signature1 = await account1.sign(signBytes1); + const signature2 = await account2.sign(signBytes2); + const signature3 = await account3.sign(signBytes3); + const signedTx = { + msg: [theMsg], + fee: fee, + memo: memo, + signatures: [signature1, signature2, signature3], + }; + const postResult = await client.postTx(signedTx); + // console.log(postResult.raw_log); + expect(postResult.code).toEqual(4); + expect(postResult.raw_log).toContain("wrong number of signers"); + }); + + it("can send multiple messages with one signature", async () => { + pendingWithoutWasmd(); + const account1 = await Secp256k1Pen.fromMnemonic(faucet.mnemonic, makeCosmoshubPath(0)); + const address1 = rawSecp256k1PubkeyToAddress(account1.pubkey, "cosmos"); + + const memo = "My first contract on chain"; + const msg1: MsgSend = { + type: "cosmos-sdk/MsgSend", + value: { + from_address: address1, + to_address: emptyAddress, + amount: [ + { + denom: "ucosm", + amount: "1234567", + }, + ], + }, + }; + const msg2: MsgSend = { + type: "cosmos-sdk/MsgSend", + value: { + from_address: address1, + to_address: emptyAddress, + amount: [ + { + denom: "ucosm", + amount: "7654321", + }, + ], + }, + }; + + const fee: StdFee = { + amount: [ + { + amount: "5000", + denom: "ucosm", + }, + ], + gas: "890000", + }; + + const client = new RestClient(wasmd.endpoint); + const { account_number, sequence } = (await client.authAccounts(address1)).result.value; + + const signBytes = makeSignBytes([msg1, msg2], fee, wasmd.chainId, memo, account_number, sequence); + const signature1 = await account1.sign(signBytes); + const signedTx = { + msg: [msg1, msg2], + fee: fee, + memo: memo, + signatures: [signature1], + }; + const postResult = await client.postTx(signedTx); + // console.log(postResult.raw_log); + expect(postResult.code).toBeUndefined(); + }); + + it("can send multiple messages with multiple signatures", async () => { + pendingWithoutWasmd(); + const account1 = await Secp256k1Pen.fromMnemonic(faucet.mnemonic, makeCosmoshubPath(0)); + const account2 = await Secp256k1Pen.fromMnemonic(faucet.mnemonic, makeCosmoshubPath(1)); + const address1 = rawSecp256k1PubkeyToAddress(account1.pubkey, "cosmos"); + const address2 = rawSecp256k1PubkeyToAddress(account2.pubkey, "cosmos"); + + const memo = "My first contract on chain"; + const msg1: MsgSend = { + type: "cosmos-sdk/MsgSend", + value: { + from_address: address1, + to_address: emptyAddress, + amount: [ + { + denom: "ucosm", + amount: "1234567", + }, + ], + }, + }; + const msg2: MsgSend = { + type: "cosmos-sdk/MsgSend", + value: { + from_address: address2, + to_address: emptyAddress, + amount: [ + { + denom: "ucosm", + amount: "7654321", + }, + ], + }, + }; + + const fee: StdFee = { + amount: [ + { + amount: "5000", + denom: "ucosm", + }, + ], + gas: "890000", + }; + + const client = new RestClient(wasmd.endpoint); + const { account_number: an1, sequence: sequence1 } = (await client.authAccounts(address1)).result.value; + const { account_number: an2, sequence: sequence2 } = (await client.authAccounts(address2)).result.value; + + const signBytes1 = makeSignBytes([msg2, msg1], fee, wasmd.chainId, memo, an1, sequence1); + const signBytes2 = makeSignBytes([msg2, msg1], fee, wasmd.chainId, memo, an2, sequence2); + const signature1 = await account1.sign(signBytes1); + const signature2 = await account2.sign(signBytes2); + const signedTx = { + msg: [msg2, msg1], + fee: fee, + memo: memo, + signatures: [signature2, signature1], + }; + const postResult = await client.postTx(signedTx); + // console.log(postResult.raw_log); + expect(postResult.code).toBeUndefined(); + + await sleep(500); + const searched = await client.txsQuery(`tx.hash=${postResult.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 () => { + pendingWithoutWasmd(); + const account1 = await Secp256k1Pen.fromMnemonic(faucet.mnemonic, makeCosmoshubPath(0)); + const account2 = await Secp256k1Pen.fromMnemonic(faucet.mnemonic, makeCosmoshubPath(1)); + const address1 = rawSecp256k1PubkeyToAddress(account1.pubkey, "cosmos"); + const address2 = rawSecp256k1PubkeyToAddress(account2.pubkey, "cosmos"); + + const memo = "My first contract on chain"; + const msg1: MsgSend = { + type: "cosmos-sdk/MsgSend", + value: { + from_address: address1, + to_address: emptyAddress, + amount: [ + { + denom: "ucosm", + amount: "1234567", + }, + ], + }, + }; + const msg2: MsgSend = { + type: "cosmos-sdk/MsgSend", + value: { + from_address: address2, + to_address: emptyAddress, + amount: [ + { + denom: "ucosm", + amount: "7654321", + }, + ], + }, + }; + + const fee: StdFee = { + amount: [ + { + amount: "5000", + denom: "ucosm", + }, + ], + gas: "890000", + }; + + const client = new RestClient(wasmd.endpoint); + const { account_number: an1, sequence: sequence1 } = (await client.authAccounts(address1)).result.value; + const { account_number: an2, sequence: sequence2 } = (await client.authAccounts(address2)).result.value; + + const signBytes1 = makeSignBytes([msg1, msg2], fee, wasmd.chainId, memo, an1, sequence1); + const signBytes2 = makeSignBytes([msg1, msg2], fee, wasmd.chainId, memo, an2, sequence2); + const signature1 = await account1.sign(signBytes1); + const signature2 = await account2.sign(signBytes2); + const signedTx = { + msg: [msg1, msg2], + fee: fee, + memo: memo, + signatures: [signature2, signature1], + }; + const postResult = await client.postTx(signedTx); + // console.log(postResult.raw_log); + expect(postResult.code).toEqual(8); + }); + + it("can't send transaction with wrong signature order (2)", async () => { + pendingWithoutWasmd(); + const account1 = await Secp256k1Pen.fromMnemonic(faucet.mnemonic, makeCosmoshubPath(0)); + const account2 = await Secp256k1Pen.fromMnemonic(faucet.mnemonic, makeCosmoshubPath(1)); + const address1 = rawSecp256k1PubkeyToAddress(account1.pubkey, "cosmos"); + const address2 = rawSecp256k1PubkeyToAddress(account2.pubkey, "cosmos"); + + const memo = "My first contract on chain"; + const msg1: MsgSend = { + type: "cosmos-sdk/MsgSend", + value: { + from_address: address1, + to_address: emptyAddress, + amount: [ + { + denom: "ucosm", + amount: "1234567", + }, + ], + }, + }; + const msg2: MsgSend = { + type: "cosmos-sdk/MsgSend", + value: { + from_address: address2, + to_address: emptyAddress, + amount: [ + { + denom: "ucosm", + amount: "7654321", + }, + ], + }, + }; + + const fee: StdFee = { + amount: [ + { + amount: "5000", + denom: "ucosm", + }, + ], + gas: "890000", + }; + + const client = new RestClient(wasmd.endpoint); + const { account_number: an1, sequence: sequence1 } = (await client.authAccounts(address1)).result.value; + const { account_number: an2, sequence: sequence2 } = (await client.authAccounts(address2)).result.value; + + const signBytes1 = makeSignBytes([msg2, msg1], fee, wasmd.chainId, memo, an1, sequence1); + const signBytes2 = makeSignBytes([msg2, msg1], fee, wasmd.chainId, memo, an2, sequence2); + const signature1 = await account1.sign(signBytes1); + const signature2 = await account2.sign(signBytes2); + const signedTx = { + msg: [msg2, msg1], + fee: fee, + memo: memo, + signatures: [signature1, signature2], + }; + const postResult = await client.postTx(signedTx); + // console.log(postResult.raw_log); + expect(postResult.code).toEqual(8); + }); + + it("can upload, instantiate and execute wasm", async () => { + pendingWithoutWasmd(); + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); + const client = new RestClient(wasmd.endpoint); + + const transferAmount: readonly Coin[] = [ + { + amount: "1234", + denom: "ucosm", + }, + { + amount: "321", + denom: "ustake", + }, + ]; + const beneficiaryAddress = makeRandomAddress(); + + let codeId: number; + + // upload + { + // console.log("Raw log:", result.raw_log); + const result = await uploadContract(client, pen); + expect(result.code).toBeFalsy(); + const logs = parseLogs(result.logs); + const codeIdAttr = findAttribute(logs, "message", "code_id"); + codeId = Number.parseInt(codeIdAttr.value, 10); + expect(codeId).toBeGreaterThanOrEqual(1); + expect(codeId).toBeLessThanOrEqual(200); + } + + let contractAddress: string; + + // instantiate + { + const result = await instantiateContract(client, pen, codeId, beneficiaryAddress, transferAmount); + expect(result.code).toBeFalsy(); + // console.log("Raw log:", result.raw_log); + const logs = parseLogs(result.logs); + const contractAddressAttr = findAttribute(logs, "message", "contract_address"); + contractAddress = contractAddressAttr.value; + const amountAttr = findAttribute(logs, "transfer", "amount"); + expect(amountAttr.value).toEqual("1234ucosm,321ustake"); + + const balance = (await client.authAccounts(contractAddress)).result.value.coins; + expect(balance).toEqual(transferAmount); + } + + // execute + { + const result = await executeContract(client, pen, contractAddress); + expect(result.code).toBeFalsy(); + // console.log("Raw log:", result.logs); + const logs = parseLogs(result.logs); + const wasmEvent = logs.find(() => true)?.events.find((e) => e.type === "wasm"); + assert(wasmEvent, "Event of type wasm expected"); + expect(wasmEvent.attributes).toContain({ key: "action", value: "release" }); + expect(wasmEvent.attributes).toContain({ + key: "destination", + value: beneficiaryAddress, + }); + + // Verify token transfer from contract to beneficiary + const beneficiaryBalance = (await client.authAccounts(beneficiaryAddress)).result.value.coins; + expect(beneficiaryBalance).toEqual(transferAmount); + const contractBalance = (await client.authAccounts(contractAddress)).result.value.coins; + expect(contractBalance).toEqual([]); + } + }); + }); + + // The /wasm endpoints + + describe("query", () => { + it("can list upload code", async () => { + pendingWithoutWasmd(); + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); + const client = new RestClient(wasmd.endpoint); + + // check with contracts were here first to compare + const existingInfos = await client.listCodeInfo(); + existingInfos.forEach((val, idx) => expect(val.id).toEqual(idx + 1)); + const numExisting = existingInfos.length; + + // upload data + const wasmCode = getHackatom(); + const result = await uploadCustomContract(client, pen, wasmCode); + expect(result.code).toBeFalsy(); + const logs = parseLogs(result.logs); + const codeIdAttr = findAttribute(logs, "message", "code_id"); + const codeId = Number.parseInt(codeIdAttr.value, 10); + + // ensure we were added to the end of the list + const newInfos = await client.listCodeInfo(); + expect(newInfos.length).toEqual(numExisting + 1); + const lastInfo = newInfos[newInfos.length - 1]; + expect(lastInfo.id).toEqual(codeId); + expect(lastInfo.creator).toEqual(faucet.address); + + // ensure metadata is present + expect(lastInfo.source).toEqual( + "https://github.com/confio/cosmwasm/raw/0.7/lib/vm/testdata/contract_0.6.wasm", + ); + expect(lastInfo.builder).toEqual("confio/cosmwasm-opt:0.6.2"); + + // check code hash matches expectation + const wasmHash = new Sha256(wasmCode).digest(); + expect(lastInfo.data_hash.toLowerCase()).toEqual(toHex(wasmHash)); + + // download code and check against auto-gen + const { data } = await client.getCode(codeId); + expect(fromBase64(data)).toEqual(wasmCode); + }); + + it("can list contracts and get info", async () => { + pendingWithoutWasmd(); + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); + const client = new RestClient(wasmd.endpoint); + const beneficiaryAddress = makeRandomAddress(); + const transferAmount: readonly Coin[] = [ + { + amount: "707707", + denom: "ucosm", + }, + ]; + + // reuse an existing contract, or upload if needed + let codeId: number; + const existingInfos = await client.listCodeInfo(); + if (existingInfos.length > 0) { + codeId = existingInfos[existingInfos.length - 1].id; + } else { + const uploadResult = await uploadContract(client, pen); + expect(uploadResult.code).toBeFalsy(); + const uploadLogs = parseLogs(uploadResult.logs); + const codeIdAttr = findAttribute(uploadLogs, "message", "code_id"); + codeId = Number.parseInt(codeIdAttr.value, 10); + } + + // create new instance and compare before and after + const existingContractsByCode = await client.listContractsByCodeId(codeId); + for (const contract of existingContractsByCode) { + expect(contract.address).toMatch(bech32AddressMatcher); + expect(contract.code_id).toEqual(codeId); + expect(contract.creator).toMatch(bech32AddressMatcher); + expect(contract.label).toMatch(/^.+$/); + } + + const result = await instantiateContract(client, pen, codeId, beneficiaryAddress, transferAmount); + expect(result.code).toBeFalsy(); + const logs = parseLogs(result.logs); + const contractAddressAttr = findAttribute(logs, "message", "contract_address"); + const myAddress = contractAddressAttr.value; + + const newContractsByCode = await client.listContractsByCodeId(codeId); + expect(newContractsByCode.length).toEqual(existingContractsByCode.length + 1); + const newContract = newContractsByCode[newContractsByCode.length - 1]; + expect(newContract).toEqual( + jasmine.objectContaining({ + code_id: codeId, + creator: faucet.address, + label: "my escrow", + }), + ); + + // check out info + const myInfo = await client.getContractInfo(myAddress); + assert(myInfo); + expect(myInfo.code_id).toEqual(codeId); + expect(myInfo.creator).toEqual(faucet.address); + expect((myInfo.init_msg as any).beneficiary).toEqual(beneficiaryAddress); + + // make sure random addresses don't give useful info + const nonExistentAddress = makeRandomAddress(); + expect(await client.getContractInfo(nonExistentAddress)).toBeNull(); + }); + + describe("contract state", () => { + const client = new RestClient(wasmd.endpoint); + const noContract = makeRandomAddress(); + const expectedKey = toAscii("config"); + let contractAddress: string | undefined; + + beforeAll(async () => { + if (wasmdEnabled()) { + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); + const uploadResult = await uploadContract(client, pen); + assert(!uploadResult.code); + const uploadLogs = parseLogs(uploadResult.logs); + const codeId = Number.parseInt(findAttribute(uploadLogs, "message", "code_id").value, 10); + const instantiateResult = await instantiateContract(client, pen, codeId, makeRandomAddress()); + assert(!instantiateResult.code); + const instantiateLogs = parseLogs(instantiateResult.logs); + const contractAddressAttr = findAttribute(instantiateLogs, "message", "contract_address"); + contractAddress = contractAddressAttr.value; + } + }); + + it("can get all state", async () => { + pendingWithoutWasmd(); + + // get contract state + const state = await client.getAllContractState(contractAddress!); + expect(state.length).toEqual(1); + const data = state[0]; + expect(data.key).toEqual(expectedKey); + const value = JSON.parse(fromAscii(data.val)); + expect(value.verifier).toBeDefined(); + expect(value.beneficiary).toBeDefined(); + + // bad address is empty array + const noContractState = await client.getAllContractState(noContract); + expect(noContractState).toEqual([]); + }); + + it("can query by key", async () => { + pendingWithoutWasmd(); + + // query by one key + const raw = await client.queryContractRaw(contractAddress!, expectedKey); + assert(raw, "must get result"); + const model = JSON.parse(fromAscii(raw)); + expect(model.verifier).toBeDefined(); + expect(model.beneficiary).toBeDefined(); + + // missing key is null + const missing = await client.queryContractRaw(contractAddress!, fromHex("cafe0dad")); + expect(missing).toBeNull(); + + // bad address is null + const noContractModel = await client.queryContractRaw(noContract, expectedKey); + expect(noContractModel).toBeNull(); + }); + + it("can make smart queries", async () => { + pendingWithoutWasmd(); + + // we can query the verifier properly + const resultDocument = await client.queryContractSmart(contractAddress!, { verifier: {} }); + expect(resultDocument).toEqual({ verifier: faucet.address }); + + // invalid query syntax throws an error + await client.queryContractSmart(contractAddress!, { nosuchkey: {} }).then( + () => fail("shouldn't succeed"), + (error) => + expect(error).toMatch(/query wasm contract failed: parsing hackatom::contract::QueryMsg/), + ); + + // invalid address throws an error + await client.queryContractSmart(noContract, { verifier: {} }).then( + () => fail("shouldn't succeed"), + (error) => expect(error).toMatch("not found"), + ); + }); + }); + }); +}); diff --git a/packages/cosmwasm/src/restclient.ts b/packages/cosmwasm/src/restclient.ts new file mode 100644 index 00000000..0e5846c8 --- /dev/null +++ b/packages/cosmwasm/src/restclient.ts @@ -0,0 +1,457 @@ +import { Coin } from "@cosmwasm/sdk38"; +import { Encoding, isNonNullObject } from "@iov/encoding"; +import axios, { AxiosError, AxiosInstance } from "axios"; + +import { CosmosSdkTx, JsonObject, Model, parseWasmData, StdTx, WasmData } from "./types"; + +const { fromBase64, fromUtf8, toHex, toUtf8 } = Encoding; + +export interface CosmosSdkAccount { + /** Bech32 account address */ + readonly address: string; + readonly coins: ReadonlyArray; + /** Bech32 encoded pubkey */ + readonly public_key: string; + readonly account_number: number; + readonly sequence: number; +} + +export 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; + }; +} + +export 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; +} + +export 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; +} + +export interface Block { + readonly header: BlockHeader; + readonly data: { + /** Array of base64 encoded transactions */ + readonly txs: ReadonlyArray | null; + }; +} + +export interface BlockResponse { + readonly block_id: BlockId; + readonly block: Block; +} + +interface AuthAccountsResponse { + readonly height: string; + readonly result: { + readonly type: "cosmos-sdk/Account"; + readonly value: CosmosSdkAccount; + }; +} + +// Currently all wasm query responses return json-encoded strings... +// later deprecate this and use the specific types for result +// (assuming it is inlined, no second parse needed) +type WasmResponse = WasmSuccess | WasmError; + +interface WasmSuccess { + readonly height: string; + readonly result: T; +} + +interface WasmError { + readonly error: string; +} + +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?: object; + readonly tx: CosmosSdkTx; + /** 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; +} + +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 PostTxsResponse { + readonly height: string; + readonly txhash: string; + readonly code?: number; + readonly raw_log?: string; + /** The same as `raw_log` but deserialized? */ + readonly logs?: object; + /** The gas limit as set by the user */ + readonly gas_wanted?: string; + /** The gas used by the execution */ + readonly gas_used?: string; +} + +interface EncodeTxResponse { + // base64-encoded amino-binary encoded representation + readonly tx: string; +} + +export interface CodeInfo { + readonly id: number; + /** Bech32 account address */ + readonly creator: string; + /** Hex-encoded sha256 hash of the code stored here */ + readonly data_hash: string; + // TODO: these are not supported in current wasmd + readonly source?: string; + readonly builder?: string; +} + +export interface CodeDetails extends CodeInfo { + /** Base64 encoded raw wasm data */ + readonly data: string; +} + +// This is list view, without contract info +export interface ContractInfo { + readonly address: string; + readonly code_id: number; + /** Bech32 account address */ + readonly creator: string; + readonly label: string; +} + +export interface ContractDetails extends ContractInfo { + /** Argument passed on initialization of the contract */ + readonly init_msg: object; +} + +interface SmartQueryResponse { + // base64 encoded response + readonly smart: string; +} + +type RestClientResponse = + | NodeInfoResponse + | BlockResponse + | AuthAccountsResponse + | TxsResponse + | SearchTxsResponse + | PostTxsResponse + | EncodeTxResponse + | WasmResponse + | WasmResponse + | WasmResponse + | WasmResponse + | WasmResponse; + +/** Unfortunately, Cosmos SDK encodes empty arrays as null */ +type CosmosSdkArray = ReadonlyArray | null; + +function normalizeArray(backend: CosmosSdkArray): ReadonlyArray { + return backend || []; +} + +/** + * The mode used to send transaction + * + * @see https://cosmos.network/rpc/#/Transactions/post_txs + */ +export enum BroadcastMode { + /** Return after tx commit */ + Block = "block", + /** Return afer CheckTx */ + Sync = "sync", + /** Return right away */ + Async = "async", +} + +function isWasmError(resp: WasmResponse): resp is WasmError { + return (resp as WasmError).error !== undefined; +} + +function unwrapWasmResponse(response: WasmResponse): T { + if (isWasmError(response)) { + throw new Error(response.error); + } + return response.result; +} + +// 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; + } +} + +export class RestClient { + 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 postTx method (i.e. transaction broadcasting) 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): Promise { + const { data } = await this.client.get(path).catch(parseAxiosError); + if (data === null) { + throw new Error("Received null response from server"); + } + return data; + } + + 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 /auth endpoints + + public async authAccounts(address: string): Promise { + const path = `/auth/accounts/${address}`; + const responseData = await this.get(path); + if ((responseData as any).result.type !== "cosmos-sdk/Account") { + throw new Error("Unexpected response data format"); + } + return responseData as AuthAccountsResponse; + } + + // The /blocks endpoints + + public async blocksLatest(): Promise { + const responseData = await this.get("/blocks/latest"); + if (!(responseData as any).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 as any).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 as any).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 as any).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 as any).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: CosmosSdkTx): Promise { + const responseData = await this.post("/txs/encode", tx); + if (!(responseData as any).tx) { + throw new Error("Unexpected response data format"); + } + return Encoding.fromBase64((responseData as EncodeTxResponse).tx); + } + + /** + * Broadcasts a signed transaction to into the transaction pool. + * Depending on the RestClient'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 postTx(tx: StdTx): Promise { + const params = { + tx: tx, + mode: this.broadcastMode, + }; + const responseData = await this.post("/txs", params); + if (!(responseData as any).txhash) { + throw new Error("Unexpected response data format"); + } + return responseData as PostTxsResponse; + } + + // The /wasm endpoints + + // wasm rest queries are listed here: https://github.com/cosmwasm/wasmd/blob/master/x/wasm/client/rest/query.go#L19-L27 + public async listCodeInfo(): Promise { + const path = `/wasm/code`; + const responseData = (await this.get(path)) as WasmResponse>; + return normalizeArray(unwrapWasmResponse(responseData)); + } + + // this will download the original wasm bytecode by code id + // throws error if no code with this id + public async getCode(id: number): Promise { + const path = `/wasm/code/${id}`; + const responseData = (await this.get(path)) as WasmResponse; + return unwrapWasmResponse(responseData); + } + + public async listContractsByCodeId(id: number): Promise { + const path = `/wasm/code/${id}/contracts`; + const responseData = (await this.get(path)) as WasmResponse>; + return normalizeArray(unwrapWasmResponse(responseData)); + } + + /** + * Returns null when contract was not found at this address. + */ + public async getContractInfo(address: string): Promise { + const path = `/wasm/contract/${address}`; + const response = (await this.get(path)) as WasmResponse; + return unwrapWasmResponse(response); + } + + // Returns all contract state. + // This is an empty array if no such contract, or contract has no data. + public async getAllContractState(address: string): Promise { + const path = `/wasm/contract/${address}/state`; + const responseData = (await this.get(path)) as WasmResponse>; + return normalizeArray(unwrapWasmResponse(responseData)).map(parseWasmData); + } + + // Returns the data at the key if present (unknown decoded json), + // or null if no data at this (contract address, key) pair + public async queryContractRaw(address: string, key: Uint8Array): Promise { + const hexKey = toHex(key); + const path = `/wasm/contract/${address}/raw/${hexKey}?encoding=hex`; + const responseData = (await this.get(path)) as WasmResponse; + const data = unwrapWasmResponse(responseData); + return data.length === 0 ? null : fromBase64(data[0].val); + } + + /** + * Makes a smart query on the contract and parses the reponse as JSON. + * Throws error if no such contract exists, the query format is invalid or the response is invalid. + */ + public async queryContractSmart(address: string, query: object): Promise { + const encoded = toHex(toUtf8(JSON.stringify(query))); + const path = `/wasm/contract/${address}/smart/${encoded}?encoding=hex`; + const responseData = (await this.get(path)) as WasmResponse; + const result = unwrapWasmResponse(responseData); + // By convention, smart queries must return a valid JSON document (see https://github.com/CosmWasm/cosmwasm/issues/144) + return JSON.parse(fromUtf8(fromBase64(result.smart))); + } +} diff --git a/packages/cosmwasm/src/signingcosmwasmclient.spec.ts b/packages/cosmwasm/src/signingcosmwasmclient.spec.ts new file mode 100644 index 00000000..753bb76e --- /dev/null +++ b/packages/cosmwasm/src/signingcosmwasmclient.spec.ts @@ -0,0 +1,229 @@ +import { Coin, Secp256k1Pen } from "@cosmwasm/sdk38"; +import { Sha256 } from "@iov/crypto"; +import { Encoding } from "@iov/encoding"; +import { assert } from "@iov/utils"; + +import { PrivateCosmWasmClient } from "./cosmwasmclient"; +import { RestClient } from "./restclient"; +import { SigningCosmWasmClient, UploadMeta } from "./signingcosmwasmclient"; +import { getHackatom, makeRandomAddress, pendingWithoutWasmd } from "./testutils.spec"; + +const { toHex } = Encoding; + +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", + pubkey: { + type: "tendermint/PubKeySecp256k1", + value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ", + }, + address: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", +}; + +describe("SigningCosmWasmClient", () => { + describe("makeReadOnly", () => { + it("can be constructed", async () => { + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); + const client = new SigningCosmWasmClient(httpUrl, faucet.address, (signBytes) => pen.sign(signBytes)); + expect(client).toBeTruthy(); + }); + }); + + describe("getHeight", () => { + it("always uses authAccount implementation", async () => { + pendingWithoutWasmd(); + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); + const client = new SigningCosmWasmClient(httpUrl, faucet.address, (signBytes) => pen.sign(signBytes)); + + const openedClient = (client as unknown) as PrivateCosmWasmClient; + const blockLatestSpy = spyOn(openedClient.restClient, "blocksLatest").and.callThrough(); + const authAccountsSpy = spyOn(openedClient.restClient, "authAccounts").and.callThrough(); + + const height = await client.getHeight(); + expect(height).toBeGreaterThan(0); + + expect(blockLatestSpy).toHaveBeenCalledTimes(0); + expect(authAccountsSpy).toHaveBeenCalledTimes(1); + }); + }); + + describe("upload", () => { + it("works", async () => { + pendingWithoutWasmd(); + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); + const client = new SigningCosmWasmClient(httpUrl, faucet.address, (signBytes) => pen.sign(signBytes)); + const wasm = getHackatom(); + const { + codeId, + originalChecksum, + originalSize, + compressedChecksum, + compressedSize, + } = await client.upload(wasm); + expect(originalChecksum).toEqual(toHex(new Sha256(wasm).digest())); + expect(originalSize).toEqual(wasm.length); + expect(compressedChecksum).toMatch(/^[0-9a-f]{64}$/); + expect(compressedSize).toBeLessThan(wasm.length * 0.5); + expect(codeId).toBeGreaterThanOrEqual(1); + }); + + it("can set builder and source", async () => { + pendingWithoutWasmd(); + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); + const client = new SigningCosmWasmClient(httpUrl, faucet.address, (signBytes) => pen.sign(signBytes)); + const wasm = getHackatom(); + + const meta: UploadMeta = { + source: "https://crates.io/api/v1/crates/cw-nameservice/0.1.0/download", + builder: "confio/cosmwasm-opt:0.6.2", + }; + const { codeId } = await client.upload(wasm, meta); + + const codeDetails = await client.getCodeDetails(codeId); + expect(codeDetails.source).toEqual(meta.source); + expect(codeDetails.builder).toEqual(meta.builder); + }); + }); + + describe("instantiate", () => { + it("works with transfer amount", async () => { + pendingWithoutWasmd(); + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); + const client = new SigningCosmWasmClient(httpUrl, faucet.address, (signBytes) => pen.sign(signBytes)); + const { codeId } = await client.upload(getHackatom()); + + const transferAmount: readonly Coin[] = [ + { + amount: "1234", + denom: "ucosm", + }, + { + amount: "321", + denom: "ustake", + }, + ]; + const beneficiaryAddress = makeRandomAddress(); + const { contractAddress } = await client.instantiate( + codeId, + { + verifier: faucet.address, + beneficiary: beneficiaryAddress, + }, + "My cool label", + "Let's see if the memo is used", + transferAmount, + ); + + const rest = new RestClient(httpUrl); + const balance = (await rest.authAccounts(contractAddress)).result.value.coins; + expect(balance).toEqual(transferAmount); + }); + + it("can instantiate one code multiple times", async () => { + pendingWithoutWasmd(); + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); + const client = new SigningCosmWasmClient(httpUrl, faucet.address, (signBytes) => pen.sign(signBytes)); + const { codeId } = await client.upload(getHackatom()); + + const contractAddress1 = await client.instantiate( + codeId, + { + verifier: faucet.address, + beneficiary: makeRandomAddress(), + }, + "contract 1", + ); + const contractAddress2 = await client.instantiate( + codeId, + { + verifier: faucet.address, + beneficiary: makeRandomAddress(), + }, + "contract 2", + ); + expect(contractAddress1).not.toEqual(contractAddress2); + }); + }); + + describe("execute", () => { + it("works", async () => { + pendingWithoutWasmd(); + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); + const client = new SigningCosmWasmClient(httpUrl, faucet.address, (signBytes) => pen.sign(signBytes)); + const { codeId } = await client.upload(getHackatom()); + + // instantiate + const transferAmount: readonly Coin[] = [ + { + amount: "233444", + denom: "ucosm", + }, + { + amount: "5454", + denom: "ustake", + }, + ]; + const beneficiaryAddress = makeRandomAddress(); + const { contractAddress } = await client.instantiate( + codeId, + { + verifier: faucet.address, + beneficiary: beneficiaryAddress, + }, + "amazing random contract", + undefined, + transferAmount, + ); + + // execute + const result = await client.execute(contractAddress, { release: {} }, undefined); + const wasmEvent = result.logs.find(() => true)?.events.find((e) => e.type === "wasm"); + assert(wasmEvent, "Event of type wasm expected"); + expect(wasmEvent.attributes).toContain({ key: "action", value: "release" }); + expect(wasmEvent.attributes).toContain({ + key: "destination", + value: beneficiaryAddress, + }); + + // Verify token transfer from contract to beneficiary + const rest = new RestClient(httpUrl); + const beneficiaryBalance = (await rest.authAccounts(beneficiaryAddress)).result.value.coins; + expect(beneficiaryBalance).toEqual(transferAmount); + const contractBalance = (await rest.authAccounts(contractAddress)).result.value.coins; + expect(contractBalance).toEqual([]); + }); + }); + + describe("sendTokens", () => { + it("works", async () => { + pendingWithoutWasmd(); + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); + const client = new SigningCosmWasmClient(httpUrl, faucet.address, (signBytes) => pen.sign(signBytes)); + + // instantiate + const transferAmount: readonly Coin[] = [ + { + amount: "7890", + denom: "ucosm", + }, + ]; + const beneficiaryAddress = makeRandomAddress(); + + // no tokens here + const before = await client.getAccount(beneficiaryAddress); + expect(before).toBeUndefined(); + + // send + const result = await client.sendTokens(beneficiaryAddress, transferAmount, "for dinner"); + const [firstLog] = result.logs; + expect(firstLog).toBeTruthy(); + + // got tokens + const after = await client.getAccount(beneficiaryAddress); + assert(after); + expect(after.balance).toEqual(transferAmount); + }); + }); +}); diff --git a/packages/cosmwasm/src/signingcosmwasmclient.ts b/packages/cosmwasm/src/signingcosmwasmclient.ts new file mode 100644 index 00000000..bcdd29b0 --- /dev/null +++ b/packages/cosmwasm/src/signingcosmwasmclient.ts @@ -0,0 +1,283 @@ +import { Coin, coins, makeSignBytes } from "@cosmwasm/sdk38"; +import { Sha256 } from "@iov/crypto"; +import { Encoding } from "@iov/encoding"; +import pako from "pako"; + +import { isValidBuilder } from "./builder"; +import { Account, CosmWasmClient, GetNonceResult, PostTxResult } from "./cosmwasmclient"; +import { findAttribute, Log } from "./logs"; +import { BroadcastMode } from "./restclient"; +import { + MsgExecuteContract, + MsgInstantiateContract, + MsgSend, + MsgStoreCode, + StdFee, + StdSignature, +} from "./types"; + +export interface SigningCallback { + (signBytes: Uint8Array): Promise; +} + +export interface FeeTable { + readonly upload: StdFee; + readonly init: StdFee; + readonly exec: StdFee; + readonly send: StdFee; +} + +function prepareBuilder(buider: string | undefined): string { + if (buider === undefined) { + return ""; // normalization needed by backend + } else { + if (!isValidBuilder(buider)) throw new Error("The builder (Docker Hub image with tag) is not valid"); + return buider; + } +} + +const defaultFees: FeeTable = { + upload: { + amount: coins(25000, "ucosm"), + gas: "1000000", // one million + }, + init: { + amount: coins(12500, "ucosm"), + gas: "500000", // 500k + }, + exec: { + amount: coins(5000, "ucosm"), + gas: "200000", // 200k + }, + send: { + amount: coins(2000, "ucosm"), + gas: "80000", // 80k + }, +}; + +export interface UploadMeta { + /** The source URL */ + readonly source?: string; + /** The builder tag */ + readonly builder?: string; +} + +export interface UploadResult { + /** Size of the original wasm code in bytes */ + readonly originalSize: number; + /** A hex encoded sha256 checksum of the original wasm code (that is stored on chain) */ + readonly originalChecksum: string; + /** Size of the compressed wasm code in bytes */ + readonly compressedSize: number; + /** A hex encoded sha256 checksum of the compressed wasm code (that stored in the transaction) */ + readonly compressedChecksum: string; + /** The ID of the code asigned by the chain */ + readonly codeId: number; + readonly logs: readonly Log[]; + /** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */ + readonly transactionHash: string; +} + +export interface InstantiateResult { + /** The address of the newly instantiated contract */ + readonly contractAddress: string; + readonly logs: readonly Log[]; + /** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */ + readonly transactionHash: string; +} + +export interface ExecuteResult { + readonly logs: readonly Log[]; + /** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */ + readonly transactionHash: string; +} + +export class SigningCosmWasmClient extends CosmWasmClient { + public readonly senderAddress: string; + + private readonly signCallback: SigningCallback; + private readonly fees: FeeTable; + + /** + * Creates a new client with signing capability to interact with a CosmWasm blockchain. This is the bigger brother of CosmWasmClient. + * + * 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 senderAddress The address that will sign and send transactions using this instance + * @param signCallback An asynchonous callback to create a signature for a given transaction. This can be implemented using secure key stores that require user interaction. + * @param customFees The fees that are paid for transactions + * @param broadcastMode Defines at which point of the transaction processing the postTx method (i.e. transaction broadcasting) returns + */ + public constructor( + apiUrl: string, + senderAddress: string, + signCallback: SigningCallback, + customFees?: Partial, + broadcastMode = BroadcastMode.Block, + ) { + super(apiUrl, broadcastMode); + this.anyValidAddress = senderAddress; + + this.senderAddress = senderAddress; + this.signCallback = signCallback; + this.fees = { ...defaultFees, ...(customFees || {}) }; + } + + public async getNonce(address?: string): Promise { + return super.getNonce(address || this.senderAddress); + } + + public async getAccount(address?: string): Promise { + return super.getAccount(address || this.senderAddress); + } + + /** Uploads code and returns a receipt, including the code ID */ + public async upload(wasmCode: Uint8Array, meta: UploadMeta = {}, memo = ""): Promise { + const source = meta.source || ""; + const builder = prepareBuilder(meta.builder); + + const compressed = pako.gzip(wasmCode, { level: 9 }); + const storeCodeMsg: MsgStoreCode = { + type: "wasm/store-code", + value: { + sender: this.senderAddress, + // eslint-disable-next-line @typescript-eslint/camelcase + wasm_byte_code: Encoding.toBase64(compressed), + source: source, + builder: builder, + }, + }; + const fee = this.fees.upload; + const { accountNumber, sequence } = await this.getNonce(); + const chainId = await this.getChainId(); + const signBytes = makeSignBytes([storeCodeMsg], fee, chainId, memo, accountNumber, sequence); + const signature = await this.signCallback(signBytes); + const signedTx = { + msg: [storeCodeMsg], + fee: fee, + memo: memo, + signatures: [signature], + }; + + const result = await this.postTx(signedTx); + const codeIdAttr = findAttribute(result.logs, "message", "code_id"); + return { + originalSize: wasmCode.length, + originalChecksum: Encoding.toHex(new Sha256(wasmCode).digest()), + compressedSize: compressed.length, + compressedChecksum: Encoding.toHex(new Sha256(compressed).digest()), + codeId: Number.parseInt(codeIdAttr.value, 10), + logs: result.logs, + transactionHash: result.transactionHash, + }; + } + + public async instantiate( + codeId: number, + initMsg: object, + label: string, + memo = "", + transferAmount?: readonly Coin[], + ): Promise { + const instantiateMsg: MsgInstantiateContract = { + type: "wasm/instantiate", + value: { + sender: this.senderAddress, + // eslint-disable-next-line @typescript-eslint/camelcase + code_id: codeId.toString(), + label: label, + // eslint-disable-next-line @typescript-eslint/camelcase + init_msg: initMsg, + // eslint-disable-next-line @typescript-eslint/camelcase + init_funds: transferAmount || [], + }, + }; + const fee = this.fees.init; + const { accountNumber, sequence } = await this.getNonce(); + const chainId = await this.getChainId(); + const signBytes = makeSignBytes([instantiateMsg], fee, chainId, memo, accountNumber, sequence); + + const signature = await this.signCallback(signBytes); + const signedTx = { + msg: [instantiateMsg], + fee: fee, + memo: memo, + signatures: [signature], + }; + + const result = await this.postTx(signedTx); + const contractAddressAttr = findAttribute(result.logs, "message", "contract_address"); + return { + contractAddress: contractAddressAttr.value, + logs: result.logs, + transactionHash: result.transactionHash, + }; + } + + public async execute( + contractAddress: string, + handleMsg: object, + memo = "", + transferAmount?: readonly Coin[], + ): Promise { + const executeMsg: MsgExecuteContract = { + type: "wasm/execute", + value: { + sender: this.senderAddress, + contract: contractAddress, + msg: handleMsg, + // eslint-disable-next-line @typescript-eslint/camelcase + sent_funds: transferAmount || [], + }, + }; + const fee = this.fees.exec; + const { accountNumber, sequence } = await this.getNonce(); + const chainId = await this.getChainId(); + const signBytes = makeSignBytes([executeMsg], fee, chainId, memo, accountNumber, sequence); + const signature = await this.signCallback(signBytes); + const signedTx = { + msg: [executeMsg], + fee: fee, + memo: memo, + signatures: [signature], + }; + + const result = await this.postTx(signedTx); + return { + logs: result.logs, + transactionHash: result.transactionHash, + }; + } + + public async sendTokens( + recipientAddress: string, + transferAmount: readonly Coin[], + memo = "", + ): Promise { + const sendMsg: MsgSend = { + type: "cosmos-sdk/MsgSend", + value: { + // eslint-disable-next-line @typescript-eslint/camelcase + from_address: this.senderAddress, + // eslint-disable-next-line @typescript-eslint/camelcase + to_address: recipientAddress, + amount: transferAmount, + }, + }; + const fee = this.fees.send; + const { accountNumber, sequence } = await this.getNonce(); + const chainId = await this.getChainId(); + const signBytes = makeSignBytes([sendMsg], fee, chainId, memo, accountNumber, sequence); + const signature = await this.signCallback(signBytes); + const signedTx = { + msg: [sendMsg], + fee: fee, + memo: memo, + signatures: [signature], + }; + + return this.postTx(signedTx); + } +} diff --git a/packages/cosmwasm/src/testdata/contract.json b/packages/cosmwasm/src/testdata/contract.json new file mode 100644 index 00000000..1b75f593 --- /dev/null +++ b/packages/cosmwasm/src/testdata/contract.json @@ -0,0 +1,4 @@ +{ + "// source": "https://github.com/CosmWasm/cosmwasm/blob/v0.8.0-alpha3/packages/vm/testdata/contract_0.8.wasm", + "data": "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RQ0FIAMtAIEBIQIMAgsgDUUEQCADQeABakGagsAAQQcQDiADQewBaigCACEGIANB6AFqKAIAIQQgAygC5AEhBSADKALgASECDAgLIANB4AFqIAgQdiADKALgASICQRZGDQsgAygC7AEhBiADKALoASEEIAMoAuQBIQUgEkUEQEEAIQcMIQsgDRDAAUEAIQcMIAtBACEBIANBADoA3AELIAJB/wFxIgRBIkcEQEETQRAgBEH9AEYbIQIMBAsgA0H4AGogBxB5IAMtAHhBAXFFDQIgAy0AeUEiRwRAQQ4hAgwECyAHEHMgA0HgAWogBxB4IAMoAuwBIQQgAygC6AEhBSADKALkASECIAMoAuABIgxBAUYEQCADKALwASEGDAQLAkAgBEEHRgRAQQAhCiACQZqCwABGDQEgAkGagsAAQQcQjwJFDQELQQEhCgsgBQRAIAIQwAELIARFIAxFIAJBFEdyckUEQCAFEMABCwJAAkACQCAKBEAgA0HgAWogBxB3IAMoAuABIgJBFkYNASADKALoASEEIAMoAuQBIQUgA0GMAmogAygC7AEiBjYCACADQYgCaiAENgIAIAMgBTYChAIgAyACNgKAAgwHCyANRQRAIANB4AFqIANB2AFqEBIgAygC4AFBAUcNAiADQfABaigCACEGIAMoAuwBIQQgAygC6AEhBSADKALkASECQQAhBwwiCyADQeABakGagsAAQQcQECADQewBaigCACEGIANB6AFqKAIAIQQgAygC5AEhBSADKALgASECDAcLIANBgAJqIAcQESADKAKAAiICQRZGDQEgA0GMAmooAgAhBiADQYgCaigCACEEIAMoAoQCIQUMBQsgAygC7AEhHCADKALoASESIAMoAuQBIQ0LIANB8ABqIAcQeUEAIQUgAy0AcSECIAMtAHBBAXENAAtBAiECDAILIANB4AFqQY2DwABBCBAQIANB7AFqKAIAIQYgA0HoAWooAgAMEgtBBCECCyANRQ0BCyASRQ0AIA0QwAFBACEHDBkLQQAhBwwYCyAcIQQgEgshBSABIQYMFgsgCw0CIANB4AFqIAgQdyADKALgASICQRZHDRAgA0HoAGogCBB5IAMtAGhBAXFFBEBBBCECDAoLIAMtAGlB+wBHBEBBDiECDAoLIAgQcyADQeAAaiAIEHEgAygCYCEBIAMgAy0AZEEBcSIOOgDcASADIAE2AtgBIANB2ABqIAEQeSADLQBYQQFxRQRAQQIhAgwJCyADLQBZIQJBACELIA4hBUEAIRACQANAAkACQAJAIAJB/wFxIgRBLEcEQCAEQf0ARg0BIA4NAkEJIQIMCgsgBUH/AXENASABEHMgA0HQAGogARB5IAMtAFBBAXFFDQggAy0AUSECDAILIAtFBEAgA0HgAWpBp4PAAEEGEA4gA0HsAWooAgAhBiADQegBaigCACEEIAMoAuQBIQUgAygC4AEhAkEADAoLIBBFBEAgA0HgAWpBrYPAAEEKEA4gA0HsAWooAgAhBiADQegBaigCACEEIAMoAuQBIQUgAygC4AEhAiAXRQ0NIAsQwAEMDQsgA0HgAWogCBB2IAMoAuABIgJBFkcEQCADKALsASEGIAMoAugBIQQgAygC5AEhBSAXBEAgCxDAAQsgGARAIBhBBXQhByAQQRBqIQEDQCABQQRqKAIABEAgASgCABDAAQsgAUEgaiEBIAdBYGoiBw0ACwsgDEUNDSAQEMABDA0LIBghESAMIRUgECEPIBchFAwEC0EAIQ4gA0EAOgDcAQsgAkH/AXEiBEEiRwRAQRAhAiAEQf0ARw0HQRMhAgwHCyADQcgAaiABEHkgAy0ASEEBcUUNBSADLQBJQSJHBEBBDiECDAcLIAEQcyADQeABaiABEHggAygC7AEhBCADKALoASEFIAMoAuQBIQIgAygC4AEiB0EBRgRAIAMoAvABIQYMBwsCQAJAIARBemoiCkEESw0AAkACQCAKQQFrDgQCAgIBAAtBACEKIAJBp4PAAEYNAiACQaeDwABBBhCPAkUNAgwBC0EBIQogAkGtg8AARg0BIAJBrYPAAEEKEI8CRQ0BC0ECIQoLIAUEQCACEMABCyAERSAHRSACQRRHcnJFBEAgBRDAAQsCQAJAAkACQAJAIApBAU0EQCAKQQFrDQEMAgsgA0HgAWogARB3IAMoAuABIgJBFkYNAiADKALoASEEIAMoAuQBIQUgA0GMAmogAygC7AEiBjYCACADQYgCaiAENgIAIAMgBTYChAIgAyACNgKAAgwLCyALRQRAIANB4AFqIANB2AFqEBIgAygC4AFBAUcNAyADQfABaigCACEGIAMoAuwBIQQgAygC6AEhBSADKALkASECQQAMDAsgA0HgAWpBp4PAAEEGEBAgA0HsAWooAgAhBiADQegBaigCACEEIAMoAuQBIQUgAygC4AEhAgwKCyAQDQQgA0HgAWogA0HYAWoQEyADKALgAUEBRwRAIAMoAuwBIRggAygC6AEhDCADKALkASEQDAMLIANB8AFqKAIAIQYgAygC7AEhBCADKALoASEFIAMoAuQBIQIgCyEJDAwLIANBgAJqIAEQESADKAKAAiICQRZGDQEgA0GMAmooAgAhBiADQYgCaigCACEEIAMoAoQCIQUMCAsgAygC7AEhHSADKALoASEXIAMoAuQBIQsLIANBQGsgARB5QQAhBSADLQBBIQIgAy0AQEEBcQ0AC0ECIQIMBQsgA0HgAWpBrYPAAEEKEBAgA0HsAWooAgAhBiADQegBaigCACEEIAMoAuQBIQUgAygC4AEhAiALIQkMBgsgAyAIEHlBACEHIAMtAAEhAiADLQAAQQFxDQALQQIhAgwRCyADQeABakGGg8AAQQcQECADQewBaigCACEGIANB6AFqKAIADAgLQQQhAgsgCwshCSAQRQ0BCyAYBEAgGEEFdCEHIBBBEGohAQNAIAFBBGooAgAEQCABKAIAEMABCyABQSBqIQEgB0FgaiIHDQALCyAMRQ0AIBAQwAELIAlFIBdFcg0AIAsQwAELQQAhC0EAIQcMCgsgFyEFIB0hBCAQIQYMCQsgA0HgAWpBgYPAAEEFEBAgA0HsAWooAgAhBiADQegBaigCAAshBCADKALkASEFIAMoAuABIQIMBwsgA0HsAWooAgAhBiADQegBaigCACEEIAMoAuQBIQUgAygC4AEhAgwBC0EEIQILIAxFIAlFcg0EIAkQwAEMBAsgEyEFIBkhBAwDCyADKALsASEGIAMoAugBIQQgAygC5AEhBQwCC0EEIQIMAQtBECECC0EACyEOIBJFIA1Fcg0AIA0QwAELAkAgByALRXINACAUBEAgCxDAAQsgEQRAIBFBBXQhByAPQRBqIQEDQCABQQRqKAIABEAgASgCABDAAQsgAUEgaiEBIAdBYGoiBw0ACwsgFUUNACAPEMABCyAWRSAOIBpFcnINACAaEMABCyADQYwCaiAGNgIAIANBiAJqIAQ2AgAgAyAFNgKEAiADIAI2AoACIANB4AFqQduFwABBGCADQYACahAUIABBHGogA0H4AWooAgA2AgAgAEEUaiADQfAB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ASACKAKsASEFIAJBhAFqIAIoArQBIgo2AgAgAkGAAWogATYCACACIAU2AnwgAiAENgJ4DA4LIANFBEAgAkGoAWogBhB3IAIoAqgBIgNBFkcEQCACKAK0ASEKIAIoArABIQkgAigCrAEhCAwQCyACQRBqIAYQeSACLQAQQQFxRQRAQQQhAwwMCyACLQARQSJHBEBBDiEDDAwLIAYQcyACQagBaiAGEHggAigCtAEhESACKAKwASEOIAIoAqwBIQMgAigCqAEiAUEBRgRAIAIoArgBIQogDiEIIBEhCQwQCyARRSABRSADQRRHcnINBSAOEMABDAULIAJBqAFqQYCCwABBBRAQDAMLIBZCAVIEQCACQagBaiAGEHcgAigCqAEiBEEWRwRAIAIoArQBIQogAigCsAEhASACKAKsASEFDA4LIAJBGGogBhB5IAItABhBAXFFBEBBBCEEDAMLIAItABlBIkcEQEEOIQQMAwsgBhBzIAJBqAFqIAYQeCACKAK0ASEBIAIoArABIQUgAigCrAEhBCACKAKoASIQQQFGBEAgAigCuAEhCgwOCyACIAE2AnQgAiAENgJwIAJB+ABqIAQgARCCAgJ/IAItAHhBAUcEQEEAIQcgAigCjAEhFSACKAKIASEKIAIoAoABIQggAigChAEMAQsgAiACLQB5OgCXASACQQI2ArwBIAJCAjcCrAEgAkGojcAANgKoASACQQM2AswBIAJBAjYCxAEgAiACQcABajYCuAEgAiACQZcBajYCyAEgAiACQfAAajYCwAEgAkGYAWogAkGoAWoQyQEgAkGoAWogAkGYAWoQygEgAigCnAEEQCACKAKYARDAAQsgAigCqAEhCCACKAKwASEKQQEhByACKAKsAQshCSAFBEAgBBDAAQsgAUUgEEUgBEEUR3JyRQRAIAUQwAELQgEhFiAHRQ0EQRQhBAwCCyACQagBakGhgMAAQQYQEAwCCyACQfgAaiAGEBEgAigCeCIEQRZGDQIgAkGEAWooAgAhCiACQYABaigCACEBIAIoAnwhBQwLCyAIIQUgCSEBDAoLIAJBtAFqKAIAIQogAkGwAWooAgAhASACKAKsASEFIAIoAqgBIQQMCQsgAkEIaiAGEHlBACEFIAItAAkhASACLQAIQQFxDQALC0ECIQcMBQsgAkGoAWogEhB1IAIoAqgBIgNB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AUEIaikCADcDACACIAEpAgA3AzgMBAsgAkHQAGogAkGIAWpBz4LAAEELEIUBIAIoAlBBAUYEQCACQUBrIAJB3ABqKQIANwMAIAIgAikCVDcDOAwECyACIAIoAlQ2AnggAiACQdgAai0AADoAfCACQdAAaiACQfgAakHagsAAQQkgAUEIahAFIAJB0ABqIQMCQCACKAJQQQNGBEAgAkHQAGogAkH4AGpBp4HAACABQRRqEAYgAigCUEEDRg0BCyACQUBrIANBCGopAgA3AwAgAiADKQIANwM4DAQLIAJBOGogAigCeCACLQB8EH0MAwsgAkHQAGogAkGIAWpBxYLAAEEKEIUBIAIoAlBBAUcNASACQUBrIAJB0ABqQQRyIgFBCGopAgA3AwAgAiABKQIANwM4DAILIAJBOGogAigCVCACQdgAai0AABB9DAELIAJBOGogAigCVCACQdgAai0AABB9CyACKAI4IgNBA0cEQCACQUBrKAIAIQEgAigCPCEEIAJB3ABqIAJBxABqKAIANgIAIAJB2ABqIAE2AgAgAiAENgJUIAIgAzYCUAwECwJAIAIoApABIgMgAigCjAFHBEAgAigCiAEhAQwBCyADQQFqIgEgA0kNBSADQQF0IgQgASAEIAFLGyIEQQBIDQUCfyADRQRAIARBARBADAELIAIoAogBIANBASAEEEELIgFFDQsgAiAENgKMASACIAE2AogBIAIoApABIQMLIAEgA2pB/QA6AABBAyEDIAJBAzYCUCACIAIoApABQQFqNgKQAQwDCwJAIAIoApABIgMgAigCjAFHBEAgAigCiAEhBAwBCyADQQFqIgQgA0kNBCADQQF0IgUgBCAFIARLGyIFQQBIDQQCfyADRQRAIAVBARBADAELIAIoAogBIANBASAFEEELIgRFDQkgAiAFNgKMASACIAQ2AogBCyADIARqQfsAOgAAIAIgAigCkAFBAWo2ApABIAJB0ABqIAJBiAFqQdyAwABBBBCBASACKAJQIgNBA0cEQCACQdgAaiIBKAIAIQQgAigCVCEFIAJB3ABqIgYgBigCADYCACABIAQ2AgAgAiAFNgJUIAIgAzYCUAwDCwJAIAIoApABIgMgAigCjAFHBEAgAigCiAEhBAwBCyADQQFqIgQgA0kNBCADQQF0IgUgBCAFIARLGyIFQQBIDQQCfyADRQRAIAVBARBADAELIAIoAogBIANBASAFEEELIgRFDQkgAiAFNgKMASACIAQ2AogBIAIoApABIQMLIAMgBGpBOjoAACACIAIoApABQQFqNgKQASABQRRqIQMgAUEIaiEEAkACQCABKAIEQQFHBEAgAkHQAGogAkGIAWpBtILAAEEFEIUBIAIoAlBBAUYEQCACQUBrIAJB3ABqKQIANwMAIAIgAikCVDcDOAwDCyACIAIoAlQ2AnggAiACQdgAai0AADoAfCACQdAAaiACQfgAakHPgMAAQQ0gBBAFIAIoAlBBA0YEQCACQdAAaiACQfgAakHAgMAAIAMQCSACKAJQQQNGDQILIAJBQGsgAkHQAGoiAUEIaikCADcDACACIAEpAgA3AzgMAgsgAkHQAGogAkGIAWpBsYLAAEEDEIUBIAIoAlBBAUYEQCACQUBrIAJB3ABqKQIANwMAIAIgAikCVDcDOAwCCyACIAIoAlQ2AnggAiACQdgAai0AADoAfCACQdAAaiACQfgAakHPgMAAQQ0gBBAFIAJB0ABqIQECQCACKAJQQQNGBEAgAkHQAGogAkH4AGpB5oHAACADEAkgAigCUEEDRg0BCyACQUBrIAFBCGopAgA3AwAgAiABKQIANwM4DAILIAJBOGogAigCeCACLQB8EH0MAQsgAkE4aiACKAJ4IAItAHwQfQsgAigCOCIDQQNHBEAgAkFAaygCACEBIAIoAjwhBCACQdwAaiACQcQAaigCADYCACACQdgAaiABNgIAIAIgBDYCVCACIAM2AlAMAwsCQCACKAKQASIDIAIoAowBRwRAIAIoAogBIQEMAQsgA0EBaiIBIANJDQQgA0EBdCIEIAEgBCABSxsiBEEASA0EAn8gA0UEQCAEQQEQQAwBCyACKAKIASADQQEgBBBBCyIBRQ0KIAIgBDYCjAEgAiABNgKIASACKAKQASEDCyABIANqQf0AOgAAQQMhAyACQQM2AlAgAiACKAKQAUEBajYCkAEMAgsgAkE4aiACKAJ4IAItAHwQfQsgAigCOCIDQQNHBEAgAkFAaygCACEBIAIoAjwhBCACQdwAaiACQcQAaigCADYCACACQdgAaiABNgIAIAIgBDYCVCACIAM2AlAMAQsCQCACKAKQASIDIAIoAowBRwRAIAIoAogBIQEMAQsgA0EBaiIBIANJDQIgA0EBdCIEIAEgBCABSxsiBEEASA0CAn8gA0UEQCAEQQEQQAwBCyACKAKIASADQQEgBBBBCyIBRQ0IIAIgBDYCjAEgAiABNgKIASACKAKQASEDCyABIANqQf0AOgAAQQMhAyACQQM2AlAgAiACKAKQAUEBajYCkAELIANBA0cEQCACQdwAaigCACEBIAJB2ABqKAIAIQcgAigCVCEEIAIoAowBBEAgAigCiAEQwAELIAJB3ABqIAE2AgAgAkHYAGoiASAHNgIAIAIgBDYCVCACIAM2AlAgAkGgAWpB+IbAAEE9IAJB0ABqEBYgAkHoAGogAkG4AWooAgA2AgAgAkHgAGogAkGwAWopAgA3AwAgASACQagBaikCADcDACACIAIpAqABNwNQIAJBzABqQQE2AgAgAkIBNwI8IAJB4ITAADYCOCACQQY2AnwgAiACQfgAajYCSCACIAJB0ABqNgJ4IAJBiAFqIAJBOGoQyQEQjgEhASACQcIAaiACQZABaigCADYBACACIAIpA4gBNwE6IAAgAToABSAAQQA6AAQgACACKQE4NwEGIABBDGogAkE+aikBADcBACAAQQE2AgAgAkHQAGoQHAwFCyACKAKMASENIAJB0ABqIAIoAogBIg4gAigCkAEQZiACKAJQIg9BAUcNASACQUBrIgEgAkHcAGopAgA3AwAgAiACKQJUNwM4IAJBtAFqQQE2AgAgAkIBNwKkASACQYCFwAA2AqABIAJBBzYCfCACIAJB+ABqNgKwASACIAJBOGo2AnggAkGIAWogAkGgAWoQyQEQjgEhByACQaoBaiACQZABaigCADYBACACIAIpA4gBNwGiASAAIAc6AAUgAEEAOgAEIAAgAikBoAE3AQYgAEEMaiACQaYBaikBADcBACAAQQE2AgACQCACKAI4IgBBAk0EQAJAAkAgAEEBaw4CAQMACyACQUBrKAIARQ0CIAIoAjwQwAEMAgsgAkFAaygCAEUNASACKAI8EMABDAELIAEoAgBFDQAgAigCPBDAAQtBASEDQQAMAgsQyAEACyACKAJUQQFGBEBBASEFIABBATYCACAAQRxqIAJB8ABqKAIANgIAIABBFGogAkHoAGopAwA3AgAgAEEMaiACQeAAaikDADcCACAAIAJB2ABqKQMANwIEQQEhA0EADAILIAJBgAFqIAJB4ABqKAIA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ASACKAIAQQNGDQIgACACKQMANwIAIABBCGogAkEIaikDADcCACACQRBqJAAPCyAEQQEQxwEACxDIAQALAkAgAigCAEEBRw0AIAJBCGooAgBFDQAgAigCBBDAAQsgARAoAAv/AQEBfwJAAkAgAC0AACIBQQdNBEACQAJAAkACQAJAAkAgAUEBaw4HAQIDBwQFBwALIABBCGooAgBFDQYMBwsgAEEIaigCAEUNBQwGCyAAQQhqKAIARQ0EDAULIABBCGooAgBFDQMMBAsgAEEIaigCAARAIABBBGooAgAQwAELIABBFGooAgBFDQIgAEEQaigCABDAAQ8LIABBCGooAgAEQCAAQQRqKAIAEMABCyAAQRRqKAIARQ0BIABBEGooAgAQwAEMAQsgAEEIaigCAARAIABBBGooAgAQwAELIABBFGooAgBFDQAgAEEQaigCABDAAQsPCyAAQQRqKAIAEMABCwwAQuSuwoWXm6WIEQszAQF/IwBBEGsiACQAIABBHzYCDCAAQZCPwAA2AgggAEEIakGIhcAAQQBBgI/AABC1AQALEQAgACgCACkDAEEBIAEQ9AELDAAgACgCACABEPUBCxEAIAAoAgAgACgCBCABEP8BCwMAAQvDAQEBfwJAIAAoAgAiAUECTQRAAkACQCABQQFrDgIDAQALIAAoAgQgAEEMaigCAARAIABBCGooAgAQwAELDQIgAEEYaigCAEUNAiAAQRRqKAIAEMABDwsgACgCBEEBRw0BIABBDGooAgAEQCAAQQhqKAIAEMABCyAAQRRqKAIAIgFFDQEgAEEYaigCAEUNASABEMABDAELIABBDGooAgAEQCAAQQhqKAIAEMABCyAAQRhqKAIARQ0AIABBFGooAgAQwAELC/sFAQV/IAAoAggiAQRAIAAoAgAiBCABQcgAbGohBQNAIAQiAUHIAGohBAJAIAEoAgAiAkECTQRAAkACQCACQQFrDgIDAQALIAFBCGooAgAEQCABKAIEEMABCyABQRRqKAIABEAgAUEQaigCABDAAQsgAUEkaigCACICBEAgAkEFdCECIAFBHGooAgBBEGohAwNAIANBBGooAgAEQCADKAIAEMABCyADQSBqIQMgAkFgaiICDQALCyABQSBqKAIARQ0CIAEoAhwQwAEMAgsgAUEIaigCACICQQJNBEACQAJAAkAgAkEBaw4CAQIACyABQRBqKAIABEAgAUEMaigCABDAAQsgAUEsaigCAEUNBCABQShqKAIAEMABDAQLIAFBEGooAgAEQCABQQxqKAIAEMABCyABQSxqKAIARQ0DIAFBKGooAgAQwAEMAwsgAUEQaigCAARAIAFBDGooAgAQwAELIAFBGGooAgAiAkUNAiABQRxqKAIARQ0CIAIQwAEMAgsgAUEQaigCAARAIAFBDGooAgAQwAELIAFBHGooAgAEQCABQRhqKAIAEMABCyABQTxqKAIARQ0BIAFBOGooAgAQwAEMAQsgAUEQaigCACECIAFBCGooAgBFBEAgAgRAIAEoAgwQwAELIAFBHGooAgAEQCABQRhqKAIAEMABCyABQSxqKAIAIgIEQCACQQV0IQIgAUEkaigCAEEQaiEDA0AgA0EEaigCAARAIAMoAgAQwAELIANBIGohAyACQWBqIgINAAsLIAFBKGooAgBFDQEgASgCJBDAAQwBCyACBEAgASgCDBDAAQsgAUEgaigCACICBEAgAkEFdCECIAFBGGooAgBBEGohAwNAIANBBGooAgAEQCADKAIAEMABCyADQSBqIQMgAkFgaiICDQALCyABQRxqKAIABEAgASgCGBDAAQsgAUEkaigCACICRQ0AIAFBKGooAgBFDQAgAhDAAQsgBCAFRw0ACwsgAEEEaigCAARAIAAoAgAQwAELC74EAQR/IwBBEGsiBCQAIAAoAgAhAAJAAkACQAJAAkACQCABQYABTwRAIARBADYCDCABQYAQSQ0BIAFBgIAESQRAIAQgAUE/cUGAAXI6AA4gBCABQQZ2QT9xQYABcjoADSAEIAFBDHZBD3FB4AFyOgAMQQMhAQwECyAEIAFBP3FBgAFyOgAPIAQgAUESdkHwAXI6AAwgBCABQQZ2QT9xQYABcjoADiAEIAFBDHZBP3FBgAFyOgANQQQhAQwDCwJAIAAoAggiAiAAQQRqKAIARwRAIAAoAgAhAwwBCyACQQFqIgMgAkkNBiACQQF0IgUgAyAFIANLGyIFQQBIDQYCfyACRQRAIAVBARBADAELIAAoAgAgAkEBIAUQQQsiA0UNAiAAIAM2AgAgAEEEaiAFNgIAIAAoAgghAgsgAiADaiABOgAAIAAgACgCCEEBajYCCAwDCyAEIAFBP3FBgAFyOgANIAQgAUEGdkEfcUHAAXI6AAxBAiEBDAELIAVBARDHAQALAkAgAEEEaigCACIDIABBCGooAgAiAmsgAU8EQCAAKAIAIQMMAQsgASACaiIFIAJJDQMgA0EBdCICIAUgAiAFSxsiAkEASA0DAn8gA0UEQCACQQEQQAwBCyAAKAIAIANBASACEEELIgNFDQIgACADNgIAIABBBGogAjYCACAAQQhqKAIAIQILIABBCGogASACajYCACACIANqIARBDGogARCOAhoLIARBEGokAEEADwsgAkEBEMcBAAsQyAEAC1oBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpBnIrAACACQQhqENUBIAJBIGokAAu/AQEDfwJAAkACQCAAKAIAIgBBBGooAgAiBCAAQQhqKAIAIgNrIAJPBEAgACgCACEEDAELIAIgA2oiBSADSQ0CIARBAXQiAyAFIAMgBUsbIgNBAEgNAgJ/IARFBEAgA0EBEEAMAQsgACgCACAEQQEgAxBBCyIERQ0BIAAgBDYCACAAQQRqIAM2AgAgAEEIaigCACEDCyAAQQhqIAIgA2o2AgAgAyAEaiABIAIQjgIaQQAPCyADQQEQxwEACxDIAQALoAEBA38CQAJAIAAoAggiASAAQQRqKAIARgR/IAFBAWoiAiABSQ0CIAFBAXQiAyACIAMgAksbIgJBAEgNAgJ/IAFFBEAgAkEBEEAMAQsgACgCACABQQEgAhBBCyIBRQ0BIAAgATYCACAAQQRqIAI2AgAgACgCCAUgAQsgACgCAGpBOjoAACAAIAAoAghBAWo2AggPCyACQQEQxwEACxDIAQALxwICAn8BfiMAQUBqIgIkACACIAE2AgQgAkEANgIQIAJCATcDCCACQQg2AhwgAiACQQRqNgIYIAIgAkEIajYCJCACQTxqQQE2AgAgAkIBNwIsIAJBnIXAADYCKCACIAJBGGo2AjgCQAJAIAJBJGpBnIrAACACQShqENUBRQRAIAIoAgwiAyACKAIQIgFHBEAgAyABSQ0CAkAgAUUEQCADBEAgAigCCBDAAQsgAkEBNgIIQQAhAQwBCyACKAIIIANBASABEEEiA0UNBCACIAM2AggLIAIgATYCDAsgAkEwaiACQRBqKAIAIgE2AgAgAiACKQMIIgQ3AyggAEEMaiABNgIAIAAgBDcCBCAAQRQ2AgAgAkFAayQADwtBpIXAAEE3IAJBKGpBtIrAABDfAQALQcyLwABBJEG8i8AAEM0BAAsgAUEBEMcBAAu5AQEBfyMAQUBqIgUkACAFIAI2AgwgBSABNgIIAkAgBARAIAVBNGpBCTYCACAFQSRqQQI2AgAgBUICNwIUIAVB/IzAADYCECAFQQI2AiwgBSAENgI8IAUgAzYCOCAFIAVBKGo2AiAgBSAFQThqNgIwDAELIAVBJGpBATYCACAFQgI3AhQgBUHgjMAANgIQIAVBAjYCLCAFIAVBKGo2AiALIAUgBUEIajYCKCAAIAVBEGoQKSAFQUBrJAAL9wIBBH8jAEEgayICJAAgAkEIaiABKAIAEHkCQAJAAkAgAi0ACEEBcUUEQEECIQMMAQsCQAJAIAItAAkiBCIDQf0ARwRAAkAgA0EsRgRAIAEtAARFDQEMAwsgAS0ABA0CQQkhAwwECyABKAIAEHMgAiABKAIAEHkgAi0AAEEBcUUEQEEEIQMMBAsgAi0AASEEDAILIABBADsBAAwECyABQQA6AAQLIARB/wFxIgNB/QBHBEAgA0EiRwRAQRAhAwwCCyACQRBqIAEoAgAQLCACKAIQIgNBFkYNAiACQRxqKAIAIQEgAkEYaigCACEEIAIoAhQhBQwBC0ETIQMLIABBAToAACAAQRBqIAE2AgAgAEEMaiAENgIAIABBCGogBTYCACAAQQRqIAM2AgAMAQsgAkEQaiABEC0gAigCEEEWRwRAIABBAToAACAAQQRqIAIpAxA3AgAgAEEMaiACQRhqKQMANwIADAELIABBgAI7AQALIAJBIGokAAvNAQEEfyMAQSBrIgIkACACIAEQeQJAIAItAABBAXEEQCACLQABQSJHBEAgAEEONgIADAILIAEQcyACQQhqIAEQeCACQRRqKAIAIQUgAkEQaigCACEBIAIoAgwhAyACKAIIIgRBAUYEQCACQRhqKAIAIQQgACABNgIEIAAgAzYCACAAQQxqIAQ2AgAgAEEIaiAFNgIADAILIABBFjYCACABBEAgAxDAAQsgBUUgBEUgA0EUR3JyDQEgARDAAQwBCyAAQQQ2AgALIAJBIGokAAtxAQN/IwBBEGsiAiQAIAIgASgCABB3AkAgAigCACIDQRZHBEAgAkEMaigCACEBIAJBCGooAgAhBCAAIAIoAgQ2AgQgACADNgIAIABBDGogATYCACAAQQhqIAQ2AgAMAQsgACABKAIAEBELIAJBEGokAAvKAgEDfyMAQSBrIgIkACACQQhqIAEoAgAQeUEBIQMCQAJAAkAgAi0ACEEBcQRAAkACQCACLQAJIgMiBEEsRwRAIARB3QBHDQFBACEDIABBADoAAQwGCyABKAIAEHMgAiABKAIAEHlBASEDIAItAABBAXFFDQMgAi0AASEDDAELIAEtAARFBEAgAEEEakEHNgIAQQEhAwwFCyABQQA6AAQLIANB3QBGDQIgAkEQaiABKAIAEBEgAigCECIBQRZHBEAgAkEYaigCACEDIAIoAhQhBCAAQRBqIAJBHGooAgA2AgAgAEEMaiADNgIAIABBCGogBDYCACAAQQRqIAE2AgBBASEDDAQLIABBAToAAUEAIQMMAwsgAEEEakEBNgIADAILIABBBGpBBDYCAAwBCyAAQQRqQRM2AgBBASEDCyAAIAM6AAAgAkEgaiQAC4wDAQV/IwBBIGsiAiQAIAIgARB5AkACQAJAIAItAABBAXEEQCACLQABQSJHBEAgAEEBOgAAIABBBGpBDjYCAAwECyABEHMgAkEIaiABEHggAkEUaigCACEDIAJBEGooAgAhBCACKAIMIQEgAigCCCIFQQFGBEAgAkEYaigCACEFIABBAToAACAAQRBqIAU2AgAgAEEMaiADNgIAIABBCGogBDYCACAAQQRqIAE2AgAMBAsgA0F4aiIGQQVLDQECQAJAIAZBAWsOBQMDAwMBAAsgAUGvj8AARwRAIAEpAABC9srJy+as2rLyAFINAwsgAEEAOwEADAMLIAFBtJDAAEcEQCABQbSQwABBDRCPAg0CCyAAQYACOwEADAILIABBAToAACAAQQRqQQQ2AgAMAgsgAkEIaiABIANBxJDAAEECECogAEEBOgAAIABBDGogAkEQaikDADcCACAAQQRqIAIpAwg3AgALIAQEQCABEMABCyADRSAFRSABQRRHcnINACAEEMABCyACQSBqJAALrwQBBX8jAEEgayICJAAgAiABEHkCQAJAAkAgAi0AAEEBcQRAIAItAAFBIkcEQCAAQQE6AAAgAEEEakEONgIADAQLIAEQcyACQQhqIAEQeCACQRRqKAIAIQMgAkEQaigCACEEIAIoAgwhASACKAIIIgVBAUYEQCACQRhqKAIAIQUgAEEBOgAAIABBEGogBTYCACAAQQxqIAM2AgAgAEEIaiAENgIAIABBBGogATYCAAwECyADQXtqIgZBEEsNAQJAAkACQAJAAkACQCAGQQFrDhAHAAEHBwMCBwcHBwcHBwcEBQsgAUHsjcAARwRAIAFB7I3AAEEHEI8CDQcLIABBADsBAAwHCyABQciPwABHBEAgASkAAELj4NX7xe3bt/AAUg0GCyAAQYACOwEADAYLIAFB0I/AAEcEQCABQdCPwABBDBCPAg0FCyAAQYAEOwEADAULIAFB3I/AAEcEQCABQdyPwABBCxCPAg0ECyAAQYAGOwEADAQLIAFB54/AAEcEQCABQeePwABBFRCPAg0DCyAAQYAIOwEADAMLIAFB/I/AAEcEQCABQfyPwABBBRCPAg0CCyAAQYAKOwEADAILIABBAToAACAAQQRqQQQ2AgAMAgsgAkEIaiABIANBhJDAAEEGECogAEEBOgAAIABBDGogAkEQaikDADcCACAAQQRqIAIpAwg3AgALIAQEQCABEMABCyADRSAFRSABQRRHcnINACAEEMABCyACQSBqJAAL4xABBH8jAEEwayIDJAACQAJAAkACQAJAAkACQAJAAkAgASgCCCIEIAFBBGooAgBHBEAgASgCACEFDAELIARBAWoiBSAESQ0HIARBAXQiBiAFIAYgBUsbIgZBAEgNBwJ/IARFBEAgBkEBEEAMAQsgASgCACAEQQEgBhBBCyIFRQ0BIAEgBTYCACABQQRqIAY2AgAgASgCCCEECyAEIAVqQfsAOgAAIAEgASgCCEEBajYCCCADQRhqIAFBjI3AAEEDEIEBIAMoAhgiBEEDRwRAIANBJGooAgAhASADQSBqKAIAIQIgACADKAIcNgIEIAAgBDYCACAAQQxqIAE2AgAgAEEIaiACNgIADAgLAkAgASgCCCIEIAFBBGooAgBHBEAgASgCACEFDAELIARBAWoiBSAESQ0HIARBAXQiBiAFIAYgBUsbIgZBAEgNBwJ/IARFBEAgBkEBEEAMAQsgASgCACAEQQEgBhBBCyIFRQ0CIAEgBTYCACABQQRqIAY2AgAgASgCCCEECyAEIAVqQTo6AAAgASABKAIIQQFqNgIIAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgAi0AAEEBaw4IAQIDBAUGBwgACyADQRhqIAFBuoTAAEELEIUBIAMoAhhBAUcNCCADQQhqIANBJGopAgA3AwAgAyADKQIcNwMADBQLIANBGGogAUGshMAAQQ4QhQEgAygCGEEBRw0IIANBCGogA0EkaikCADcDACADIAMpAhw3AwAMEwsgA0EYaiABQaCEwABBDBCFASADKAIYQQFHDQggA0EIaiADQSRqKQIANwMAIAMgAykCHDcDAAwSCyADQRhqIAFBk4TAAEEJEIUBIAMoAhhBAUcNCCADQQhqIANBJGopAgA3AwAgAyADKQIcNwMADBELIANBGGogAUGHhMAAQQwQhQEgAygCGEEBRw0IIANBCGogA0EYakEEciICQQhqKQIANwMAIAMgAikCADcDAAwQCyADQRhqIAFB+IPAAEEJEIUBIAMoAhhBAUYEQCADQQhqIANBJGopAgA3AwAgAyADKQIcNwMADBALIAMgAygCHDYCECADIANBIGotAAA6ABQgA0EYaiADQRBqQYGEwABBBiACQQRqEAUgA0EYaiEEAkAgAygCGEEDRgRAIANBGGogA0EQakHAgMAAQQMgAkEQahAFIAMoAhhBA0YNAQsgA0EIaiAEQQhqKQIANwMAIAMgBCkCADcDAAwQCyADIAMoAhAgAy0AFBB9DA8LIANBGGogAUHlg8AAQQ0QhQEgAygCGEEBRgRAIANBCGogA0EkaikCADcDACADIAMpAhw3AwAMDwsgAyADKAIcNgIQIAMgA0Egai0AADoAFCADQRhqIANBEGpB8oPAAEEGIAJBBGoQBSADQRhqIQQCQCADKAIYQQNGBEAgA0EYaiADQRBqQcCAwABBAyACQRBqEAUgAygCGEEDRg0BCyADQQhqIARBCGopAgA3AwAgAyAEKQIANwMADA8LIAMgAygCECADLQAUEH0MDgsgA0EYaiABQdmDwABBDBCFASADKAIYQQFHDQYgA0EIaiADQRhqQQRyIgJBCGopAgA3AwAgAyACKQIANwMADA0LIANBGGogAUG/g8AAQQkQhQEgAygCGEEBRgRAIANBCGogA0EkaikCADcDACADIAMpAhw3AwAMDQsgAyADKAIcNgIQIAMgA0Egai0AADoAFCADQRhqIANBEGpByIPAAEEHIAJBBGoQBSADQRhqIQQCQCADKAIYQQNGBEAgA0EYaiADQRBqQc+DwABBCiACQRBqEAUgAygCGEEDRg0BCyADQQhqIARBCGopAgA3AwAgAyAEKQIANwMADA0LIAMgAygCECADLQAUEH0MDAsgAyADKAIcNgIQIAMgA0Egai0AADoAFCADQRhqIANBEGpBwIDAAEEDIAJBBGoQBSADKAIYQQNGDQUgA0EIaiADQSBqKQMANwMAIAMgAykDGDcDAAwLCyADIAMoAhw2AhAgAyADQSBqLQAAOgAUIANBGGogA0EQakHAgMAAQQMgAkEEahAFIAMoAhhBA0YNCSADQQhqIANBIGopAwA3AwAgAyADKQMYNwMADAoLIAMgAygCHDYCECADIANBIGotAAA6ABQgA0EYaiADQRBqQcCAwABBAyACQQRqEAUgAygCGEEDRg0HIANBCGogA0EgaikDADcDACADIAMpAxg3AwAMCQsgAyADKAIcNgIQIAMgA0Egai0AADoAFCADQRhqIANBEGpBnITAAEEEIAJBBGoQBSADKAIYQQNGDQUgA0EIaiADQSBqKQMANwMAIAMgAykDGDcDAAwICyADIAMoAhwgA0Egai0AABB9DAcLIAMgAygCHCADQSBqLQAAEH0MBgsgAyADKAIQIAMtABQQfQwFCyAGQQEQxwEACyAGQQEQxwEACyADIAMoAhAgAy0AFBB9DAILIAMgAygCECADLQAUEH0MAQsgAyADKAIQIAMtABQQfQsgAygCACICQQNHBEAgA0EMaigCACEBIANBCGooAgAhBCAAIAMoAgQ2AgQgACACNgIAIABBDGogATYCACAAQQhqIAQ2AgAMAgsCQAJAIAEoAggiBCABQQRqKAIARwRAIAEoAgAhBQwBCyAEQQFqIgIgBEkNAiAEQQF0IgUgAiAFIAJLGyICQQBIDQICfyAERQRAIAJBARBADAELIAEoAgAgBEEBIAIQQQsiBUUNASABIAU2AgAgAUEEaiACNgIAIAEoAgghBAsgBCAFakH9ADoAACAAQQM2AgAgASABKAIIQQFqNgIIDAILIAJBARDHAQALEMgBAAsgA0EwaiQACx0AIAEoAgBFBEAACyAAQdCNwAA2AgQgACABNgIAC1UBAn8gASgCACECIAFBADYCAAJAIAIEQCABKAIEIQNBCEEEEEAiAUUNASABIAM2AgQgASACNgIAIABB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AnwhBiADQZgBaiACQQxqIggQZCADQZgBakEEciEEIAMoApgBQQFGBEAgAEEBNgIAIAAgBCkCADcCBCAAQRxqIARBGGooAgA2AgAgAEEUaiAEQRBqKQIANwIAIABBDGogBEEIaikCADcCACAFRQ0BIAYQwAEMAQsgA0HkAGogBEEIaigCADYCACADQfAAaiABQShqKAIANgIAIAMgBzYCWCADIAU2AlQgAyAGNgJQIAMgBCkCADcCXCADIAEpAiA3A2ggA0G4AWoQfyADQdABaiADQbgBahCEAQJAIAMoAtABQQFGBEAgA0H4AWogA0HcAWopAgA3AwAgAyADKQLUATcD8AEMAQsgAyADKALUATYCyAEgAyADQdgBai0AADoAzAEgA0HQAWogA0HIAWpBr4/AAEEIIANB0ABqEDcgA0HQAWohBAJAIAMoAtABQQNHDQAgA0HQAWogA0HIAWpBt4/AAEELIANB3ABqEDcgAygC0AFBA0cNACADQdABaiADQcgBakHCj8AAQQYgA0HoAGoQNyADKALQAUEDRw0AIANB8AFqIAMoAsgBIAMtAMwBEHwMAQsgA0H4AWogBEEIaikCADcDACADIAQpAgA3A/ABCwJ/IAMoAvABIgRBA0cEQCADQfgBaigCACEFIANB/AFqKAIAIQYgAygC9AEhByADKAK8AQRAIAMoArgBEMABCyADQfwBaiAGNgIAIANB+AFqIAU2AgAgAyAHNgL0ASADIAQ2AvABIANB0AFqQZiJwABBGSADQfABahAWIANByABqIANB5AFqKQIANwMAIAMgA0HcAWopAgA3A0AgA0HYAWooAgAhBSADKALQASEEQQEhBiADKALUAQwBCyADKALAASEFIAMoArgBIQRBACEGIAMoArwBCyEHIANBLGoiCSAFNgIAIANBKGogBzYCACADQTBqIAMpA0A3AwAgA0E4aiADQcgAaikDADcDACADIAQ2AiQgAyAGNgIgAkAgBkUEQCADQeCNwABBBiAEIAUQYyADLQAAQQlHDQEgBwRAIAQQwAELIAMoAlQEQCADKAJQEMABCyADQeAAaigCAARAIAMoAlwQwAELIANB7ABqKAIABEAgAygCaBDAAQsgAEEYakIANwIAIABBEGpCBDcCACAAQQhqQgA3AgAgAEKAgICAgAE3AgAgAkEEaigCAARAIAIoAgAQwAELIAJBEGooAgAEQCAIKAIAEMABCyABQRRqKAIABEAgASgCEBDAAQsgAUE0aigCACIABEAgAEEFdCECIAFBLGooAgBBEGohAANAIABBBGooAgAEQCAAKAIAEMABCyAAQSBqIQAgAkFgaiICDQALCyABQTBqKAIABEAgASgCLBDAAQsgAUE8aigCAEUNBCABKAI4EMABDAQLIAAgAykCJDcCBCAAQQE2AgAgAEEcaiADQTxqKAIANgIAIABBFGogA0E0aikCADcCACAAQQxqIAkpAgA3AgAgAygCVARAIAMoAlAQwAELIANB4ABqKAIABEAgAygCXBDAAQsgA0HsAGooAgAEQCADKAJoEMABCyACQQRqKAIABEAgAigCABDAAQsgAkEQaigCAARAIAgoAgAQwAELIAFBFGooAgBFDQIgASgCEBDAAQwCCyAAIAMpAwA3AgQgAEEBNgIAIABBHGogA0EYaigCADYCACAAQRRqIANBEGopAwA3AgAgAEEMaiADQQhqKQMANwIAIAcEQCAEEMABCyADKAJUBEAgAygCUBDAAQsgA0HgAGooAgAEQCADKAJcEMABCyADQewAaigCAARAIAMoAmgQwAELIAJBBGooAgAEQCACKAIAEMABCyACQRBqKAIABEAgCCgCABDAAQsgAUEUaigCAEUNASABKAIQEMABDAELIAJBBGooAgAEQCACKAIAEMABCyACQRBqKAIABEAgAigCDBDAAQsgAUEUaigCAARAIAEoAhAQwAELIAFBJGooAgBFDQAgASgCIBDAAQsgAUE0aigCACIABEAgAEEFdCECIAFBLGooAgBBEGohAANAIABBBGooAgAEQCAAKAIAEMABCyAAQSBqIQAgAkFgaiICDQALCyABQTBqKAIABEAgASgCLBDAAQsgAUE8aigCAEUNACABKAI4EMABCyADQYACaiQAC+4YAgl/A34jAEHAAmsiAyQAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCACQf8BcUEBaw4FAgMEBQABCxAeAAsgA0EQaiABQcgAEI4CGiADQYABahBiIAMoAoABQQFHDQkgAEEBNgIAIAAgA0GAAWpBBHIiASkCADcCBCAAQRxqIAFBGGooAgA2AgAgAEEUaiABQRBqKQIANwIAIABBDGogAUEIaikCADcCAAwKCxA6AAsCQANAIAMgDDcD+AEgAyADQfgBajYCyAEgA0EANgKgAiADQgE3A5gCIANBCjYCXCADIANByAFqNgJYIAMgA0GYAmo2AtgBIANBATYClAEgA0IBNwKEASADQZyFwAA2AoABIAMgA0HYAGo2ApABIANB2AFqQZyKwAAgA0GAAWoQ1QENBQJAIAMoApwCIgIgAygCoAIiBEYEQCADKAKYAiEFDAELIAIgBEkNByAERQRAIAIEQCADKAKYAhDAAQsgA0IBNwOYAkEAIQJBASEFDAELIAMoApgCIAJBASAEEEEiBUUNCCADIAQ2ApwCIAMgBTYCmAIgBCECCyADQRBqQaSOwABBCCAFIAMoAqACEGMgAy0AEEEJRw0BIAIEQCAFEMABCyADKQP4ASINQgF8IgwgDVoNAAtBgIvAAEEcQayOwAAQzQEACyAAIAMpAxA3AgQgAEEBNgIAIABBHGogA0EoaigCADYCACAAQRRqIANBIGopAwA3AgAgAEEMaiADQRhqKQMANwIAIAJFDQIgBRDAAQwCCxA7AAtBwAxAAEF/RwRAIABCgICAgIABNwIAIABBGGpCADcCACAAQRBqQgQ3AgAgAEEIakIANwIADAELQSBBARBAIgJFDQQgAkEYakH4jsAAKQAANwAAIAJBEGpB8I7AACkAADcAACACQQhqQeiOwAApAAA3AAAgAkHgjsAAKQAANwAAEI4BIQQgAEEMakKggICAgAQ3AgAgAEEIaiACNgIAIAAgBDoABSAAQQA6AAQgAEEBNgIAIABBFGogAykCmAI3AgAgAEEcaiADQaACaigCADYCAAsgAUEUaigCAARAIAEoAhAQwAELIAFBJGooAgAEQCABKAIgEMABCyABQSxqKAIAIQAgAUE0aigCACICBEAgAkEFdCEEIABBEGohAgNAIAJBBGooAgAEQCACKAIAEMABCyACQSBqIQIgBEFgaiIEDQALCyABQTBqKAIABEAgABDAAQsgAUE8aigCAEUNBiABKAI4EMABDAYLQaSFwABBNyADQYABakG0isAAEN8BAAtBzIvAAEEkQbyLwAAQzQEACyAEQQEQxwEAC0EgQQEQxwEACwJ/AkAgAygChAEiAkUEQEEBIQFBBSEGQQVBARBAIgQNAUEFQQEQxwEACyACQQh2IQUgA0GIAWooAgAhBCADQYwBaigCACEGQQAhASACQYCAfHEMAQsgBEEEakGCjsAALQAAOgAAIARB/o3AACgAADYAABCOASEFIANB4ABqIANBoAJqKAIANgIAIAMgAykCmAI3A1hBAyECQQALIQcgA0GAAmoiCCADQeAAaigCADYCACADIAMpA1g3A/gBIAJB/wFxIAVBCHRBgP4DcXIgB3IhBSABBEAgACAFNgIEIABBATYCACAAQRBqQQU2AgAgAEEMaiAGNgIAIABBCGogBDYCACAAQRRqIAMpA/gBNwIAIABBHGogCCgCADYCAAwBCyADQYABaiAFIAYQFSADQYABakEEciEBIAMoAoABQQFGBEAgAEEBNgIAIAAgASkCADcCBCAAQRxqIAFBGGooAgA2AgAgAEEUaiABQRBqKQIANwIAIABBDGogAUEIaikCADcCACAERQ0BIAUQwAEMAQsgA0H4AGogAUEgaigCADYCACADQfAAaiABQRhqKQIANwMAIANB6ABqIAFBEGopAgA3AwAgA0HgAGogAUEIaikCACIMNwMAIAMgASkCACINNwNYAkACQAJAAkAgA0E4aigCACIBIAynRgRAIAMoAjAiAiANpyIGRg0BIAIgBiABEI8CRQ0BCxCOASEBIANBgAFqIgJBBzoAACACIAE6AAEgAEEBNgIAIABBHGogA0GYAWooAgA2AgAgAEEUaiADQZABaikDADcCACAAQQxqIANBiAFqKQMANwIAIAAgAykDgAE3AgQMAQsgA0GAAWogA0HkAGoQZSADQYABakEEciEBIAMoAoABQQFGBEAgAEEBNgIAIAAgASkCADcCBCAAQRxqIAFBGGooAgA2AgAgAEEUaiABQRBqKQIANwIAIABBDGogAUEIaikCADcCAAwDCyADQbABaiABQQhqIgIoAgA2AgAgAyABKQIANwOoASADQYABaiADQcgAahBlIAMoAoABQQFGBEAgAEEBNgIAIAAgASkCADcCBCAAQRxqIAFBGGooAgA2AgAgAEEUaiABQRBqKQIANwIAIABBDGogAikCADcCAAwCCyADQcABaiACKAIANgIAIAMgASkCADcDuAEgA0GAAWogA0G4AWoQygEgA0GgAmogAykCgAE3AwAgA0GoAmogA0GIAWooAgA2AgAgA0KAgICAEDcDmAIgA0GAAWogA0GYAmoQGiADQYABakEEciEBIAMoAoABQQFGBEAgA0GQAmoiAiABQRhqKAIANgIAIANBiAJqIgYgAUEQaikCADcDACADQYACaiIHIAFBCGopAgA3AwAgAyABKQIANwP4ASADQZgCahAjIANB8AFqIAIoAgAiATYCACADQegBaiAGKQMAIgw3AwAgA0HgAWogBykDACINNwMAIAMgAykD+AEiDjcD2AEgAEEcaiABNgIAIABBFGogDDcCACAAQQxqIA03AgAgACAONwIEIABBATYCACADKAK8AUUNAiADKAK4ARDAAQwCCyADQYACaiICIAFBCGooAgA2AgAgAyABKQIANwP4ASADQZgCahAjIANB4AFqIAIpAwAiDDcDACADQdABaiAMPgIAIAMgAykD+AE3A8gBAkBBMEEEEEAiAQRAIANBmAJqQeaNwABBBkHsjcAAQQcQXCADQQhqIANBqAFqEF4gA0GAAWpB843AAEELIAMoAgggAygCDBBcIAFBEGogA0GoAmoiBikDADcCACABQQhqIANBoAJqKQMANwIAIAEgAykDmAI3AgAgASADKQOAATcCGCABQSBqIANBiAFqKQMANwIAIAFBKGogA0GQAWoiBykDADcCAEHIAEEIEEAiAkUNASADQYgBaiIIIANBwAFqKAIANgIAIANBlAFqIANBsAFqKAIANgIAIANBsAJqIgkgAykDyAE3AwAgA0G4AmoiCiADQdABaigCADYCACADIAMpA6gBNwKMASADQaACaiILIAgpAwA3AwAgBiAHKQMANwMAIAMgAykDuAE3A5gCIAJBADYCACACIAMpA5gCNwIEIAJBDGogCykDADcCACACQRRqIAYpAwA3AgAgAkEcaiAJKQMANwIAIAJBJGogCigCADYCACAAQRxqQQA2AgAgAEEUakKCgICAIDcCACAAQRBqIAE2AgAgAEEIakKBgICAEDcCACAAIAI2AgQgAEEANgIADAILQTBBBBDHAQALQcgAQQgQxwEACyADKAJcBEAgAygCWBDAAQsgA0HoAGooAgAEQCADKAJkEMABCyADQfQAaigCAARAIAMoAnAQwAELIAQEQCAFEMABCyADQSRqKAIABEAgAygCIBDAAQsgA0E0aigCAARAIAMoAjAQwAELIANBxABqKAIAIgAEQCAAQQV0IQQgA0E8aigCAEEQaiECA0AgAkEEaigCAARAIAIoAgAQwAEL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An8gBEUEQCAFQQEQQAwBCyABKAIAIARBASAFEEELIgNFDQcgASADNgIAIAFBBGogBTYCACABQQhqKAIAIQQLIAMgBGpBIjoAACABQQhqIgMgAygCAEEBaiIENgIAAkAgAUEEaigCACIDIARrQQZPBEAgASgCACEDDAELIARBBmoiBSAESQ0KIANBAXQiBCAFIAQgBUsbIgRBAEgNCgJ/IANFBEAgBEEBEEAMAQsgASgCACADQQEgBBBBCyIDRQ0IIAEgAzYCACABQQRqIAQ2AgAgAUEIaigCACEECyABQQhqIgUgBEEGajYCACADIARqIgNBBGpBpYDAAC8AADsAACADQaGAwAAoAAA2AAACQCABQQRqKAIAIgMgBSgCACIEa0ECTwRAIAEoAgAhAwwBCyAEQQJqIgUgBEkNCiADQQF0IgQgBSAEIAVLGyIEQQBIDQoCfyADRQRAIARBARBADAELIAEoAgAgA0EBIAQQQQsiA0UNCSABIAM2AgAgAUEEaiAENgIAIAFBCGooAgAhBAsgAUEIaiAEQQJqNgIAIAMgBGpBovQAOwAAIAJBKGogAkHQAGogARALIAIoAigiA0EDRw0KIAIgAUEAEHwMCwsgAEEBNgIAIAAgAkEoakEEciIDKQIANwIEIABBHGogA0EYaigCADYCACAAQRRqIANBEGopAgA3AgAgAEEMaiADQQhqKQIANwIADA4LIAZBARDHAQALIAZBARDHAQALIANBARDHAQALIANBARDHAQALIAVBARDHAQALIAVBARDHAQALIARBARDHAQALIARBARDHAQALEMgBAAsgAkEwaigCACEBIAIoAiwhBCACQQxqIAJBNGooAgA2AgAgAkEIaiABNgIAIAIgBDYCBCACIAM2AgALIAACfyACKAIAIgFBA0cEQCACQQxqKAIAIQMgAkEIaigCACEEIAIoAgQhBSACKAKUAQRAIAIoApABEMABCyACQQxqIAM2AgAgAkEIaiAENgIAIAIgBTYCBCACIAE2AgAgAkEoakHyicAAQScgAhAWIAJB+ABqIAJBPGopAgAiDDcDACACIAJBNGopAgAiDTcDcCACKQMoIQ4gAEEMaiACQTBqKAIANgIAIAAgDjcCBCAAQRBqIA03AgAgAEEYaiAMNwIAQQEMAQsgAikDkAEhDCAAQQxqIAIoApgBNgIAIAAgDDcCBEEACzYCACACKAJQIQMgAigCWCIABEAgAEEFdCEBIANBEGohAANAIABBBGooAgAEQCAAKAIAEMABCyAAQSBqIQAgAUFgaiIBDQALCyACKAJURQ0EIAMQwAEMBAsgAkEwaigCACEEIAIoAiwhBSACQZwBaiACQTRqKAIANgIAIAJBmAFqIAQ2AgAgAiAFNgKUASACIAM2ApABCwJAIAIoApABIgNBA0cEQCACQZwBaigCACEEIAJBmAFqKAIAIQUgAigClAEhBiACKAJkRQ0BIAIoAmAQwAEMAQsgAkHYAGogAkH4AGopAwA3AwAgAiACKQNwNwNQIAIpA2AhDCAAQQxqIAIoAmg2AgAgACAMNwIEIABBADYCACACKAIEBEAgAigCABDAAQsgAkEQaigCAARAIAIoAgwQwAELIAJBHGooAgAEQCACKAIYEMABCyAHBEAgCBDAAQsgCkUNAiAJEMABDAILIAJBnAFqIAQ2AgAgAkGYAWogBTYCACACIAY2ApQBIAIgAzYCkAEgAkEoakHOicAAQSQgAkGQAWoQFiACQdgAaiACQTxqKQIAIgw3AwAgAiACQTRqKQIAIg03A1AgAikDKCEOIABBDGogAkEwaigCADYCACAAIA43AgQgAEEQaiANNwIAIABBGGogDDcCACAAQQE2AgAgAigCBARAIAIoAgAQwAELIAJBEGooAgAEQCACKAIMEMABCyACQRxqKAIABEAgAigCGBDAAQsgBwRAIAgQwAELIApFDQEgCRDAAQwBCyAHRQ0AIAgQwAELIAEoAgAiAEUNACABQQRqKAIARQ0AIAAQwAELIAJBsAFqJAALpR4CG38DfiMAQZACayICJAAgAkHwAGogABBpIAJB8ABqQQRyIQACQCACKAJwQQFGBEAgAkHkAGogAEEYaigCADYCACACQdwAaiAAQRBqKQIANwIAIAJB1ABqIABBCGopAgA3AgAgAkEBNgJIIAIgACkCADcCTAwBCyACQfwAaiIDKAIAIQQgAkH4AGoiBSgCACERIAIoAnQhCiACQfAAaiABEGkCQCACKAJwQQFGBEAgAkHkAGogAEEYaigCADYCACACQdwAaiAAQRBqKQIANwIAIAJB1ABqIABBCGopAgA3AgAgAkEBNgJIIAIgACkCADcCTAwBCyADKAIAIQAgBSgCACESIAIoAnQh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2AJBAUcEQAJAIAIoAogDIgAgAigChANHBEAgAigCgAMhAwwBCyAAQQFqIgEgAEkNCSAAQQF0IgMgASADIAFLGyIBQQBIDQkCfyAARQRAIAFBARBADAELIAIoAoADIABBASABEEELIgNFDQIgAiABNgKEAyACIAM2AoADCyAAIANqQfsAOgAAIAIgAigCiANBAWo2AogDIAJBsANqIAJBgANqQY+NwABBAhCBASACKAKwAyIBQQNHBEAgAkG8A2ooAgAhACACQbgDaigCACEDIAIoArQDIQQMBgsCQCACKAKIAyIBIAIoAoQDRwRAIAIoAoADIQMMAQsgAUEBaiIAIAFJDQkgAUEBdCIDIAAgAyAASxsiAEEASA0JAn8gAUUEQCAAQQEQQAwBCyACKAKAAyABQQEgABBBCyIDRQ0DIAIgADYChAMgAiADNgKAAyACKAKIAyEBCyABIANqQTo6AAAgAiACKAKIA0EBajYCiAMgAkGwA2ogAkGAA2oQhAEgAigCsANBAUYEQCACQZgDaiACQbwDaikCADcDACACIAIpArQDNwOQAwwFCyACIAIoArQDNgKABCACIAJBuANqLQAAOgCEBCACQbADaiACQYAEaiAEEDYgAkGwA2ohACACKAKwA0EDRw0DIAJBsANqIAJBgARqIAJB6AJqEDQgAigCsANBA0cNAyACQbADaiACQYAEaiACQfQCahA1IAIoArADQQNHDQMgAkGQA2ogAigCgAQgAi0AhAQQfAwECyACQZAEaiACQYADaiAEEDEgAigCkAQiAUEDRwRAIAJBnARqKAIAIQAgAkGYBGooAgAhAyACKAKUBCEEDAULIAIoAogDIQEMBQsgAUEBEMcBAAsgAEEBEMcBAAsgAkGYA2ogAEEIaikCADcDACACIAApAgA3A5ADCyACKAKQAyIBQQNHBEAgAkGYA2ooAgAhAyACQZwDaigCACEAIAIoApQDIQQMAQsCQCACKAKIAyIBIAIoAoQDRwRAIAIoAoADIQMMAQsgAUEBaiIAIAFJDQQgAUEBdCIDIAAgAyAASxsiAEEASA0EAn8gAUUEQCAAQQEQQAwBCyACKAKAAyABQQEgABBBCyIDRQ0DIAIgADYChAMgAiADNgKAAyACKAKIAyEBCyABIANqQf0AOgAAIAIgAigCiANBAWoiATYCiAMMAQsgAigChAMEQCACKAKAAxDAAQsgAkGcA2ogADYCACACQZgDaiADNgIAIAIgBDYClAMgAiABNgKQAyACQbADakGOhsAAQeoAIAJBkANqEBYgAkGYBGogAkHEA2oiACkCACIXNwMAIAIgAkG8A2oiASkCACIYNwOQBCACKQOwAyEZIAJBuANqIgMgAygCADYCACABIBg3AgAgACAXNwIAIAIgGTcDsANBxIrAAEErIAJBsANqQfCKwAAQ3wEACyACKQOAAyEXIAIgATYCuAMgAiAXNwOwAyACQbADahBoAkAgAigC2AJFBEAgBBAkIAJB8AJqKAIAIgEEQCACQegCaigCACEAIAFBGGwhAQNAIABBBGooAgAEQCAAKAIAEMABCyAAQRBqKAIABEAgAEEMaigCABDAAQsgAEEYaiEAIAFBaGoiAQ0ACwsgAkHsAmooAgAEQCACKALoAhDAAQsgAkH0AmooAgAiAEUNASACQfgCaigCAEUNASAAEMABDAELIAQQHAsgAkGgBGokAA8LIABBARDHAQALEMgBAAu1GwIPfwN+IwBB8AFrIgEkACABQaABaiAAEGlBBCEAAkAgASgCoAFBAUYEQCABQZwBaiABQaABakEEciIAQRhqKAIANgIAIAFBlAFqIABBEGopAgA3AgAgAUGMAWogAEEIaikCADcCACABQQE2AoABIAEgACkCADcChAEMAQsgAUGoAWoiDigCACELIAFB4AFqIAEoAqQBIgwgAUGsAWoiDygCABByIAFB+ABqIAFB4AFqEHkCQCABLQB4QQFxRQ0AIAEtAHkiAkH7AEcEQCACQSJHBEBBCiEADAILIAFBoAFqIAFB4AFqEC8gAUGsAWooAgAhAiABQagBaigCACEEIAEoAqQBIQNBDiEAAkAgAS0AoAEiCEEBTQRAIAhBAWsNAwwBCyACRSADQRRHcg0CIAQQwAEMAgsgAUGwAWooAgAhBSADIQAMAQsgAUHgAWoQcyABQaABaiABQeABaiIJEC8gAUGsAWooAgAhAiABQagBaigCACEEIAEoAqQBIQMgAS0AoQEhBwJAIAEtAKABIgVBAU0EQCAFQQFrDQEgAUGwAWooAgAhBSADIQAMAgsgAkUgA0EUR3INACAEEMABCyABQaABaiAJEHcgASgCoAEiA0EWRwRAIAFBrAFqKAIAIQUgAUGoAWooAgAh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AgAgASAHNgKkASABIAFB4AFqNgKgASABQYABaiABQaABakEEchA8IAtFDQMgDBDAAQwDC0ECIQAMAQtBDiEACyABQewBaiAFNgIAIAFB6AFqIAI2AgAgASAENgLkASABIAA2AuABIAFBoAFqQfyIwABBHCABQeABahAUIAFByAFqIAFBtAFqKQIAIhA3AwAgAUGMAWogDigCADYCACABQZABaiAPKQIANwMAIAFBmAFqIBA3AwAgAUEBNgKAASABIAEpA6ABNwKEASALRQ0AIAwQwAELIAFB0AFqEH8gAUGAAWpBBHIhCAJAAkACQAJAAn8gASgCgAFBAUcEQAJAIAEoAtgBIgcgASgC1AFHBEAgASgC0AEhAgwBCyAHQQFqIgMgB0kNBSAHQQF0IgAgAyAAIANLGyIAQQBIDQUCfyAHRQRAIABBARBADAELIAEoAtABIAdBASAAEEELIgJFDQYgASAANgLUASABIAI2AtABCyACIAdqQfsAOgAAIAEgASgC2AFBAWo2AtgBIAFBoAFqIAFB0AFqQY+NwABBAhCBASABKAKgASIGQQNHBEAgAUGoAWooAgAhAiABKAKkASEEIAFBrAFqKAIADAILAkAgASgC2AEiBiABKALUAUcEQCABKALQASECDAELIAZBAWoiAyAGSQ0FIAZBAXQiACADIAAgA0sbIgBBAEgNBQJ/IAZFBEAgAEEBEEAMAQsgASgC0AEgBkEBIAAQQQsiAkUNBiABIAA2AtQBIAEgAjYC0AEgASgC2AEhBgsgAiAGakE6OgAAIAEgASgC2AFBAWo2AtgBIAFBwAFqIAgQWiABQaABaiABQdABaiABKALAASIAIAEoAsgBEIEBIAEoAsQBBEAgABDAAQsgASgCoAEiBkEDRwRAIAFBqAFqKAIAIQIgASgCpAEhBCABQawBaigCAAwCCwJAIAEoAtgBIgYgASgC1AFHBEAgASgC0AEhAgwBCyAGQQFqIgMgBkkNBSAGQQF0IgAgAyAAIANLGyIAQQBIDQUCfyAGRQRAIABBARBADAELIAEoAtABIAZBASAAEEELIgJFDQYgASAANgLUASABIAI2AtABIAEoAtgBIQYLIAIgBmpB/QA6AAAgASABKALYAUEBaiIGNgLYAQwDCyABQeABaiABQdABaiAIEDEgASgC4AEiBkEDRg0BIAFB6AFq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AmooAgAhBiADQdACaigCACECIAMoAswCIQcgAygCyAJBAUYEQCACIQQgBiECIAEhBiAHIQEMCwsgA0HkBGogATYCACADQeAEaiAGNgIAIANB6ARqIgUgAykD+AQ3AwAgA0HwBGogBCgCADYCACADIAI2AtwEIAMgBzYC2AQgA0GYAmogChB5IAMtAJgCQQFxDQEgA0HYBGoQHEEEIQEMCgsgA0HUAmooAgAhCCADQdACaigCACEFIAMoAswCIQcMAQsgAy0AmQJB/QBHBEAgA0HYBGoQHEELIQEMCQsgChBzIANByARqIAVBCGooAgA2AgAgAyAFKQIANwPABEEBDAQLIAQEQCABEMABCyACRSAMRSABQRRHcnJFBEAgBBDAAQsgCwRAIAghAiAFIQQgByEBDAgLIANBqAJqIAoQeSADLQCoAkEBcQ0CIAUNAQtBBCEBDAYLIAcQwAFBBCEBDAULIAMtAKkCQf0ARwRAQQshASAFRQ0FIAcQwAEMBQsgChBzIAghBiAFIQJBAAshCiADQaAEaiIFIAE2AgAgA0GcBGogBjYCACADQZgEaiACNgIAIANBpARqIAMpA8AENwIAIANBrARqIANByARqKAIANgIAIAMgByIENgKUBCADIAo2ApAEIANBkAJqIA0QeSADLQCQAkEBcUUNASADLQCRAkH9AEcEQAJAIApFBEAgAkUNASAHEMABQQshAQwGCyADQZAEakEEchAcC0ELIQEMBAsgDRBzIANBiARqIAVBCGopAgA3AwAgAyAFKQIANwOABEEACyEIIANB2ANqIg0gBjYCACADQdQDaiACNgIAIANB0ANqIAQ2AgAgA0HcA2ogAykDgAQ3AgAgA0HkA2ogA0GIBGopAwA3AgAgAyAKNgLMAyADIAg2AsgDIANByAJqIANBuANqEHQgA0HUAmohByADQdACaiELIAMoAsgCIgFBFkcEQCAHKAIAIQYgCygCACECIAMoAswCIQQgA0HIA2oQSQwDCyADQfgCaiANQQhqKQIAIhE3AwAgA0GAA2ogDUEQaigCACIFNgIAIAsgCjYCACAHIAQ2AgAgA0HYAmogAjYCACADQdwCaiANKQIAIhI3AgAgA0HkAmogETcCACADQewCaiIBIAU2AgAgAyASNwPwAiADIAg2AswCIANBADYCyAIgEARAIA8QwAELIAAgAykCzAI3AgAgAEEgaiABKAIANgIAIABBGGogA0HkAmopAgA3AgAgAEEQaiADQdwCaikCADcCACAAQQhqIANB1AJqKQIANwIADAMLIApFBEAgAkUNASAHEMABQQQhAQwCCyADQZAEakEEchAcC0EEIQELIANB1ANqIAY2AgAgA0HQA2ogAjYCACADIAQ2AswDIAMgATYCyANBpgFBARBAIgFFDQEgAUHPkcAAQaYBEI4CIQUgAyADQcgDajYCiAUgA0EANgKYBCADQgE3A5AEIANBHjYC/AQgAyADQYgFajYC+AQgAyADQZAEajYC2AQgA0HcAmpBATYCACADQgE3AswCIANBkJHAADYCyAIgAyADQfgEajYC2AIgA0HYBGpB+JLAACADQcgCahDVAQ0CIAMoApQEIgEgAygCmAQiAkcEQCABIAJJDQQCQCACRQRAIAEEQCADKAKQBBDAAQsgA0EBNgKQBEEAIQIMAQsgAygCkAQgAUEBIAIQQSIBRQ0GIAMgATYCkAQLIAMgAjYClAQLIANB4ARqIgIgA0GYBGooAgA2AgAgAyADKQOQBDcD2AQQjgEhBAJAIAMoAsgDQRRHDQAgAygC0ANFDQAgAygCzAMQwAELIANBqANqIgEgAigCADYCACADQZgDaiADQbADaigCADYCACADQZADaiABKQMAIhE3AwAgA0HUAmoiAkKmgYCA4BQ3AgAgA0HQAmogBTYCACADQdwCaiADKQPYBCISNwIAIANB5AJqIgEgET4CACADIBI3A4gDIAMgBEEIdEEFcjYCzAIgA0EBNgLIAiAQBEAgDxDAAQsgAEKAgICAEDcCACAAQQhqIAMpAswCNwIAIABBEGogAikCADcCACAAQRhqIANB3AJqKQIANwIAIABBIGogASgCADYCAAsgDhDAASADQaAFaiQADwtBpgFBARDHAQALQZiRwABBNyADQcgCakGQk8AAEN8BAAtB3JTAAEEkQcyUwAAQzQEACyACQQEQxwEAC5FvAQ9/IwBB8AVrIgIkACACQagFaiABEFUgAkG0BWooAgAhAyACQbAFaigCACEJIAIoAqwFIQQgAi0AqQUhBgJAAkAgAAJ/AkACQAJAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgAi0AqAUiBUEBTQRAIAVBAWsNAgwBCyADRSAE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IAIgBBDPAQALQaCwwABBHEGAssAAEM0BAAsgBEEBagwBCyAKDQMgAwshBCABIAQ2AgggByAESw0ACwsgAEKBgICAMDcCAAwFC0GgsMAAQRxBgLLAABDNAQALQQwhBiALQQFxDQFBESEGIA1BAUYNAQsgCEEQaiAFIAQQ5AEgCCgCEEEBRw0BIAEEQCAFEMABCyAAQoGAgIDwATcCACAAQQhqIAgpAhA3AgAgAEEQaiAIQRhqKAIANgIADAILIABBATYCACAAIAY2AgQgAUUNASAFEMABDAELIAAgBTYCBCAAQQA2AgAgAEEMaiAENgIAIABBCGogATYCAAsgCEEgaiQADwsQbAALIAJBARDHAQALcwEGfwJAIAEoAgQiBCABKAIIIgJNDQAgASgCACEFA0AgAiAFai0AACIGQXdqIgdBF0sEQEEBIQMMAgtBASAHdEGTgIAEcUUEQEEBIQMMAgsgASACQQFqIgI2AgggBCACSw0ACwsgACAGOgABIAAgAzoAAAs4AQF/An9BACABKAIEIAEoAggiAk0NABogASgCACACai0AACECQQELIQEgACACOgABIAAgAToAAAuyAQEDfwJAAkACQCABKAIIIgIgAUEEaigCAEcEQCABKAIAIQQMAQsgAkEBaiIDIAJJDQIgAkEBdCIEIAMgBCADSxsiA0EASA0CAn8gAkUEQCADQQEQQAwBCyABKAIAIAJBASADEEELIgRFDQEgASAENgIAIAFBBGogAzYCACABKAIIIQILIAIgBGpB3QA6AAAgAEEDNgIAIAEgASgCCEEBajYCCA8LIANBARDHAQALEMgBAAuyAQECfwJAAkACQCABKAIIIgIgAUEEaigCAEcEQCABKAIAIQMMAQsgAkEBaiIDIAJJDQIgAkEBdCIEIAMgBCADSxsiBEEASA0CAn8gAkUEQCAEQQEQQAwBCyABKAIAIAJBASAEEEELIgNFDQEgASADNgIAIAFBBGogBDYCACABKAIIIQILIAIgA2pB/QA6AAAgAEEDNgIAIAEgASgCCEEBajYCCA8LIARBARDHAQALEMgBAAvOAgECfwJAAkACQAJAIAEoAggiAiABQQRqKAIARwRAIAEoAgAhAwwBCyACQQFqIgMgAkkNAyACQQF0IgQgAyAEIANLGyIEQQBIDQMCfyACRQRAIARBARBADAELIAEo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ACAAQQhqQQE6AAAgACABNgIEIABBADYCACABIAEoAghBAWo2AggPCyADQQEQxwEACxDIAQAL8wQBBH8jAEEQayIGJAACQAJAAkACQAJAAkAgASgCCCIEIAFBBGooAgBHBEAgASgCACEFDAELIARBAWoiBSAESQ0EIARBAXQiByAFIAcgBUsbIgdBAEgNBAJ/IARFBEAgB0EBEEAMAQsgASgCACAEQQEgBxBBCyIFRQ0BIAEgBTYCACABQQRqIAc2AgAgASgCCCEECyAEIAVqQfsAOgAAQQEhBCABIAEoAghBAWo2AgggBiABIAIgAxCBASAGKAIAIgJBA0cEQCAGQQxqKAIAIQEgBkEIaigCACEDIAYoAgQhBSAAIAI2AgQgAEEQaiABNgIAIABBDGogAzYCACAAQQhqIAU2AgAMBQsCQCABKAIIIgQgAUEEaigCAEcEQCABKAIAIQUMAQsgBEEBaiICIARJDQQgBEEBdCIDIAIgAyACSxsiAkEASA0EAn8gBEUEQCACQQEQQAwBCyABKAIAIARBASACEEELIgVFDQIgASAFNgIAIAFBBGogAjYCACABKAIIIQQLIAQgBWpBOjoAACABIAEoAghBAWoiBDYCCAJAIAFBBGooAgAgBEcEQCABKAIAIQUMAQsgBEEBaiICIARJDQQgBEEBdCIDIAIgAyACSxsiAkEASA0EAn8gBEUEQCACQQEQQAwBCyABKAIAIARBASACEEELIgVFDQMgASAFNgIAIAFBBGogAjYCACABKAIIIQQLIAQgBWpB+wA6AAAgACABNgIEIABBCGpBAToAACABIAEoAghBAWo2AghBACEEDAQLIAdBARDHAQALIAJBARDHAQALIAJBARDHAQALEMgBAAsgACAENgIAIAZBEGokAAucEAIJfwN+AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQEEAIAFBZmoiBiAGIAFLGyIHBEADQCAJQRpqIgggCUkiBg0CIAYNByAIIAFLDQggC0EgaiIIIAtJIgYNAyAGDQkgCCADSw0KIAIgC2oiBSAEIAAgCWoiDCkAACIOQjiGIg9COoinai0AADoAACAFQQFqIAQgDyAOQiiGQoCAgICAgMD/AIOEIg9CNIinQT9xai0AADoAACAFQQJqIAQgDyAOQhiGQoCAgICA4D+DIA5CCIZCgICA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AyAEQQEQxwEACyACQQEQxwEACxDIAQALQeTIwABBJEHUyMAAEM0BAAsgACAENgIEIAAgATYCAAv0AQEDfyMAQRBrIgIkACAAKAIAQRhqIgMoAgAhASADQQI2AgACQAJAAkACQCABQQJNBEAgAUEBaw0CDAELQZzLwABBHEGMy8AAEJoBAAsgACgCACIDQRxqIgEoAgAiAC0AAA0BIABBAToAAEEAIQACQEGQhsEAKAIAQQFGBEBBlIbBACgCACEADAELQZCGwQBCATcDAAtBlIbBACAANgIAIANBIGotAAANAiABKAIAQQA6AAALIAJBEGokAA8LQcTPwABBIEG0z8AAEJoBAAsgAiABNgIIIAIgAEEARzoADEH4x8AAQSsgAkEIakGkyMAAEN8BAAsJACAAQQA2AgALPAECfyAAKAIIIgFB3MLAACgCAEYEfyAAKAIAIgBB2MLAACgCACICRgRAQQEPCyAAIAIgARCPAkUFQQALC7kDAQV/IwBBEGsiAyQAIANBAnIhBEGogsEAKAIAIQEDQAJAAkACQAJAAkAgASICQQNLDQACQAJAIAJBAWsOAwMCAQALQaiCwQBBAkGogsEAKAIAIgEgASACRhs2AgAgASACRw0GIANBqILBADYCACAAIAJBAUZBuMHAACgCABEBACADQQM2AgQgAxCvAQsgA0EQaiQADwsgAkEDcUECRgRAA0BBwILBACgCAEEBRwRAQcCCwQBCATcCAEHIgsEAQQA2AgALIAIhARClASEFQaiCwQAgBEGogsEAKAIAIgIgASACRhs2AgAgA0EAOgAIIAMgBTYCACADIAFBfHE2AgQgASACRgRAIAMtAAhFDQQMBQsCQCADKAIAIgFFDQAgASABKAIAIgFBf2o2AgAgAUEBRw0AIAMQpAELIAJBA3FBAkYNAAwFCwALQcTMwABBOUG0zMAAEJoBAAtBkM3AAEEqQYDNwAAQmgEACwNAEKYBIAMtAAhFDQALCyADKAIAIgJFDQAgAiACKAIAIgJBf2o2AgAgAkEBRw0AIAMQpAFBqILBACgCACEBDAELQaiCwQAoAgAhAQwACwALowIBA38jAEFAaiIBJAAgACgCACICKAIAIQMgAiAAKAIENgIAIAEgA0EDcSIANgIMIABBAkYEQAJAIANBfHEiAARAA0AgACgCBCAAKAIAIQIgAEEA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AAtBAAwECyAFQQQQzgEACyABIAJBACAEENEBAAsgASACIAQgAhDRAQALQQELIANBMGokAAt4AQJ/IAAtAAQhASAALQAFBEAgAUH/AXEhAiAAAn9BASACDQAaIAAoAgAiAUEcaigCACgCDCECIAEoAhghACABLQAAQQRxRQRAIABB49vAAEECIAIRAgAMAQsgAEHi28AAQQEgAhECAAsiAToABAsgAUH/AXFBAEcL5QICA38FfiMAQdAAayIDJAAgAAJ/QQEgAC0ACA0AGiAAKAIEIQUgACgCACIELQAAQQRxRQRAQQEgBCgCGEHd28AAQefbwAAgBRtBAkEBIAUbIARBHGooAgAoAgwRAgANARogASAAKAIAIAIoAgwRAAAMAQsgBUUEQEEBIAQoAhhB5dvAAEECIARBHGooAgAoAgwRAgANARogACgCACEECyADQQE6ABcgAyADQRdqNgIQIAQpAgghBiAEKQIQIQcgA0E0akG828AANgIAIAMgBCkCGDcDCCAEKQIgIQggBCkCKCEJIAMgBC0AMDoASCAEKQIAIQogAyAJNwNAIAMgCDcDOCADIAc3AyggAyAGNwMgIAMgCjcDGCADIANBCGo2AjBBASABIANBGGogAigCDBEAAA0AGiADKAIwQdvbwABBAiADKAI0KAIMEQIACzoACCAAIAAoAgRBAWo2AgQgA0HQAGokAAuWAQECfyAALQAIIQEgACgCBCICBEAgAUH/AXEhASAAAn9BASABDQAaAkAgAkEBRw0AIAAtAAlFDQAgACgCACICLQAAQQRxDQBBASACKAIYQejbwABBASACQRxqKAIAKAIMEQIADQEaCyAAKAIAIgEoAhhBlNfAAEEBIAFBHGooAgAoAgwRAgALIgE6AAgLIAFB/wFxQQBHCwsAIAAgASACEOcBCzIBAX9BASEBIAAtAAQEfyABBSAAKAIAIgAoAhhB/NvAAEEBIABBHGooAgAoAgwRAgALC+gBAQF/IwBBEGsiAiQAIAJBADYCDCAAIAJBDGoCfwJAIAFBgAFPBEAgAUGAEEkNASABQYCABEkEQCACIAFBP3FBgAFyOgAOIAIgAUEGdkE/cUGAAXI6AA0gAiABQQx2QQ9xQeABcjoADEEDDAMLIAIgAUE/cUGAAXI6AA8gAiABQRJ2QfABcjoADCACIAFBBnZBP3FBgAFy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CWohAwwECyAPQv////+PYINCgICAgMAAhAshD0EDIQQLIAIoAhggAyACKAIcKAIQEQAARQ0ACwwECyAJIA1rIAZqIQkgBiENIAYgDEcNAQsLIANFIAEgA0ZyDQAgAyABTw0CIAAgA2osAABBv39MDQILQQEhCiACKAIYIAAgA2ogASADayACKAIcKAIMEQIADQAgAigCGEEiIAIoAhwoAhARAAAhCgsgCEEgaiQAIAoPCyAAIAEgAyABENEBAAsLACACIAAgARDQAQuKAQEDfyMAQYABayIDJAAgACgCACECQQAhAANAIAAgA2pB/wBqIAJBD3EiBEEwciAEQdcAaiAEQQpJGzoAACAAQX9qIQAgAkEEdiICDQALIABBgAFqIgJBgQFPBEAgAkGAARDPAQALIAFBAUH928AAQQIgACADakGAAWpBACAAaxD2ASADQYABaiQAC9cCAQd/QQEhCQJAAkAgAkUNACABIAJBAXRqIQogAEGA/gNxQQh2IQsgAEH/AXEhDQJAA0AgAUECaiEMIAcgAS0AASICaiEIIAsgAS0AACIBRwRAIAEgC0sNAyAIIQcgDCIBIApHDQEMAwsgCCAHTwRAIAggBEsNAiADIAdqIQECQANAIAJFDQEgAkF/aiECIAEtAAAgAUEBaiEBIA1HDQALQQAhCQwFCyAIIQcgDCIBIApHDQEMAwsLIAcgCBDPAQALIAggBBDOAQALIAZFDQAgBSAGaiEDIABB//8DcSEBA0ACQCAFQQFqIQACfyAAIAUtAAAiAkEYdEEYdSIEQQBODQAaIAAgA0YNASAFLQABIARB/wBxQQh0ciECIAVBAmoLIQUgASACayIBQQBIDQIgCUEBcyEJIAMgBUcNAQwCCwtBzNTAAEErQYzVwAAQzQEACyAJQQFxC8oCAgN/BH4jAEEwayIDJAACQCACRQRAIABBADoAAUEBIQQMAQsCQCABLQAAQStGBEBBASEEIAJBf2oiAkUNASABQQFqIQELIANBKGohBAJAA0AgAkUNASABLQAAQVBqIgVBCk8EQEEBIQQgAEEBOgABDAQLIANBEGogB0IAQgoQkgIgA0EgaiAGQgBCChCSAiADQgBCACAGEJICIAMpAxggAykDCIRCAFIgBCkDACIGIAMpAxAgAykDAHx8IgggBlRyQQFGBEAgAEECOgABQQEhBAwE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ZXNyY192YWxpZGF0b3Jkc3RfdmFsaWRhdG9yd2l0aGRyYXd2YWxpZGF0b3JyZWNpcGllbnR1bmRlbGVnYXRlZGVsZWdhdGVJbml0UmVzcG9uc2Vsb2dMb2dBdHRyaWJ1dGVrZXl2YWx1ZUhhbmRsZVJlc3BvbnNlQ29pbmRlbm9tQmFua1F1ZXJ5YWxsX2JhbGFuY2VzYWRkcmVzc2JhbGFuY2VXYXNtUXVlcnlyYXdzbWFydFN0YWtpbmdRdWVyeXZhbGlkYXRvcnNkZWxlZ2F0aW9uc2RlbGVnYXRvcmJvbmRlZF9kZW5vbUFsbEJhbGFuY2VSZXNwb25zZWJsb2NrbWVzc2FnZWNvbnRyYWN0aGVpZ2h0dGltZWNoYWluX2lkc2VuZGVyc2VudF9mdW5kc1N0ZEVycm9ydW5kZXJmbG93bWludWVuZHN1YnRyYWhlbmR1bmF1dGhvcml6ZWRzZXJpYWxpemVfZXJyc291cmNlcGFyc2VfZXJydGFyZ2V0bnVsbF9wb2ludGVybm90X2ZvdW5ka2luZGludmFsaWRfdXRmOGludmFsaWRfYmFzZTY0Z2VuZXJpY19lcnJTZXJpYWxpemluZyBRdWVyeVJlcXVlc3Q6IABFAhAAGgAAAFF1ZXJpZXIgc3lzdGVtIGVycm9yOiAAAGgCEAAWAAAACwAAAAgAAAAEAAAADAAAAA0AAACcAhAAAAAAAGEgRGlzcGxheSBpbXBsZW1lbnRhdGlvbiByZXR1cm5lZCBhbiBlcnJvciB1bmV4cGVjdGVkbHljb3Ntd2FzbV9zdGQ6OnR5cGVzOjpFbnZoYWNrYXRvbTo6Y29udHJhY3Q6OkluaXRNc2djb3JlOjpyZXN1bHQ6OlJlc3VsdDxjb3Ntd2FzbV9zdGQ6OmluaXRfaGFuZGxlOjpIYW5kbGVSZXNwb25zZSwgY29zbXdhc21fc3RkOjplcnJvcnM6OnN0ZF9lcnJvcjo6U3RkRXJyb3I+Y29zbXdhc21fc3RkOjpxdWVyeTo6UXVlcnlSZXF1ZXN0PGNvc213YXNtX3N0ZDo6dHlwZXM6Ok5ldmVyPmNvcmU6OnJlc3VsdDo6UmVzdWx0PGNvc213YXNtX3N0ZDo6ZW5jb2Rpbmc6OkJpbmFyeSwgY29zbXdhc21fc3RkOjplcnJvcnM6OnN0ZF9lcnJvcjo6U3RkRXJyb3I+Y29yZTo6cmVzdWx0OjpSZXN1bHQ8Y29zbXdhc21fc3RkOjppbml0X2hhbmRsZTo6SW5pdFJlc3BvbnNlLCBjb3Ntd2FzbV9zdGQ6OmVycm9yczo6c3RkX2Vycm9yOjpTdGRFcnJvcj5oYWNrYXRvbTo6Y29udHJhY3Q6OlF1ZXJ5TXNnaGFja2F0b206OmNvbnRyYWN0OjpTdGF0ZWhhY2thdG9tOjpjb250cmFjdDo6SGFuZGxlTXNnaGFja2F0b206OmNvbnRyYWN0OjpWZXJpZmllclJlc3BvbnNlY29zbXdhc21fc3RkOjpxdWVyeTo6QWxsQmFsYW5jZVJlc3BvbnNlAAAADgAAAAQAAAAEAAAADwAAABAAAAARAAAAEgAAAAAAAAABAAAAEwAAAGNhbGxlZCBgUmVzdWx0Ojp1bndyYXAoKWAgb24gYW4gYEVycmAgdmFsdWUAFAAAABwAAAAEAAAAFQAAAGF0dGVtcHQgdG8gYWRkIHdpdGggb3ZlcmZsb3c8Ojpjb3JlOjptYWNyb3M6OnBhbmljIG1hY3Jvcz4AAJwFEAAeAAAAAwAAAAoAAABUcmllZCB0byBzaHJpbmsgdG8gYSBsYXJnZXIgY2FwYWNpdHltaXNzaW5nIGZpZWxkIGBg8AUQAA8AAAD/BRAAAQAAAGR1cGxpY2F0ZSBmaWVsZCBgAAAAEAYQABEAAAD/BRAAAQAAAHVua25vd24gdmFyaWFudCBgYCwgdGhlcmUgYXJlIG5vIHZhcmlhbnRzAAAANAYQABEAAABFBhAAGAAAAGAsIGV4cGVjdGVkIDQGEAARAAAAcAYQAAwAAABFcnJPa2ludmFsaWQgVWludDEyOCAnJyAtIAAAkQYQABEAAACiBhAABAAAAGludmFsaWQgYmFzZTY0OiC4BhAAEAAAAAsAAAAIAAAABAAAABYAAABjb25maWdhY3Rpb25yZWxlYXNlZGVzdGluYXRpb25TdGF0ZXNyYy9jb250cmFjdC5ycwAAAwcQAA8AAAB/AAAACQAAAHRlc3Qua2V5AwcQAA8AAACNAAAACQAAAG11c3Qgbm90IGJlIGVtcHR5AAAAAwcQAA8AAACVAAAAEwAAAEVycm9yIGluIG1lbW9yeS5ncm93IGluc3RydWN0aW9uAwcQAA8AAACuAAAABQAAAFRoaXMgcGFnZSBpbnRlbnRpb25hbGx5IGZhdWx0ZWR2ZXJpZmllcmJlbmVmaWNpYXJ5ZnVuZGVyY3B1X2xvb3BzdG9yYWdlX2xvb3BtZW1vcnlfbG9vcGFsbG9jYXRlX2xhcmdlX21lbW9yeXBhbmljAAAA7AYQAAcAAADIBxAACAAAANAHEAAMAAAA3AcQAAsAAADnBxAAFQAAAPwHEAAFAAAAb3RoZXJfYmFsYW5jZQAAAK8HEAAIAAAANAgQAA0AAABWZXJpZmllclJlc3BvbnNlT2tFcnIAAABkCBAAAgAAAGYIEAADAAAAHwAAAAgAAAAEAAAAIAAAACEAAACQCBAAAAAAAGEgRGlzcGxheSBpbXBsZW1lbnRhdGlvbiByZXR1cm5lZCBhbiBlcnJvciB1bmV4cGVjdGVkbHljb3JlOjpyZXN1bHQ6OlJlc3VsdDxjb3JlOjpyZXN1bHQ6OlJlc3VsdDxjb3Ntd2FzbV9zdGQ6OmVuY29kaW5nOjpCaW5hcnksIGNvc213YXNtX3N0ZDo6ZXJyb3JzOjpzdGRfZXJyb3I6OlN0ZEVycm9yPiwgY29zbXdhc21fc3RkOjplcnJvcnM6OnN5c3RlbV9lcnJvcjo6U3lzdGVtRXJyb3I+AAAAIgAAAAQAAAAEAAAAIwAAACQAAAAlAAAAJgAAAAAAAAABAAAAEwAAACcAAAAUAAAABAAAACgAAAAvcnVzdGMvZjNlMWE5NTRkMmVhZDRlMmZjMTk3YzdkYTdkNzFlNmM2MWJhZDE5Ni9zcmMvbGliY29yZS9vcHMvYXJpdGgucnOwCRAASAAAALsCAAAzAEGQlMAAC+EFYXR0ZW1wdCB0byBhZGQgd2l0aCBvdmVyZmxvdzw6OmNvcmU6Om1hY3Jvczo6cGFuaWMgbWFjcm9zPgAALAoQAB4AAAADAAAACgAAAFRyaWVkIHRvIHNocmluayB0byBhIGxhcmdlciBjYXBhY2l0eW1pc3NpbmcgZmllbGQgYGCAChAADwAAAI8KEAABAAAAZHVwbGljYXRlIGZpZWxkIGAAAACgChAAEQAAAI8KEAABAAAAdW5rbm93biB2YXJpYW50IGBgLCB0aGVyZSBhcmUgbm8gdmFyaWFudHMAAADEChAAEQAAANUKEAAYAAAAYCwgZXhwZWN0ZWQgxAoQABEAAAAACxAADAAAAFNvbWUiAAAABAAAAAQAAAApAAAATm9uZSIAAAAEAAAABAAAACoAAAAvdXNyL2xvY2FsL2NhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvYmFzZTY0LTAuMTEuMC9zcmMvZGVjb2RlLnJzAAAARAsQAFUAAADHAQAAHwAAAEQLEABVAAAAzQEAAB8AAABECxAAVQAAANABAAANAAAARAsQAFUAAADWAQAAHwAAAEQLEABVAAAA2QEAAA0AAABECxAAVQAAAN8BAAAfAAAARAsQAFUAAADiAQAADQAAAEQLEABVAAAA6AEAAB8AAABECxAAVQAAAOsBAAANAAAARAsQAFUAAADxAQAAHwAAAEQLEABVAAAA9AEAAA0AAABECxAAVQAAAPoBAAAfAAAARAsQAFUAAAD9AQAADQAAAEQLEABVAAAAAwIAAB8AAABECxAAVQAAAAYCAAANAAAARAsQAFUAAABtAAAALwAAAAAAAABhdHRlbXB0IHRvIG11bHRpcGx5IHdpdGggb3ZlcmZsb3cAAABECxAAVQAAAPgAAAA3AAAARAsQAFUAAAD5AAAAPgAAAEQLEABVAAAAFgEAABEAQYCawAALlRZhdHRlbXB0IHRvIHN1YnRyYWN0IHdpdGggb3ZlcmZsb3cAAABECxAAVQAAAB8BAAApAAAARAsQAFUAAAAjAQAAKQAAAEQLEABVAAAAIwEAACgAAABECxAAVQAAACgBAAARAAAARAsQAFUAAAA5AQAAJwAAAEQLEABVAAAAPAEAAAkAAABECxAAVQAAAFsBAAApAAAARAsQAFUAAABtAQAADQAAAEQLEABVAAAAdwEAABEAAABECxAAVQAAAH8BAAAVAAAARAsQAFUAAACDAQAAMQAAAGludGVybmFsIGVycm9yOiBlbnRlcmVkIHVucmVhY2hhYmxlIGNvZGU6IAAA1A0QACoAAABJbXBvc3NpYmxlOiBtdXN0IG9ubHkgaGF2ZSAwIHRvIDggaW5wdXQgYnl0ZXMgaW4gbGFzdCBjaHVuaywgd2l0aCBubyBpbnZhbGlkIGxlbmd0aHMIDhAAVAAAAEQLEABVAAAAkgEAAA4AAABECxAAVQAAAJ0BAAANAAAARAsQAFUAAACmAQAACQAAAE92ZXJmbG93IHdoZW4gY2FsY3VsYXRpbmcgb3V0cHV0IGJ1ZmZlciBsZW5ndGhJbnZhbGlkIFVURjgvdXNyL2xvY2FsL2NhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvYmFzZTY0LTAuMTEuMC9zcmMvZW5jb2RlLnJzAM4OEABVAAAALwAAABEAAABpbnRlZ2VyIG92ZXJmbG93IHdoZW4gY2FsY3VsYXRpbmcgYnVmZmVyIHNpemV1c2l6ZSBvdmVyZmxvdyB3aGVuIGNhbGN1bGF0aW5nIGJ1ZmZlciBzaXplHwAAAAgAAAAEAAAAKwAAAGludmFsaWQgYmFzZTY0OiCcDxAAEAAAAFVuc3VwcG9ydCBxdWVyeSB0eXBlOiAAALQPEAAWAAAAVW5rbm93biBzeXN0ZW0gZXJyb3LUDxAAFAAAAE5vIHN1Y2ggY29udHJhY3Q6IAAA8A8QABIAAABDYW5ub3QgcGFyc2UgcmVxdWVzdDogAAAMEBAAFgAAAEFsbG9jYXRlZCBtZW1vcnkgdG9vIHNtYWxsIHRvIGhvbGQgdGhlIGRhdGFiYXNlIHZhbHVlIGZvciB0aGUgZ2l2ZW4ga2V5LiBZb3UgY2FuIHNwZWNpZnkgY3VzdG9tIHJlc3VsdCBidWZmZXIgbGVuZ3RocyBieSB1c2luZyBFeHRlcm5hbFN0b3JhZ2UuZ2V0X3dpdGhfcmVzdWx0X2xlbmd0aCBleHBsaWNpdGVseS5FcnJvciByZWFkaW5nIGZyb20gZGF0YWJhc2UuIEVycm9yIGNvZGU6IADeEBAAKQAAAEVycm9yIHdyaXRpbmcgdG8gZGF0YWJhc2UuIEVycm9yIGNvZGU6IAAQERAAJwAAAGNhbm9uaWNhbGl6ZV9hZGRyZXNzIHJldHVybmVkIGVycm9yaHVtYW5pemVfYWRkcmVzcyByZXR1cm5lZCBlcnJvcmdlbmVyaWNfZXJybXNnaW52YWxpZF9iYXNlNjRpbnZhbGlkX3V0Zjhub3RfZm91bmRraW5kbnVsbF9wb2ludGVycGFyc2VfZXJydGFyZ2V0c2VyaWFsaXplX2VycnNvdXJjZXVuYXV0aG9yaXplZHVuZGVyZmxvd21pbnVlbmRzdWJ0cmFoZW5kQ2Fubm90IHN1YnRyYWN0ICBmcm9tIAAAAAsSEAAQAAAAGxIQAAYAAABVbmF1dGhvcml6ZWQ0EhAADAAAAEVycm9yIHNlcmlhbGl6aW5nIHR5cGUgOiAAAABIEhAAFwAAAF8SEAACAAAARXJyb3IgcGFyc2luZyBpbnRvIHR5cGUgdBIQABgAAABfEhAAAgAAAFJlY2VpdmVkIG51bGwgcG9pbnRlciwgcmVmdXNlIHRvIHVzZZwSEAAkAAAAIG5vdCBmb3VuZAAAkAgQAAAAAADIEhAACgAAAENhbm5vdCBkZWNvZGUgVVRGOCBieXRlcyBpbnRvIHN0cmluZzogAADkEhAAJgAAAEludmFsaWQgQmFzZTY0IHN0cmluZzogABQTEAAXAAAAR2VuZXJpYyBlcnJvcjogADQTEAAPAAAATnVsbFBvaW50ZXIAghEQAAsAAACQERAADgAAAJ4REAAMAAAAqhEQAAkAAAC3ERAADAAAAMMREAAJAAAA0hEQAA0AAADlERAADAAAAPEREAAJAAAAVW5kZXJmbG93YmFja3RyYWNlAAAiAAAABAAAAAQAAAAsAAAAU2VyaWFsaXplRXJyUGFyc2VFcnJOb3RGb3VuZEludmFsaWRVdGY4SW52YWxpZEJhc2U2NEdlbmVyaWNFcnJpbnZhbGlkX3JlcXVlc3RlcnJvcm5vX3N1Y2hfY29udHJhY3RhZGRydW5rbm93bnVuc3VwcG9ydGVkX3JlcXVlc3QCFBAADwAAABYUEAAQAAAAKhQQAAcAAAAxFBAAEwAAAC8AAAAIAAAABAAAADAAAAAxAAAALwAAAAgAAAAEAAAAMgAAAIgUEAAAAAAASW52YWxpZCBKU09OSlNPTiBoYXMgYSBjb21tYSBhZnRlciB0aGUgbGFzdCB2YWx1ZSBpbiBhbiBhcnJheSBvciBtYXAuSlNPTiBoYXMgbm9uLXdoaXRlc3BhY2UgdHJhaWxpbmcgY2hhcmFjdGVycyBhZnRlciB0aGUgdmFsdWUuRm91bmQgYSBsb25lIHN1cnJvZ2F0ZSwgd2hpY2ggY2FuIGV4aXN0IGluIEpTT04gYnV0IGNhbm5vdCBiZSBlbmNvZGVkIHRvIFVURi04Lk9iamVjdCBrZXkgaXMgbm90IGEgc3RyaW5nLkludmFsaWQgdW5pY29kZSBjb2RlIHBvaW50LkludmFsaWQgdHlwZUludmFsaWQgbnVtYmVyLkludmFsaWQgZXNjYXBlIHNlcXVlbmNlLkV4cGVjdGVkIHRoaXMgY2hhcmFjdGVyIHRvIHN0YXJ0IGEgSlNPTiB2YWx1ZS5FeHBlY3RlZCB0byBwYXJzZSBlaXRoZXIgYSBgdHJ1ZWAsIGBmYWxzZWAsIG9yIGEgYG51bGxgLkV4cGVjdGVkIHRoaXMgY2hhcmFjdGVyIHRvIGJlIGVpdGhlciBhIGAnLCdgIG9yIGEgYCd9J2AuRXhwZWN0ZWQgYSBsb3cgc3Vycm9nYXRlIChEQzAw4oCTREZGRikuRXhwZWN0ZWQgdGhpcyBjaGFyYWN0ZXIgdG8gYmUgZWl0aGVyIGEgYCcsJ2Agb3JhIGAnXSdgLkV4cGVjdGVkIGEgaGlnaCBzdXJyb2dhdGUgKEQ4MDDigJNEQkZGKS5FeHBlY3RlZCB0aGlzIGNoYXJhY3RlciB0byBiZSBhIGAnOidgLkVPRiB3aGlsZSBwYXJzaW5nIGEgSlNPTiB2YWx1ZS5FT0Ygd2hpbGUgcGFyc2luZyBhIHN0cmluZy5FT0Ygd2hpbGUgcGFyc2luZyBhbiBvYmplY3QuRU9GIHdoaWxlIHBhcnNpbmcgYSBsaXN0LkNvbnRyb2wgY2hhcmFjdGVyIGZvdW5kIGluIHN0cmluZy4vdXNyL2xvY2FsL2NhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvc2VyZGUtanNvbi13YXNtLTAuMi4xL3NyYy9kZS91bmVzY2FwZS5ycwAApBcQAGIAAAAlAAAAFQBBoLDAAAvxA2F0dGVtcHQgdG8gYWRkIHdpdGggb3ZlcmZsb3ekFxAAYgAAADMAAAApAAAAAAAAAGF0dGVtcHQgdG8gc3VidHJhY3Qgd2l0aCBvdmVyZmxvdwAAAKQXEABiAAAAmQAAAA4AAABOb24taGV4IEFTQ0lJIGNoYXJhY3RlciBmb3VuZC91c3IvbG9jYWwvY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9zZXJkZS1qc29uLXdhc20tMC4yLjEvc3JjL2RlL21vZC5ycwAAoRgQAF0AAAAeAAAACQAAAKEYEABdAAAAewAAACsAAAChGBAAXQAAAHsAAAAgAAAAoRgQAF0AAAB8AAAAIQAAAFVua25vd24gc2VyaWFsaXphdGlvbiBlcnJvcgBAGRAAGwAAAEJ1ZmZlciBpcyBmdWxsAABkGRAADgAAAC91c3IvbG9jYWwvY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9zZXJkZS1qc29uLXdhc20tMC4yLjEvc3JjL3Nlci9tb2QucnMAAHwZEABeAAAA0QAAAAkAAAAAAAAAYXR0ZW1wdCB0byBzdWJ0cmFjdCB3aXRoIG92ZXJmbG93AEGgtMAAC4skYXR0ZW1wdCB0byBhZGQgd2l0aCBvdmVyZmxvd3VzaXplIG92ZXJmbG93IHdoZW4gY2FsY3VsYXRpbmcgYjY0IGxlbmd0aC91c3IvbG9jYWwvY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9iYXNlNjQtMC4xMS4wL3NyYy9lbmNvZGUucnMAZhoQAFUAAAC7AAAAMwAAAGYaEABVAAAAvAAAADoAAABmGhAAVQAAAPwAAAAYAAAAZhoQAFUAAAABAQAALwAAAGYaEABVAAAAAgEAADYAAABmGhAAVQAAABABAAAuAAAAZhoQAFUAAAAQAQAACQAAAGYaEABVAAAAEgEAAA8AAABmGhAAVQAAABEBAAAJAAAAZhoQAFUAAAAUAQAACQAAAGYaEABVAAAAFgEAAAkAAABmGhAAVQAAABgBAAAuAAAAZhoQAFUAAAAYAQAACQAAAGYaEABVAAAAGQEAAAkAAABpbnRlcm5hbCBlcnJvcjogZW50ZXJlZCB1bnJlYWNoYWJsZSBjb2RlOiAAAJwbEAAqAAAASW1wb3NzaWJsZSByZW1haW5kZXLQGxAAFAAAAGYaEABVAAAALwEAABYAAABmGhAAVQAAAEABAAAJAAAASW52YWxpZCBsYXN0IHN5bWJvbCAsIG9mZnNldCAuAAAMHBAAFAAAACAcEAAJAAAAKRwQAAEAAABFbmNvZGVkIHRleHQgY2Fubm90IGhhdmUgYSA2LWJpdCByZW1haW5kZXIuAEQcEAArAAAASW52YWxpZCBieXRlIAAAAHgcEAANAAAAIBwQAAkAAAApHBAAAQAAAE92ZXJmbG93IHdoZW4gY2FsY3VsYXRpbmcgbnVtYmVyIG9mIGNodW5rcyBpbiBpbnB1dC4vMDEyMzQ1Njc4OUFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OS1fQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrL/////////////////////////////////////////////////////////////8AAQIDBAUGBwgJCgv/////////DA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCX///////8mJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8+//80NTY3ODk6Ozw9/////////wABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ/////z//GhscHR4fICEiIyQlJicoKSorLC0uLzAxMjP//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////z7///8/NDU2Nzg5Ojs8Pf////////8AAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGf///////xobHB0eHyAhIiMkJSYnKCkqKywtLi8wMTIz/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBTHRAAEx0QANMcEACTHxAAkx4QAJMdEAA2AAAABAAAAAQAAAA3AAAAOAAAACgpL3J1c3RjL2YzZTFhOTU0ZDJlYWQ0ZTJmYzE5N2M3ZGE3ZDcxZTZjNjFiYWQxOTYvc3JjL2xpYmNvcmUvbWFjcm9zL21vZC5ycwDCIBAASQAAAA8AAAAoAAAAY2FsbGVkIGBPcHRpb246OnVud3JhcCgpYCBvbiBhIGBOb25lYCB2YWx1ZVJVU1RfQkFDS1RSQUNFMQAAVSEQAAEAAABSVVNUX0xJQl9CQUNLVFJBQ0VCYWNrdHJhY2UANgAAAAQAAAAEAAAAOQAAADwAAAAIAAAABAAAAD0AAAA+AAAAPAAAAAgAAAAEAAAAPwAAAGBvbmUgb2YgsSEQAAcAAAAsIAAAwCEQAAIAAACwIRAAAQAAALAhEAABAAAAYCBvciBgAACwIRAAAQAAANwhEAAGAAAAsCEQAAEAAAAvdXNyL2xvY2FsL2NhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvc2VyZGUtMS4wLjEwNC9zcmMvZGUvbW9kLnJzAAAA/CEQAFUAAADVCAAAEgAAAGV4cGxpY2l0IHBhbmljAABDAAAABAAAAAQAAABEAAAARQAAAEYAAABDAAAABAAAAAQAAABHAAAAYWxyZWFkeSBib3Jyb3dlZGFscmVhZHkgbXV0YWJseSBib3Jyb3dlZC9ydXN0Yy9mM2UxYTk1NGQyZWFkNGUyZmMxOTdjN2RhN2Q3MWU2YzYxYmFkMTk2L3NyYy9saWJjb3JlL21hY3Jvcy9tb2QucnNhc3NlcnRpb24gZmFpbGVkOiBgKGxlZnQgPT0gcmlnaHQpYAogIGxlZnQ6IGBgLAogcmlnaHQ6IGBgAA0jEAAtAAAAOiMQAAwAAABGIxAAAQAAAMQiEABJAAAADwAAACgAAABIAAAAAAAAAAEAAABJAAAAYDogAA0jEAAtAAAAOiMQAAwAAACAIxAAAwAAAGNhbGxlZCBgT3B0aW9uOjp1bndyYXAoKWAgb24gYSBgTm9uZWAgdmFsdWUASAAAAAAAAAABAAAASgAAAEsAAAAQAAAABAAAAEwAAABIAAAAAAAAAAEAAABNAAAAY2FsbGVkIGBSZXN1bHQ6OnVud3JhcCgpYCBvbiBhbiBgRXJyYCB2YWx1ZQBOAAAACAAAAAQAAABPAAAAPDo6Y29yZTo6bWFjcm9zOjpwYW5pYyBtYWNyb3M+AAA0JBAAHgAAAAMAAAAKAAAAVHJpZWQgdG8gc2hyaW5rIHRvIGEgbGFyZ2VyIGNhcGFjaXR5QwAAAAQAAAAEAAAAQQAAAHNyYy9saWJzdGQvdGhyZWFkL21vZC5yc5gkEAAYAAAAiQMAABMAAABpbmNvbnNpc3RlbnQgcGFyayBzdGF0ZQACAAAAcGFyayBzdGF0ZSBjaGFuZ2VkIHVuZXhwZWN0ZWRseQDcJBAAHwAAAJgkEAAYAAAAhgMAAA0AAACYJBAAGAAAAB8EAAARAAAAZmFpbGVkIHRvIGdlbmVyYXRlIHVuaXF1ZSB0aHJlYWQgSUQ6IGJpdHNwYWNlIGV4aGF1c3RlZHRocmVhZCBuYW1lIG1heSBub3QgY29udGFpbiBpbnRlcmlvciBudWxsIGJ5dGVzAACYJBAAGAAAAJQEAAASAAAAaW5jb25zaXN0ZW50IHN0YXRlIGluIHVucGFya3NyYy9saWJzdGQvc3luYy9jb25kdmFyLnJzAAC4JRAAGgAAAEgCAAASAAAAYXR0ZW1wdGVkIHRvIHVzZSBhIGNvbmRpdGlvbiB2YXJpYWJsZSB3aXRoIHR3byBtdXRleGVzc3JjL2xpYnN0ZC9zeW5jL29uY2UucnMAAAAaJhAAFwAAAKgBAAAVAAAAYXNzZXJ0aW9uIGZhaWxlZDogc3RhdGVfYW5kX3F1ZXVlICYgU1RBVEVfTUFTSyA9PSBSVU5OSU5HAAAAGiYQABcAAACMAQAAFQAAAE9uY2UgaW5zdGFuY2UgaGFzIHByZXZpb3VzbHkgYmVlbiBwb2lzb25lZAAAGiYQABcAAADpAQAACQAAAFBvaXNvbkVycm9yIHsgaW5uZXI6IC4uIH0AAABQAAAAEAAAAAQAAABRAAAAUgAAAFMAAAAMAAAABAAAAFQAAABVAAAACAAAAAQAAABWAAAAVwAAAFUAAAAIAAAABAAAAFgAAABOdWxFcnJvckMAAAAEAAAABAAAAFkAAABzcmMvbGlic3RkL3N5cy93YXNtL2NvbmR2YXIucnMAAEgnEAAeAAAAFwAAAAkAAABjYW4ndCBibG9jayB3aXRoIHdlYiBhc3NlbWJseXNyYy9saWJzdGQvc3lzL3dhc20vbXV0ZXgucnMAAACVJxAAHAAAABYAAAAJAAAAY2Fubm90IHJlY3Vyc2l2ZWx5IGFjcXVpcmUgbXV0ZXhaAAAABAAAAAQAAABbAAAAXAAAAF0AAABaAAAABAAAAAQAAABeAAAAL3J1c3RjL2YzZTFhOTU0ZDJlYWQ0ZTJmYzE5N2M3ZGE3ZDcxZTZjNjFiYWQxOTYvc3JjL2xpYmNvcmUvZm10L21vZC5ycwAADCgQAEYAAABaAQAAEwAAAF8AAAAAAAAAAQAAABMAAABzcmMvbGliYWxsb2MvcmF3X3ZlYy5yc2NhcGFjaXR5IG92ZXJmbG93dCgQABcAAAAJAwAABQAAAGEgZm9ybWF0dGluZyB0cmFpdCBpbXBsZW1lbnRhdGlvbiByZXR1cm5lZCBhbiBlcnJvckZyb21VdGY4RXJyb3JieXRlcwAAAFoAAAAEAAAABAAAAGAAAABlcnJvcgAAAFoAAAAEAAAABAAAAGEAAABgbnVtYmVyIHdvdWxkIGJlIHplcm8gZm9yIG5vbi16ZXJvIHR5cGVudW1iZXIgdG9vIHNtYWxsIHRvIGZpdCBpbiB0YXJnZXQgdHlwZW51bWJlciB0b28gbGFyZ2UgdG8gZml0IGluIHRhcmdldCB0eXBlaW52YWxpZCBkaWdpdCBmb3VuZCBpbiBzdHJpbmdjYW5ub3QgcGFyc2UgaW50ZWdlciBmcm9tIGVtcHR5IHN0cmluZy4u0ikQAAIAAABCb3Jyb3dFcnJvckJvcnJvd011dEVycm9yAAAAZwAAAAAAAAABAAAAaAAAAGluZGV4IG91dCBvZiBib3VuZHM6IHRoZSBsZW4gaXMgIGJ1dCB0aGUgaW5kZXggaXMgAAAIKhAAIAAAACgqEAASAAAAY2FsbGVkIGBPcHRpb246OnVud3JhcCgpYCBvbiBhIGBOb25lYCB2YWx1ZXNyYy9saWJjb3JlL29wdGlvbi5yc3cqEAAVAAAAfQEAABUAAAAcKRAAAAAAAHcqEAAVAAAApAQAAAUAAAA6IAAAHCkQAAAAAAC0KhAA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AGAAAAAAAAAAAKDDB/jnDwAAADwAABwAAAAAAAAA////////f/j//////x8gABAAAPj+/wAAf///+dsHAAAAAAAAAPAAAAAAfwAAAAAA8AcAQcz1wAALEv///////////////////////wBBwPbAAAsO//////////////////8AQfD2wAALAvgDAEGS98AACwf+/////7+2AEGi98AACw3/BwAAAAAA+P//AAABAEG698AACxDAn589AAAAAAIAAAD///8HAEHU98AAC9EKwP8BAAAAAAAA+A8gwDQQAEoAAAAQNxAAAAIAABA5EAA6AAAAAAECAwQFBgcICQgKCwwNDg8QERITFAIVFhcYGRobHB0eHyACAgICAgICAgICIQICAgICAgICAgICAgICIiMkJSYCJwIoAgICKSorAiwtLi8wAgIxAgICMgICAgICAgICMwICNAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNQI2AjcCAgICAgICAjgCOQICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICOjs8AgICAj0CAj4/QEFCQ0RFRgICAkcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICSAICAgICAgICAgICSQICAgICOwIAAQICAgIDAgICAgQCBQYCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICbQAAAAQAAAAEAAAAcgAAAFNvbWVOb25lVXRmOEVycm9ydmFsaWRfdXBfdG9lcnJvcl9sZW4AAABtAAAABAAAAAQAAABzAAAARXJyb3IAQaCGwQALAQE=" +} diff --git a/packages/cosmwasm/src/testdata/cosmoshub.json b/packages/cosmwasm/src/testdata/cosmoshub.json new file mode 100644 index 00000000..cb33539c --- /dev/null +++ b/packages/cosmwasm/src/testdata/cosmoshub.json @@ -0,0 +1,44 @@ +{ + "//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/cosmwasm/src/testdata/txresponse1.json b/packages/cosmwasm/src/testdata/txresponse1.json new file mode 100644 index 00000000..703ea696 --- /dev/null +++ b/packages/cosmwasm/src/testdata/txresponse1.json @@ -0,0 +1,57 @@ +{ + "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/cosmwasm/src/testdata/txresponse2.json b/packages/cosmwasm/src/testdata/txresponse2.json new file mode 100644 index 00000000..0d1a37f9 --- /dev/null +++ b/packages/cosmwasm/src/testdata/txresponse2.json @@ -0,0 +1,57 @@ +{ + "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/cosmwasm/src/testdata/txresponse3.json b/packages/cosmwasm/src/testdata/txresponse3.json new file mode 100644 index 00000000..8ffd0727 --- /dev/null +++ b/packages/cosmwasm/src/testdata/txresponse3.json @@ -0,0 +1,57 @@ +{ + "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/cosmwasm/src/testutils.spec.ts b/packages/cosmwasm/src/testutils.spec.ts new file mode 100644 index 00000000..888f5954 --- /dev/null +++ b/packages/cosmwasm/src/testutils.spec.ts @@ -0,0 +1,77 @@ +import { Random } from "@iov/crypto"; +import { Bech32, Encoding } from "@iov/encoding"; + +import hackatom from "./testdata/contract.json"; + +export function getHackatom(): Uint8Array { + return Encoding.fromBase64(hackatom.data); +} + +export function makeRandomAddress(): string { + return Bech32.encode("cosmos", Random.getBytes(20)); +} + +export const nonNegativeIntegerMatcher = /^[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 semverMatcher = /^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/; + +// 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}$/; + +/** Deployed as part of scripts/wasmd/init.sh */ +export const deployedErc20 = { + codeId: 1, + source: "https://crates.io/api/v1/crates/cw-erc20/0.4.0/download", + builder: "cosmwasm/rust-optimizer:0.8.0", + checksum: "41b3bafd7f9a3870bbfb0a0620508df564c52499cdcdc67bf9df72262f3958a6", + instances: [ + "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5", // HASH + "cosmos1hqrdl6wstt8qzshwc6mrumpjk9338k0lr4dqxd", // ISA + "cosmos18r5szma8hm93pvx6lwpjwyxruw27e0k5uw835c", // JADE + ], +}; + +export const wasmd = { + endpoint: "http://localhost:1317", + chainId: "testing", +}; + +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", + pubkey: { + type: "tendermint/PubKeySecp256k1", + value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ", + }, + address: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", +}; + +/** Unused account */ +export const unused = { + pubkey: { + type: "tendermint/PubKeySecp256k1", + value: "ArkCaFUJ/IH+vKBmNRCdUVl3mCAhbopk9jjW4Ko4OfRQ", + }, + address: "cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u", + accountNumber: 9, + sequence: 0, +}; + +export function wasmdEnabled(): boolean { + return !!process.env.WASMD_ENABLED; +} + +export function pendingWithoutWasmd(): void { + if (!wasmdEnabled()) { + return pending("Set WASMD_ENABLED to enable Wasmd 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/cosmwasm/src/types.ts b/packages/cosmwasm/src/types.ts new file mode 100644 index 00000000..bfc8dbcf --- /dev/null +++ b/packages/cosmwasm/src/types.ts @@ -0,0 +1,173 @@ +import { Coin } from "@cosmwasm/sdk38"; +import { Encoding } from "@iov/encoding"; + +const { fromBase64, fromHex } = Encoding; + +/** An Amino/Cosmos SDK StdTx */ +export interface StdTx { + readonly msg: ReadonlyArray; + readonly fee: StdFee; + readonly signatures: ReadonlyArray; + readonly memo: string | undefined; +} + +export function isStdTx(txValue: unknown): txValue is StdTx { + const { memo, msg, fee, signatures } = txValue as StdTx; + return ( + typeof memo === "string" && Array.isArray(msg) && typeof fee === "object" && Array.isArray(signatures) + ); +} + +export interface CosmosSdkTx { + readonly type: string; + readonly value: StdTx; +} + +interface MsgTemplate { + readonly type: string; + readonly value: any; +} + +/** A Cosmos SDK token transfer message */ +export interface MsgSend extends MsgTemplate { + readonly type: "cosmos-sdk/MsgSend"; + readonly value: { + /** Bech32 account address */ + readonly from_address: string; + /** Bech32 account address */ + readonly to_address: string; + readonly amount: ReadonlyArray; + }; +} + +/** + * Uploads Wam code to the chain + * + * @see https://github.com/cosmwasm/wasmd/blob/9842678d89/x/wasm/internal/types/msg.go#L17 + */ +export interface MsgStoreCode extends MsgTemplate { + readonly type: "wasm/store-code"; + readonly value: { + /** Bech32 account address */ + readonly sender: string; + /** Base64 encoded Wasm */ + readonly wasm_byte_code: string; + /** A valid URI reference to the contract's source code. Can be empty. */ + readonly source: string; + /** A docker tag. Can be empty. */ + readonly builder: string; + }; +} + +/** + * Creates an instance of contract that was uploaded before. + * + * @see https://github.com/cosmwasm/wasmd/blob/9842678d89/x/wasm/internal/types/msg.go#L73 + */ +export interface MsgInstantiateContract extends MsgTemplate { + readonly type: "wasm/instantiate"; + readonly value: { + /** Bech32 account address */ + readonly sender: string; + /** ID of the Wasm code that was uploaded before */ + readonly code_id: string; + /** Human-readable label for this contract */ + readonly label: string; + /** Init message as JavaScript object */ + readonly init_msg: any; + readonly init_funds: ReadonlyArray; + }; +} + +/** + * Creates an instance of contract that was uploaded before. + * + * @see https://github.com/cosmwasm/wasmd/blob/9842678d89/x/wasm/internal/types/msg.go#L103 + */ +export interface MsgExecuteContract extends MsgTemplate { + readonly type: "wasm/execute"; + readonly value: { + /** Bech32 account address */ + readonly sender: string; + /** Bech32 account address */ + readonly contract: string; + /** Handle message as JavaScript object */ + readonly msg: any; + readonly sent_funds: ReadonlyArray; + }; +} + +export type Msg = MsgSend | MsgStoreCode | MsgInstantiateContract | MsgExecuteContract | MsgTemplate; + +export function isMsgSend(msg: Msg): msg is MsgSend { + return (msg as MsgSend).type === "cosmos-sdk/MsgSend"; +} + +export function isMsgStoreCode(msg: Msg): msg is MsgStoreCode { + return (msg as MsgStoreCode).type === "wasm/store-code"; +} + +export function isMsgInstantiateContract(msg: Msg): msg is MsgInstantiateContract { + return (msg as MsgInstantiateContract).type === "wasm/instantiate"; +} + +export function isMsgExecuteContract(msg: Msg): msg is MsgExecuteContract { + return (msg as MsgExecuteContract).type === "wasm/execute"; +} + +export interface StdFee { + readonly amount: ReadonlyArray; + readonly gas: string; +} + +export interface StdSignature { + readonly pub_key: PubKey; + readonly signature: string; +} + +export interface PubKey { + // type is one of the strings defined in pubkeyTypes + // I don't use a string literal union here as that makes trouble with json test data: + // https://github.com/confio/cosmwasm-js/pull/44#pullrequestreview-353280504 + readonly type: string; + // Value field is base64-encoded in all cases + // Note: if type is Secp256k1, this must contain a COMPRESSED pubkey - to encode from bcp/keycontrol land, you must compress it first + readonly value: string; +} + +export const pubkeyType = { + /** @see https://github.com/tendermint/tendermint/blob/v0.33.0/crypto/ed25519/ed25519.go#L22 */ + secp256k1: "tendermint/PubKeySecp256k1" as const, + /** @see https://github.com/tendermint/tendermint/blob/v0.33.0/crypto/secp256k1/secp256k1.go#L23 */ + ed25519: "tendermint/PubKeyEd25519" as const, + /** @see https://github.com/tendermint/tendermint/blob/v0.33.0/crypto/sr25519/codec.go#L12 */ + sr25519: "tendermint/PubKeySr25519" as const, +}; + +export const pubkeyTypes: readonly string[] = [pubkeyType.secp256k1, pubkeyType.ed25519, pubkeyType.sr25519]; + +export interface WasmData { + // key is hex-encoded + readonly key: string; + // value is base64 encoded + readonly val: string; +} + +// Model is a parsed WasmData object +export interface Model { + readonly key: Uint8Array; + readonly val: Uint8Array; +} + +export function parseWasmData({ key, val }: WasmData): Model { + return { + key: fromHex(key), + val: fromBase64(val), + }; +} + +/** + * An object containing a parsed JSON document. The result of JSON.parse(). + * This doen't privide any type safety over `any` but expresses intent in the code. + */ +export type JsonObject = any; diff --git a/packages/cosmwasm/tsconfig.json b/packages/cosmwasm/tsconfig.json new file mode 100644 index 00000000..167e8c02 --- /dev/null +++ b/packages/cosmwasm/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "baseUrl": ".", + "outDir": "build", + "declarationDir": "build/types", + "rootDir": "src" + }, + "include": [ + "src/**/*" + ] +} diff --git a/packages/cosmwasm/typedoc.js b/packages/cosmwasm/typedoc.js new file mode 100644 index 00000000..e2387c7d --- /dev/null +++ b/packages/cosmwasm/typedoc.js @@ -0,0 +1,14 @@ +const packageJson = require("./package.json"); + +module.exports = { + src: ["./src"], + out: "docs", + exclude: "**/*.spec.ts", + target: "es6", + name: `${packageJson.name} Documentation`, + readme: "README.md", + mode: "file", + excludeExternals: true, + excludeNotExported: true, + excludePrivate: true, +}; diff --git a/packages/cosmwasm/types/builder.d.ts b/packages/cosmwasm/types/builder.d.ts new file mode 100644 index 00000000..68e18c0a --- /dev/null +++ b/packages/cosmwasm/types/builder.d.ts @@ -0,0 +1 @@ +export declare function isValidBuilder(builder: string): boolean; diff --git a/packages/cosmwasm/types/cosmwasmclient.d.ts b/packages/cosmwasm/types/cosmwasmclient.d.ts new file mode 100644 index 00000000..3b57ffde --- /dev/null +++ b/packages/cosmwasm/types/cosmwasmclient.d.ts @@ -0,0 +1,175 @@ +import { Coin } from "@cosmwasm/sdk38"; +import { Log } from "./logs"; +import { BroadcastMode, RestClient } from "./restclient"; +import { CosmosSdkTx, JsonObject, PubKey, StdTx } from "./types"; +export interface GetNonceResult { + readonly accountNumber: number; + readonly sequence: number; +} +export interface Account { + /** Bech32 account address */ + readonly address: string; + readonly balance: ReadonlyArray; + readonly pubkey: PubKey | undefined; + readonly accountNumber: number; + readonly sequence: number; +} +export interface PostTxResult { + 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; +} +export interface SearchByIdQuery { + readonly id: string; +} +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: readonly { + readonly key: string; + readonly value: string; + }[]; +} +export declare type SearchTxQuery = + | SearchByIdQuery + | SearchByHeightQuery + | SearchBySentFromOrToQuery + | SearchByTagsQuery; +export interface SearchTxFilter { + readonly minHeight?: number; + readonly maxHeight?: number; +} +export interface Code { + readonly id: number; + /** Bech32 account address */ + readonly creator: string; + /** Hex-encoded sha256 hash of the code stored here */ + readonly checksum: string; + readonly source?: string; + readonly builder?: string; +} +export interface CodeDetails extends Code { + /** The original wasm bytes */ + readonly data: Uint8Array; +} +export interface Contract { + readonly address: string; + readonly codeId: number; + /** Bech32 account address */ + readonly creator: string; + readonly label: string; +} +export interface ContractDetails extends Contract { + /** Argument passed on initialization of the contract */ + readonly initMsg: object; +} +/** 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: CosmosSdkTx; + /** 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: ReadonlyArray; +} +/** Use for testing only */ +export interface PrivateCosmWasmClient { + readonly restClient: RestClient; +} +export declare class CosmWasmClient { + protected readonly restClient: RestClient; + /** Any address the chain considers valid (valid bech32 with proper prefix) */ + protected anyValidAddress: string | undefined; + private readonly codesCache; + private chainId; + /** + * 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 postTx method (i.e. transaction broadcasting) returns + */ + constructor(apiUrl: string, broadcastMode?: BroadcastMode); + getChainId(): Promise; + getHeight(): Promise; + /** + * Returns a 32 byte upper-case hex transaction hash (typically used as the transaction ID) + */ + getIdentifier(tx: CosmosSdkTx): Promise; + /** + * 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. + */ + getNonce(address: string): Promise; + getAccount(address: string): Promise; + /** + * Gets block header and meta + * + * @param height The height of the block. If undefined, the latest height is used. + */ + getBlock(height?: number): Promise; + searchTx(query: SearchTxQuery, filter?: SearchTxFilter): Promise; + postTx(tx: StdTx): Promise; + getCodes(): Promise; + getCodeDetails(codeId: number): Promise; + getContracts(codeId: number): Promise; + /** + * Throws an error if no contract was found at the address + */ + getContract(address: string): Promise; + /** + * Returns the data at the key if present (raw contract dependent storage data) + * or null if no data at this key. + * + * Promise is rejected when contract does not exist. + */ + queryContractRaw(address: string, key: Uint8Array): Promise; + /** + * Makes a smart query on the contract, returns the parsed JSON document. + * + * Promise is rejected when contract does not exist. + * Promise is rejected for invalid query format. + * Promise is rejected for invalid response format. + */ + queryContractSmart(address: string, queryMsg: object): Promise; + private txsQuery; +} diff --git a/packages/cosmwasm/types/index.d.ts b/packages/cosmwasm/types/index.d.ts new file mode 100644 index 00000000..1241731b --- /dev/null +++ b/packages/cosmwasm/types/index.d.ts @@ -0,0 +1,33 @@ +import * as logs from "./logs"; +import * as types from "./types"; +export { logs, types }; +export { BroadcastMode, RestClient, TxsResponse } from "./restclient"; +export { + Account, + Block, + BlockHeader, + Code, + CodeDetails, + Contract, + ContractDetails, + CosmWasmClient, + GetNonceResult, + IndexedTx, + PostTxResult, + SearchByHeightQuery, + SearchByIdQuery, + SearchBySentFromOrToQuery, + SearchByTagsQuery, + SearchTxQuery, + SearchTxFilter, +} from "./cosmwasmclient"; +export { decodeBech32Pubkey, encodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey"; +export { + ExecuteResult, + FeeTable, + InstantiateResult, + SigningCallback, + SigningCosmWasmClient, + UploadMeta, + UploadResult, +} from "./signingcosmwasmclient"; diff --git a/packages/cosmwasm/types/logs.d.ts b/packages/cosmwasm/types/logs.d.ts new file mode 100644 index 00000000..2e1decb3 --- /dev/null +++ b/packages/cosmwasm/types/logs.d.ts @@ -0,0 +1,28 @@ +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 declare function parseAttribute(input: unknown): Attribute; +export declare function parseEvent(input: unknown): Event; +export declare function parseLog(input: unknown): Log; +export declare function parseLogs(input: unknown): readonly Log[]; +/** + * 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 declare function findAttribute( + logs: readonly Log[], + eventType: "message" | "transfer", + attrKey: string, +): Attribute; diff --git a/packages/cosmwasm/types/pubkey.d.ts b/packages/cosmwasm/types/pubkey.d.ts new file mode 100644 index 00000000..b6ebdebc --- /dev/null +++ b/packages/cosmwasm/types/pubkey.d.ts @@ -0,0 +1,4 @@ +import { PubKey } from "./types"; +export declare function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey; +export declare function decodeBech32Pubkey(bechEncoded: string): PubKey; +export declare function encodeBech32Pubkey(pubkey: PubKey, prefix: string): string; diff --git a/packages/cosmwasm/types/restclient.d.ts b/packages/cosmwasm/types/restclient.d.ts new file mode 100644 index 00000000..2c914be4 --- /dev/null +++ b/packages/cosmwasm/types/restclient.d.ts @@ -0,0 +1,231 @@ +import { Coin } from "@cosmwasm/sdk38"; +import { CosmosSdkTx, JsonObject, Model, StdTx } from "./types"; +export interface CosmosSdkAccount { + /** Bech32 account address */ + readonly address: string; + readonly coins: ReadonlyArray; + /** Bech32 encoded pubkey */ + readonly public_key: string; + readonly account_number: number; + readonly sequence: number; +} +export 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; + }; +} +export 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; +} +export interface BlockId { + readonly hash: string; +} +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; +} +export interface Block { + readonly header: BlockHeader; + readonly data: { + /** Array of base64 encoded transactions */ + readonly txs: ReadonlyArray | null; + }; +} +export interface BlockResponse { + readonly block_id: BlockId; + readonly block: Block; +} +interface AuthAccountsResponse { + readonly height: string; + readonly result: { + readonly type: "cosmos-sdk/Account"; + readonly value: CosmosSdkAccount; + }; +} +declare type WasmResponse = WasmSuccess | WasmError; +interface WasmSuccess { + readonly height: string; + readonly result: T; +} +interface WasmError { + readonly error: string; +} +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?: object; + readonly tx: CosmosSdkTx; + /** 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; +} +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 PostTxsResponse { + readonly height: string; + readonly txhash: string; + readonly code?: number; + readonly raw_log?: string; + /** The same as `raw_log` but deserialized? */ + readonly logs?: object; + /** The gas limit as set by the user */ + readonly gas_wanted?: string; + /** The gas used by the execution */ + readonly gas_used?: string; +} +interface EncodeTxResponse { + readonly tx: string; +} +export interface CodeInfo { + readonly id: number; + /** Bech32 account address */ + readonly creator: string; + /** Hex-encoded sha256 hash of the code stored here */ + readonly data_hash: string; + readonly source?: string; + readonly builder?: string; +} +export interface CodeDetails extends CodeInfo { + /** Base64 encoded raw wasm data */ + readonly data: string; +} +export interface ContractInfo { + readonly address: string; + readonly code_id: number; + /** Bech32 account address */ + readonly creator: string; + readonly label: string; +} +export interface ContractDetails extends ContractInfo { + /** Argument passed on initialization of the contract */ + readonly init_msg: object; +} +declare type RestClientResponse = + | NodeInfoResponse + | BlockResponse + | AuthAccountsResponse + | TxsResponse + | SearchTxsResponse + | PostTxsResponse + | EncodeTxResponse + | WasmResponse + | WasmResponse + | WasmResponse + | WasmResponse + | WasmResponse; +/** + * The mode used to send transaction + * + * @see https://cosmos.network/rpc/#/Transactions/post_txs + */ +export declare enum BroadcastMode { + /** Return after tx commit */ + Block = "block", + /** Return afer CheckTx */ + Sync = "sync", + /** Return right away */ + Async = "async", +} +export declare class RestClient { + private readonly client; + private readonly 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 postTx method (i.e. transaction broadcasting) returns + */ + constructor(apiUrl: string, broadcastMode?: BroadcastMode); + get(path: string): Promise; + post(path: string, params: any): Promise; + authAccounts(address: string): Promise; + blocksLatest(): Promise; + blocks(height: number): Promise; + nodeInfo(): Promise; + txById(id: string): Promise; + txsQuery(query: string): Promise; + /** returns the amino-encoding of the transaction performed by the server */ + encodeTx(tx: CosmosSdkTx): Promise; + /** + * Broadcasts a signed transaction to into the transaction pool. + * Depending on the RestClient'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) + */ + postTx(tx: StdTx): Promise; + listCodeInfo(): Promise; + getCode(id: number): Promise; + listContractsByCodeId(id: number): Promise; + /** + * Returns null when contract was not found at this address. + */ + getContractInfo(address: string): Promise; + getAllContractState(address: string): Promise; + queryContractRaw(address: string, key: Uint8Array): Promise; + /** + * Makes a smart query on the contract and parses the reponse as JSON. + * Throws error if no such contract exists, the query format is invalid or the response is invalid. + */ + queryContractSmart(address: string, query: object): Promise; +} +export {}; diff --git a/packages/cosmwasm/types/signingcosmwasmclient.d.ts b/packages/cosmwasm/types/signingcosmwasmclient.d.ts new file mode 100644 index 00000000..d3f9e00e --- /dev/null +++ b/packages/cosmwasm/types/signingcosmwasmclient.d.ts @@ -0,0 +1,89 @@ +import { Coin } from "@cosmwasm/sdk38"; +import { Account, CosmWasmClient, GetNonceResult, PostTxResult } from "./cosmwasmclient"; +import { Log } from "./logs"; +import { BroadcastMode } from "./restclient"; +import { StdFee, StdSignature } from "./types"; +export interface SigningCallback { + (signBytes: Uint8Array): Promise; +} +export interface FeeTable { + readonly upload: StdFee; + readonly init: StdFee; + readonly exec: StdFee; + readonly send: StdFee; +} +export interface UploadMeta { + /** The source URL */ + readonly source?: string; + /** The builder tag */ + readonly builder?: string; +} +export interface UploadResult { + /** Size of the original wasm code in bytes */ + readonly originalSize: number; + /** A hex encoded sha256 checksum of the original wasm code (that is stored on chain) */ + readonly originalChecksum: string; + /** Size of the compressed wasm code in bytes */ + readonly compressedSize: number; + /** A hex encoded sha256 checksum of the compressed wasm code (that stored in the transaction) */ + readonly compressedChecksum: string; + /** The ID of the code asigned by the chain */ + readonly codeId: number; + readonly logs: readonly Log[]; + /** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */ + readonly transactionHash: string; +} +export interface InstantiateResult { + /** The address of the newly instantiated contract */ + readonly contractAddress: string; + readonly logs: readonly Log[]; + /** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */ + readonly transactionHash: string; +} +export interface ExecuteResult { + readonly logs: readonly Log[]; + /** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */ + readonly transactionHash: string; +} +export declare class SigningCosmWasmClient extends CosmWasmClient { + readonly senderAddress: string; + private readonly signCallback; + private readonly fees; + /** + * Creates a new client with signing capability to interact with a CosmWasm blockchain. This is the bigger brother of CosmWasmClient. + * + * 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 senderAddress The address that will sign and send transactions using this instance + * @param signCallback An asynchonous callback to create a signature for a given transaction. This can be implemented using secure key stores that require user interaction. + * @param customFees The fees that are paid for transactions + * @param broadcastMode Defines at which point of the transaction processing the postTx method (i.e. transaction broadcasting) returns + */ + constructor( + apiUrl: string, + senderAddress: string, + signCallback: SigningCallback, + customFees?: Partial, + broadcastMode?: BroadcastMode, + ); + getNonce(address?: string): Promise; + getAccount(address?: string): Promise; + /** Uploads code and returns a receipt, including the code ID */ + upload(wasmCode: Uint8Array, meta?: UploadMeta, memo?: string): Promise; + instantiate( + codeId: number, + initMsg: object, + label: string, + memo?: string, + transferAmount?: readonly Coin[], + ): Promise; + execute( + contractAddress: string, + handleMsg: object, + memo?: string, + transferAmount?: readonly Coin[], + ): Promise; + sendTokens(recipientAddress: string, transferAmount: readonly Coin[], memo?: string): Promise; +} diff --git a/packages/cosmwasm/types/types.d.ts b/packages/cosmwasm/types/types.d.ts new file mode 100644 index 00000000..e7592e66 --- /dev/null +++ b/packages/cosmwasm/types/types.d.ts @@ -0,0 +1,123 @@ +import { Coin } from "@cosmwasm/sdk38"; +/** An Amino/Cosmos SDK StdTx */ +export interface StdTx { + readonly msg: ReadonlyArray; + readonly fee: StdFee; + readonly signatures: ReadonlyArray; + readonly memo: string | undefined; +} +export declare function isStdTx(txValue: unknown): txValue is StdTx; +export interface CosmosSdkTx { + readonly type: string; + readonly value: StdTx; +} +interface MsgTemplate { + readonly type: string; + readonly value: any; +} +/** A Cosmos SDK token transfer message */ +export interface MsgSend extends MsgTemplate { + readonly type: "cosmos-sdk/MsgSend"; + readonly value: { + /** Bech32 account address */ + readonly from_address: string; + /** Bech32 account address */ + readonly to_address: string; + readonly amount: ReadonlyArray; + }; +} +/** + * Uploads Wam code to the chain + * + * @see https://github.com/cosmwasm/wasmd/blob/9842678d89/x/wasm/internal/types/msg.go#L17 + */ +export interface MsgStoreCode extends MsgTemplate { + readonly type: "wasm/store-code"; + readonly value: { + /** Bech32 account address */ + readonly sender: string; + /** Base64 encoded Wasm */ + readonly wasm_byte_code: string; + /** A valid URI reference to the contract's source code. Can be empty. */ + readonly source: string; + /** A docker tag. Can be empty. */ + readonly builder: string; + }; +} +/** + * Creates an instance of contract that was uploaded before. + * + * @see https://github.com/cosmwasm/wasmd/blob/9842678d89/x/wasm/internal/types/msg.go#L73 + */ +export interface MsgInstantiateContract extends MsgTemplate { + readonly type: "wasm/instantiate"; + readonly value: { + /** Bech32 account address */ + readonly sender: string; + /** ID of the Wasm code that was uploaded before */ + readonly code_id: string; + /** Human-readable label for this contract */ + readonly label: string; + /** Init message as JavaScript object */ + readonly init_msg: any; + readonly init_funds: ReadonlyArray; + }; +} +/** + * Creates an instance of contract that was uploaded before. + * + * @see https://github.com/cosmwasm/wasmd/blob/9842678d89/x/wasm/internal/types/msg.go#L103 + */ +export interface MsgExecuteContract extends MsgTemplate { + readonly type: "wasm/execute"; + readonly value: { + /** Bech32 account address */ + readonly sender: string; + /** Bech32 account address */ + readonly contract: string; + /** Handle message as JavaScript object */ + readonly msg: any; + readonly sent_funds: ReadonlyArray; + }; +} +export declare type Msg = MsgSend | MsgStoreCode | MsgInstantiateContract | MsgExecuteContract | MsgTemplate; +export declare function isMsgSend(msg: Msg): msg is MsgSend; +export declare function isMsgStoreCode(msg: Msg): msg is MsgStoreCode; +export declare function isMsgInstantiateContract(msg: Msg): msg is MsgInstantiateContract; +export declare function isMsgExecuteContract(msg: Msg): msg is MsgExecuteContract; +export interface StdFee { + readonly amount: ReadonlyArray; + readonly gas: string; +} +export interface StdSignature { + readonly pub_key: PubKey; + readonly signature: string; +} +export interface PubKey { + readonly type: string; + readonly value: string; +} +export declare const pubkeyType: { + /** @see https://github.com/tendermint/tendermint/blob/v0.33.0/crypto/ed25519/ed25519.go#L22 */ + secp256k1: "tendermint/PubKeySecp256k1"; + /** @see https://github.com/tendermint/tendermint/blob/v0.33.0/crypto/secp256k1/secp256k1.go#L23 */ + ed25519: "tendermint/PubKeyEd25519"; + /** @see https://github.com/tendermint/tendermint/blob/v0.33.0/crypto/sr25519/codec.go#L12 */ + sr25519: "tendermint/PubKeySr25519"; +}; +export declare const pubkeyTypes: readonly string[]; +export interface WasmData { + readonly key: string; + readonly val: string; +} +export interface Model { + readonly key: Uint8Array; + readonly val: Uint8Array; +} +export declare function parseWasmData({ key, val }: WasmData): Model; +/** + * An object containing a parsed JSON document. The result of JSON.parse(). + * This doen't privide any type safety over `any` but expresses intent in the code. + */ +export declare type JsonObject = any; +export {}; diff --git a/packages/cosmwasm/webpack.web.config.js b/packages/cosmwasm/webpack.web.config.js new file mode 100644 index 00000000..7373cace --- /dev/null +++ b/packages/cosmwasm/webpack.web.config.js @@ -0,0 +1,19 @@ +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(["WASMD_ENABLED"])], + }, +];