diff --git a/packages/cosmwasm-stargate/src/modules/wasm/aminomessages.spec.ts b/packages/cosmwasm-stargate/src/modules/wasm/aminomessages.spec.ts index 4f75c472..1ddb441f 100644 --- a/packages/cosmwasm-stargate/src/modules/wasm/aminomessages.spec.ts +++ b/packages/cosmwasm-stargate/src/modules/wasm/aminomessages.spec.ts @@ -9,6 +9,7 @@ import { MsgStoreCode, MsgUpdateAdmin, } from "cosmjs-types/cosmwasm/wasm/v1/tx"; +import { AccessType } from "cosmjs-types/cosmwasm/wasm/v1/types"; import Long from "long"; import { @@ -38,6 +39,34 @@ describe("AminoTypes", () => { value: { sender: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", wasm_byte_code: "WUVMTE9XIFNVQk1BUklORQ==", + instantiate_permission: undefined, + }, + }; + expect(aminoMsg).toEqual(expected); + }); + + it("works for MsgStoreCode with access type", () => { + const msg: MsgStoreCode = { + sender: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", + wasmByteCode: fromBase64("WUVMTE9XIFNVQk1BUklORQ=="), + instantiatePermission: { + permission: AccessType.ACCESS_TYPE_ONLY_ADDRESS, + address: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", + }, + }; + const aminoMsg = new AminoTypes(createWasmAminoConverters()).toAmino({ + typeUrl: "/cosmwasm.wasm.v1.MsgStoreCode", + value: msg, + }); + const expected: AminoMsgStoreCode = { + type: "wasm/MsgStoreCode", + value: { + sender: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", + wasm_byte_code: "WUVMTE9XIFNVQk1BUklORQ==", + instantiate_permission: { + permission: "OnlyAddress", + address: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", + }, }, }; expect(aminoMsg).toEqual(expected); @@ -209,6 +238,33 @@ describe("AminoTypes", () => { }); }); + it("works for MsgStoreCode with access type", () => { + const aminoMsg: AminoMsgStoreCode = { + type: "wasm/MsgStoreCode", + value: { + sender: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", + wasm_byte_code: "WUVMTE9XIFNVQk1BUklORQ==", + instantiate_permission: { + permission: "OnlyAddress", + address: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", + }, + }, + }; + const msg = new AminoTypes(createWasmAminoConverters()).fromAmino(aminoMsg); + const expectedValue: MsgStoreCode = { + sender: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", + wasmByteCode: fromBase64("WUVMTE9XIFNVQk1BUklORQ=="), + instantiatePermission: { + permission: AccessType.ACCESS_TYPE_ONLY_ADDRESS, + address: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", + }, + }; + expect(msg).toEqual({ + typeUrl: "/cosmwasm.wasm.v1.MsgStoreCode", + value: expectedValue, + }); + }); + it("works for MsgInstantiateContract", () => { // With admin { diff --git a/packages/cosmwasm-stargate/src/modules/wasm/aminomessages.ts b/packages/cosmwasm-stargate/src/modules/wasm/aminomessages.ts index 5ba5cac9..5fc534e3 100644 --- a/packages/cosmwasm-stargate/src/modules/wasm/aminomessages.ts +++ b/packages/cosmwasm-stargate/src/modules/wasm/aminomessages.ts @@ -9,13 +9,51 @@ import { MsgStoreCode, MsgUpdateAdmin, } from "cosmjs-types/cosmwasm/wasm/v1/tx"; +import { AccessType } from "cosmjs-types/cosmwasm/wasm/v1/types"; import Long from "long"; -// TODO: implement +export function accessTypeFromString(str: string): AccessType { + switch (str) { + case "Unspecified": + return AccessType.ACCESS_TYPE_UNSPECIFIED; + case "Nobody": + return AccessType.ACCESS_TYPE_NOBODY; + case "OnlyAddress": + return AccessType.ACCESS_TYPE_ONLY_ADDRESS; + case "Everybody": + return AccessType.ACCESS_TYPE_EVERYBODY; + default: + return AccessType.UNRECOGNIZED; + } +} + +export function accessTypeToString(object: any): string { + switch (object) { + case AccessType.ACCESS_TYPE_UNSPECIFIED: + return "Unspecified"; + case AccessType.ACCESS_TYPE_NOBODY: + return "Nobody"; + case AccessType.ACCESS_TYPE_ONLY_ADDRESS: + return "OnlyAddress"; + case AccessType.ACCESS_TYPE_EVERYBODY: + return "Everybody"; + case AccessType.UNRECOGNIZED: + default: + return "UNRECOGNIZED"; + } +} + /** * @see https://github.com/CosmWasm/wasmd/blob/v0.18.0-rc1/proto/cosmwasm/wasm/v1/types.proto#L36-L41 */ -type AccessConfig = never; +export interface AccessConfig { + /** + * Permission should be one kind of string 'Nobody', 'OnlyAddress', 'Everybody', 'Unspecified' + * @see https://github.com/CosmWasm/wasmd/blob/v0.28.0/x/wasm/types/params.go#L54 + */ + readonly permission: string; + readonly address?: string; +} /** * The Amino JSON representation of [MsgStoreCode]. @@ -128,14 +166,33 @@ export function createWasmAminoConverters(): AminoConverters { return { "/cosmwasm.wasm.v1.MsgStoreCode": { aminoType: "wasm/MsgStoreCode", - toAmino: ({ sender, wasmByteCode }: MsgStoreCode): AminoMsgStoreCode["value"] => ({ + toAmino: ({ + sender, + wasmByteCode, + instantiatePermission, + }: MsgStoreCode): AminoMsgStoreCode["value"] => ({ sender: sender, wasm_byte_code: toBase64(wasmByteCode), + instantiate_permission: instantiatePermission + ? { + permission: accessTypeToString(instantiatePermission.permission), + address: instantiatePermission.address || undefined, + } + : undefined, }), - fromAmino: ({ sender, wasm_byte_code }: AminoMsgStoreCode["value"]): MsgStoreCode => ({ + fromAmino: ({ + sender, + wasm_byte_code, + instantiate_permission, + }: AminoMsgStoreCode["value"]): MsgStoreCode => ({ sender: sender, wasmByteCode: fromBase64(wasm_byte_code), - instantiatePermission: undefined, + instantiatePermission: instantiate_permission + ? { + permission: accessTypeFromString(instantiate_permission.permission), + address: instantiate_permission.address ?? "", + } + : undefined, }), }, "/cosmwasm.wasm.v1.MsgInstantiateContract": { diff --git a/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts b/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts index fac91980..b0c47274 100644 --- a/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts +++ b/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts @@ -20,6 +20,7 @@ import { Coin } from "cosmjs-types/cosmos/base/v1beta1/coin"; import { MsgDelegate } from "cosmjs-types/cosmos/staking/v1beta1/tx"; import { AuthInfo, TxBody, TxRaw } from "cosmjs-types/cosmos/tx/v1beta1/tx"; import { MsgExecuteContract, MsgStoreCode } from "cosmjs-types/cosmwasm/wasm/v1/tx"; +import { AccessConfig, AccessType } from "cosmjs-types/cosmwasm/wasm/v1/types"; import Long from "long"; import pako from "pako"; import protobuf from "protobufjs/minimal"; @@ -113,6 +114,26 @@ describe("SigningCosmWasmClient", () => { expect(codeId).toBeGreaterThanOrEqual(1); client.disconnect(); }); + + it("works with legacy Amino signer access type", async () => { + pendingWithoutWasmd(); + const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: wasmd.prefix }); + const options = { ...defaultSigningClientOptions, prefix: wasmd.prefix }; + const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options); + const wasm = getHackatom().data; + const accessConfig: AccessConfig = { + permission: AccessType.ACCESS_TYPE_EVERYBODY, + address: "", + }; + const { codeId, originalChecksum, originalSize, compressedChecksum, compressedSize } = + await client.upload(alice.address0, wasm, defaultUploadFee, "test memo", accessConfig); + expect(originalChecksum).toEqual(toHex(sha256(wasm))); + expect(originalSize).toEqual(wasm.length); + expect(compressedChecksum).toMatch(/^[0-9a-f]{64}$/); + expect(compressedSize).toBeLessThan(wasm.length * 0.5); + expect(codeId).toBeGreaterThanOrEqual(1); + client.disconnect(); + }); }); describe("instantiate", () => { diff --git a/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts b/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts index 5d03812a..e5340da7 100644 --- a/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts +++ b/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts @@ -45,6 +45,7 @@ import { MsgStoreCode, MsgUpdateAdmin, } from "cosmjs-types/cosmwasm/wasm/v1/tx"; +import { AccessConfig } from "cosmjs-types/cosmwasm/wasm/v1/types"; import Long from "long"; import pako from "pako"; @@ -251,6 +252,7 @@ export class SigningCosmWasmClient extends CosmWasmClient { wasmCode: Uint8Array, fee: StdFee | "auto" | number, memo = "", + instantiatePermission?: AccessConfig, ): Promise { const compressed = pako.gzip(wasmCode, { level: 9 }); const storeCodeMsg: MsgStoreCodeEncodeObject = { @@ -258,6 +260,7 @@ export class SigningCosmWasmClient extends CosmWasmClient { value: MsgStoreCode.fromPartial({ sender: senderAddress, wasmByteCode: compressed, + instantiatePermission, }), };