From 47f13b231aebfc4b2323188fe7f3e9c354fa2d38 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Thu, 23 Jun 2022 16:42:51 +0200 Subject: [PATCH 1/2] Add SigningCosmWasmClient.executeMultiple --- CHANGELOG.md | 3 ++ packages/cosmwasm-stargate/src/index.ts | 1 + .../src/signingcosmwasmclient.ts | 35 +++++++++++++++---- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4f9bde7..ba5791f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,10 @@ and this project adheres to `makeMultisignedTx` but returns bytes ready to broadcast ([#1176]). - @cosmjs/tendermint-rpc: Add fields `codespace` and `info` to `AbciQueryResponse`. +- @cosmjs/cosmwasm-stargate: Add `SigningCosmWasmClient.executeMultiple` + ([#1072]). +[#1072]: https://github.com/cosmos/cosmjs/issues/1072 [#1176]: https://github.com/cosmos/cosmjs/pull/1176 ### Fixed diff --git a/packages/cosmwasm-stargate/src/index.ts b/packages/cosmwasm-stargate/src/index.ts index 49908b5d..4b00e898 100644 --- a/packages/cosmwasm-stargate/src/index.ts +++ b/packages/cosmwasm-stargate/src/index.ts @@ -21,6 +21,7 @@ export { } from "./modules"; export { ChangeAdminResult, + ExecuteInstruction, ExecuteResult, InstantiateOptions, InstantiateResult, diff --git a/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts b/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts index 69e2d71d..2065437c 100644 --- a/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts +++ b/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts @@ -135,6 +135,12 @@ export interface MigrateResult { readonly gasUsed: number; } +export interface ExecuteInstruction { + contractAddress: string; + msg: Record; + funds?: readonly Coin[]; +} + export interface ExecuteResult { readonly logs: readonly logs.Log[]; /** Block height in which the transaction is included */ @@ -396,16 +402,33 @@ export class SigningCosmWasmClient extends CosmWasmClient { memo = "", funds?: readonly Coin[], ): Promise { - const executeContractMsg: MsgExecuteContractEncodeObject = { + const instruction: ExecuteInstruction = { + contractAddress: contractAddress, + msg: msg, + funds: funds, + }; + return this.executeMultiple(senderAddress, [instruction], fee, memo); + } + + /** + * Like `execute` but allows executing multiple messages in one transaction. + */ + public async executeMultiple( + senderAddress: string, + instructions: readonly ExecuteInstruction[], + fee: StdFee | "auto" | number, + memo = "", + ): Promise { + const msgs: MsgExecuteContractEncodeObject[] = instructions.map((i) => ({ typeUrl: "/cosmwasm.wasm.v1.MsgExecuteContract", value: MsgExecuteContract.fromPartial({ sender: senderAddress, - contract: contractAddress, - msg: toUtf8(JSON.stringify(msg)), - funds: [...(funds || [])], + contract: i.contractAddress, + msg: toUtf8(JSON.stringify(i.msg)), + funds: [...(i.funds || [])], }), - }; - const result = await this.signAndBroadcast(senderAddress, [executeContractMsg], fee, memo); + })); + const result = await this.signAndBroadcast(senderAddress, msgs, fee, memo); if (isDeliverTxFailure(result)) { throw new Error(createDeliverTxResponseErrorMessage(result)); } From c8bc6c6e3711719d45e083d53fa00b728502b080 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 27 Jun 2022 15:01:14 +0200 Subject: [PATCH 2/2] Test executeMultiple --- .../src/signingcosmwasmclient.spec.ts | 62 +++++++++++++++++++ .../cosmwasm-stargate/src/testutils.spec.ts | 1 + 2 files changed, 63 insertions(+) diff --git a/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts b/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts index 3093b718..8f9884d0 100644 --- a/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts +++ b/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts @@ -530,6 +530,68 @@ describe("SigningCosmWasmClient", () => { }); }); + describe("executeMultiple", () => { + it("works", async () => { + pendingWithoutWasmd(); + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: wasmd.prefix }); + const options = { ...defaultSigningClientOptions, prefix: wasmd.prefix }; + const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options); + const { codeId } = await client.upload(alice.address0, getHackatom().data, defaultUploadFee); + // instantiate + const funds = [coin(233444, "ucosm"), coin(5454, "ustake")]; + const beneficiaryAddress1 = makeRandomAddress(); + const beneficiaryAddress2 = makeRandomAddress(); + const { contractAddress: contractAddress1 } = await client.instantiate( + alice.address0, + codeId, + { + verifier: alice.address0, + beneficiary: beneficiaryAddress1, + }, + "amazing random contract", + defaultInstantiateFee, + { funds: funds }, + ); + const { contractAddress: contractAddress2 } = await client.instantiate( + alice.address0, + codeId, + { + verifier: alice.address0, + beneficiary: beneficiaryAddress2, + }, + "amazing random contract", + defaultInstantiateFee, + { funds: funds }, + ); + // execute + const result = await client.executeMultiple( + alice.address0, + [ + { contractAddress: contractAddress1, msg: { release: {} } }, + { contractAddress: contractAddress2, msg: { release: {} } }, + ], + "auto", + ); + expect(result.logs.length).toEqual(2); + const wasmEvent1 = result.logs[0].events.find((e) => e.type === "wasm"); + assert(wasmEvent1, "Event of type wasm expected"); + expect(wasmEvent1.attributes).toContain({ key: "action", value: "release" }); + expect(wasmEvent1.attributes).toContain({ + key: "destination", + value: beneficiaryAddress1, + }); + const wasmEvent2 = result.logs[1].events.find((e) => e.type === "wasm"); + assert(wasmEvent2, "Event of type wasm expected"); + expect(wasmEvent2.attributes).toContain({ key: "action", value: "release" }); + expect(wasmEvent2.attributes).toContain({ + key: "destination", + value: beneficiaryAddress2, + }); + + client.disconnect(); + }); + }); + describe("sendTokens", () => { it("works with direct signer", async () => { pendingWithoutWasmd(); diff --git a/packages/cosmwasm-stargate/src/testutils.spec.ts b/packages/cosmwasm-stargate/src/testutils.spec.ts index ca5f4790..c4166443 100644 --- a/packages/cosmwasm-stargate/src/testutils.spec.ts +++ b/packages/cosmwasm-stargate/src/testutils.spec.ts @@ -55,6 +55,7 @@ export const wasmd = { export const defaultSigningClientOptions: SigningCosmWasmClientOptions = { broadcastPollIntervalMs: 300, broadcastTimeoutMs: 8_000, + gasPrice: defaultGasPrice, }; export function getHackatom(): ContractUploadInstructions {