From 3ce9005a2ba31f35e1bb51aee2e5f886d0d1e930 Mon Sep 17 00:00:00 2001 From: "jinseong.cho" Date: Tue, 4 Apr 2023 13:49:03 +0900 Subject: [PATCH 1/4] feat: add instantiate2 broadcast --- .../src/modules/wasm/messages.ts | 15 ++++ .../src/signingcosmwasmclient.spec.ts | 45 ++++++++++++ .../src/signingcosmwasmclient.ts | 72 +++++++++++++++++++ 3 files changed, 132 insertions(+) diff --git a/packages/cosmwasm-stargate/src/modules/wasm/messages.ts b/packages/cosmwasm-stargate/src/modules/wasm/messages.ts index e9a1ea0278..bf3fc00cda 100644 --- a/packages/cosmwasm-stargate/src/modules/wasm/messages.ts +++ b/packages/cosmwasm-stargate/src/modules/wasm/messages.ts @@ -3,6 +3,7 @@ import { MsgClearAdmin, MsgExecuteContract, MsgInstantiateContract, + MsgInstantiateContract2, MsgMigrateContract, MsgStoreCode, MsgUpdateAdmin, @@ -14,6 +15,7 @@ export const wasmTypes: ReadonlyArray<[string, GeneratedType]> = [ ["/cosmwasm.wasm.v1.MsgMigrateContract", MsgMigrateContract], ["/cosmwasm.wasm.v1.MsgStoreCode", MsgStoreCode], ["/cosmwasm.wasm.v1.MsgInstantiateContract", MsgInstantiateContract], + ["/cosmwasm.wasm.v1.MsgInstantiateContract2", MsgInstantiateContract2], ["/cosmwasm.wasm.v1.MsgUpdateAdmin", MsgUpdateAdmin], ]; @@ -39,6 +41,19 @@ export function isMsgInstantiateContractEncodeObject( ); } +export interface MsgInstantiateContract2EncodeObject extends EncodeObject { + readonly typeUrl: "/cosmwasm.wasm.v1.MsgInstantiateContract2"; + readonly value: Partial; +} + +export function isMsgInstantiateContract2EncodeObject( + object: EncodeObject, +): object is MsgInstantiateContract2EncodeObject { + return ( + (object as MsgInstantiateContract2EncodeObject).typeUrl === "/cosmwasm.wasm.v1.MsgInstantiateContract2" + ); +} + export interface MsgUpdateAdminEncodeObject extends EncodeObject { readonly typeUrl: "/cosmwasm.wasm.v1.MsgUpdateAdmin"; readonly value: Partial; diff --git a/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts b/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts index fac9198078..3b7bb6aa3e 100644 --- a/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts +++ b/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts @@ -23,6 +23,7 @@ import { MsgExecuteContract, MsgStoreCode } from "cosmjs-types/cosmwasm/wasm/v1/ import Long from "long"; import pako from "pako"; import protobuf from "protobufjs/minimal"; +import { instantiate2Address } from "./instantiate2"; import { MsgExecuteContractEncodeObject, MsgStoreCodeEncodeObject } from "./modules"; import { SigningCosmWasmClient } from "./signingcosmwasmclient"; @@ -250,6 +251,50 @@ describe("SigningCosmWasmClient", () => { }); }); + describe("instantiate2", () => { + it("can instantiate with predictable address", 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); + const funds = [coin(1234, "ucosm"), coin(321, "ustake")]; + const beneficiaryAddress = makeRandomAddress(); + const salt = Uint8Array.from([0x01]); + const wasm = getHackatom().data; + const msg = { + verifier: alice.address0, + beneficiary: beneficiaryAddress, + }; + const expectedAddress = instantiate2Address(sha256(wasm), alice.address0, salt, wasmd.prefix); + + const { contractAddress } = await client.instantiate2( + alice.address0, + codeId, + msg, + "My cool label--", + defaultInstantiateFee, + { + memo: "Let's see if the memo is used", + funds: funds, + salt: salt, + }, + ); + + const wasmClient = await makeWasmClient(wasmd.endpoint); + const ucosmBalance = await wasmClient.bank.balance(contractAddress, "ucosm"); + const ustakeBalance = await wasmClient.bank.balance(contractAddress, "ustake"); + expect(ucosmBalance).toEqual(funds[0]); + expect(ustakeBalance).toEqual(funds[1]); + + expect(contractAddress).toEqual(expectedAddress); + client.disconnect(); + }); + }); + describe("updateAdmin", () => { it("can update an admin", async () => { pendingWithoutWasmd(); diff --git a/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts b/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts index 03f6fe2fdc..f521855420 100644 --- a/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts +++ b/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts @@ -41,6 +41,7 @@ import { MsgClearAdmin, MsgExecuteContract, MsgInstantiateContract, + MsgInstantiateContract2, MsgMigrateContract, MsgStoreCode, MsgUpdateAdmin, @@ -60,6 +61,7 @@ import { MsgUpdateAdminEncodeObject, wasmTypes, } from "./modules"; +import { MsgInstantiateContract2EncodeObject } from "./modules/wasm/messages"; export interface UploadResult { /** Size of the original wasm code in bytes */ @@ -103,6 +105,38 @@ export interface InstantiateOptions { readonly admin?: string; } +/** + * The options of an .instantiate() call. + * All properties are optional. + */ +export interface Instantiate2Options { + readonly memo?: string; + /** + * The funds that are transferred from the sender to the newly created contract. + * The funds are transferred as part of the message execution after the contract address is + * created and before the instantiation message is executed by the contract. + * + * Only native tokens are supported. + */ + readonly funds?: readonly Coin[]; + /** + * A bech32 encoded address of an admin account. + * Caution: an admin has the privilege to upgrade a contract. If this is not desired, do not set this value. + */ + readonly admin?: string; + + /** + * salt is an arbitrary value provided by the sender. Size can be 1 to 64. + */ + readonly salt?: Uint8Array; + + /** + * FixMsg include the msg value into the hash for the predictable address. + * Default is false + */ + readonly fixMsg?: boolean; +} + export interface InstantiateResult { /** The address of the newly instantiated contract */ readonly contractAddress: string; @@ -335,6 +369,44 @@ export class SigningCosmWasmClient extends CosmWasmClient { }; } + public async instantiate2( + senderAddress: string, + codeId: number, + msg: Record, + label: string, + fee: StdFee | "auto" | number, + options: Instantiate2Options = {}, + ): Promise { + const instantiateContract2Msg: MsgInstantiateContract2EncodeObject = { + typeUrl: "/cosmwasm.wasm.v1.MsgInstantiateContract2", + value: MsgInstantiateContract2.fromPartial({ + sender: senderAddress, + codeId: Long.fromString(new Uint53(codeId).toString()), + label: label, + msg: toUtf8(JSON.stringify(msg)), + funds: [...(options.funds || [])], + admin: options.admin, + salt: options.salt, + fixMsg: options.fixMsg, + }), + }; + const result = await this.signAndBroadcast(senderAddress, [instantiateContract2Msg], fee, options.memo); + if (isDeliverTxFailure(result)) { + throw new Error(createDeliverTxResponseErrorMessage(result)); + } + const parsedLogs = logs.parseRawLog(result.rawLog); + const contractAddressAttr = logs.findAttribute(parsedLogs, "instantiate", "_contract_address"); + return { + contractAddress: contractAddressAttr.value, + logs: parsedLogs, + height: result.height, + transactionHash: result.transactionHash, + events: result.events, + gasWanted: result.gasWanted, + gasUsed: result.gasUsed, + }; + } + public async updateAdmin( senderAddress: string, contractAddress: string, From e5eb7c14fca2afc93d615fb2c12a8e55dbf7abda Mon Sep 17 00:00:00 2001 From: "jinseong.cho" Date: Tue, 4 Apr 2023 14:52:50 +0900 Subject: [PATCH 2/4] lint: run lint fix --- packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts b/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts index 3b7bb6aa3e..f1c0d4e065 100644 --- a/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts +++ b/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts @@ -23,8 +23,8 @@ import { MsgExecuteContract, MsgStoreCode } from "cosmjs-types/cosmwasm/wasm/v1/ import Long from "long"; import pako from "pako"; import protobuf from "protobufjs/minimal"; -import { instantiate2Address } from "./instantiate2"; +import { instantiate2Address } from "./instantiate2"; import { MsgExecuteContractEncodeObject, MsgStoreCodeEncodeObject } from "./modules"; import { SigningCosmWasmClient } from "./signingcosmwasmclient"; import { From 3152646b6c4b41172467d93662ac368bb69e2d7d Mon Sep 17 00:00:00 2001 From: "jinseong.cho" Date: Wed, 5 Apr 2023 20:25:35 +0900 Subject: [PATCH 3/4] chore: apply feedback --- packages/cosmwasm-stargate/src/index.ts | 2 + .../cosmwasm-stargate/src/modules/index.ts | 2 + .../src/signingcosmwasmclient.spec.ts | 2 +- .../src/signingcosmwasmclient.ts | 45 +++---------------- 4 files changed, 12 insertions(+), 39 deletions(-) diff --git a/packages/cosmwasm-stargate/src/index.ts b/packages/cosmwasm-stargate/src/index.ts index 91c5af3461..602f811558 100644 --- a/packages/cosmwasm-stargate/src/index.ts +++ b/packages/cosmwasm-stargate/src/index.ts @@ -5,6 +5,7 @@ export { createWasmAminoConverters, isMsgClearAdminEncodeObject, isMsgExecuteEncodeObject, + isMsgInstantiateContract2EncodeObject, isMsgInstantiateContractEncodeObject, isMsgMigrateEncodeObject, isMsgStoreCodeEncodeObject, @@ -12,6 +13,7 @@ export { JsonObject, MsgClearAdminEncodeObject, MsgExecuteContractEncodeObject, + MsgInstantiateContract2EncodeObject, MsgInstantiateContractEncodeObject, MsgMigrateContractEncodeObject, MsgStoreCodeEncodeObject, diff --git a/packages/cosmwasm-stargate/src/modules/index.ts b/packages/cosmwasm-stargate/src/modules/index.ts index 04cb2a7937..2b3114cbd8 100644 --- a/packages/cosmwasm-stargate/src/modules/index.ts +++ b/packages/cosmwasm-stargate/src/modules/index.ts @@ -10,12 +10,14 @@ export { export { isMsgClearAdminEncodeObject, isMsgExecuteEncodeObject, + isMsgInstantiateContract2EncodeObject, isMsgInstantiateContractEncodeObject, isMsgMigrateEncodeObject, isMsgStoreCodeEncodeObject, isMsgUpdateAdminEncodeObject, MsgClearAdminEncodeObject, MsgExecuteContractEncodeObject, + MsgInstantiateContract2EncodeObject, MsgInstantiateContractEncodeObject, MsgMigrateContractEncodeObject, MsgStoreCodeEncodeObject, diff --git a/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts b/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts index f1c0d4e065..e2892e6cde 100644 --- a/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts +++ b/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts @@ -274,13 +274,13 @@ describe("SigningCosmWasmClient", () => { const { contractAddress } = await client.instantiate2( alice.address0, codeId, + salt, msg, "My cool label--", defaultInstantiateFee, { memo: "Let's see if the memo is used", funds: funds, - salt: salt, }, ); diff --git a/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts b/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts index f521855420..39ffb13009 100644 --- a/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts +++ b/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts @@ -55,13 +55,13 @@ import { JsonObject, MsgClearAdminEncodeObject, MsgExecuteContractEncodeObject, + MsgInstantiateContract2EncodeObject, MsgInstantiateContractEncodeObject, MsgMigrateContractEncodeObject, MsgStoreCodeEncodeObject, MsgUpdateAdminEncodeObject, wasmTypes, } from "./modules"; -import { MsgInstantiateContract2EncodeObject } from "./modules/wasm/messages"; export interface UploadResult { /** Size of the original wasm code in bytes */ @@ -85,7 +85,7 @@ export interface UploadResult { } /** - * The options of an .instantiate() call. + * The options of .instantiate() and .instantiate2() call. * All properties are optional. */ export interface InstantiateOptions { @@ -105,38 +105,6 @@ export interface InstantiateOptions { readonly admin?: string; } -/** - * The options of an .instantiate() call. - * All properties are optional. - */ -export interface Instantiate2Options { - readonly memo?: string; - /** - * The funds that are transferred from the sender to the newly created contract. - * The funds are transferred as part of the message execution after the contract address is - * created and before the instantiation message is executed by the contract. - * - * Only native tokens are supported. - */ - readonly funds?: readonly Coin[]; - /** - * A bech32 encoded address of an admin account. - * Caution: an admin has the privilege to upgrade a contract. If this is not desired, do not set this value. - */ - readonly admin?: string; - - /** - * salt is an arbitrary value provided by the sender. Size can be 1 to 64. - */ - readonly salt?: Uint8Array; - - /** - * FixMsg include the msg value into the hash for the predictable address. - * Default is false - */ - readonly fixMsg?: boolean; -} - export interface InstantiateResult { /** The address of the newly instantiated contract */ readonly contractAddress: string; @@ -372,10 +340,11 @@ export class SigningCosmWasmClient extends CosmWasmClient { public async instantiate2( senderAddress: string, codeId: number, - msg: Record, + salt: Uint8Array, + msg: JsonObject, label: string, fee: StdFee | "auto" | number, - options: Instantiate2Options = {}, + options: InstantiateOptions = {}, ): Promise { const instantiateContract2Msg: MsgInstantiateContract2EncodeObject = { typeUrl: "/cosmwasm.wasm.v1.MsgInstantiateContract2", @@ -386,8 +355,8 @@ export class SigningCosmWasmClient extends CosmWasmClient { msg: toUtf8(JSON.stringify(msg)), funds: [...(options.funds || [])], admin: options.admin, - salt: options.salt, - fixMsg: options.fixMsg, + salt: salt, + fixMsg: false, }), }; const result = await this.signAndBroadcast(senderAddress, [instantiateContract2Msg], fee, options.memo); From cf6bea64a3e1a40fe4a4c10544bdf9e61e871814 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Wed, 24 May 2023 10:27:00 +0200 Subject: [PATCH 4/4] Add CHANGELOG entry --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90cf46ddad..f0134e9b09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ and this project adheres to ## [Unreleased] +### Added + +- @cosmjs/cosmwasm-stargate: Add `SigningCosmWasmClient.instantiate2` ([#1407]). + +[#1407]: https://github.com/cosmos/cosmjs/pull/1407 + ### Changed - all: upgrade cosmjs-types to 0.8.0 to include Cosmos SDK 0.46/0.47 and IBC v7