Merge pull request #1424 from cosmos/instantiate2-simon

Add instantiate2 (finish #1407)
This commit is contained in:
Simon Warta 2023-05-24 10:49:01 +02:00 committed by GitHub
commit 6a8ba0ccb6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 112 additions and 1 deletions

View File

@ -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

View File

@ -5,6 +5,7 @@ export {
createWasmAminoConverters,
isMsgClearAdminEncodeObject,
isMsgExecuteEncodeObject,
isMsgInstantiateContract2EncodeObject,
isMsgInstantiateContractEncodeObject,
isMsgMigrateEncodeObject,
isMsgStoreCodeEncodeObject,
@ -12,6 +13,7 @@ export {
JsonObject,
MsgClearAdminEncodeObject,
MsgExecuteContractEncodeObject,
MsgInstantiateContract2EncodeObject,
MsgInstantiateContractEncodeObject,
MsgMigrateContractEncodeObject,
MsgStoreCodeEncodeObject,

View File

@ -10,12 +10,14 @@ export {
export {
isMsgClearAdminEncodeObject,
isMsgExecuteEncodeObject,
isMsgInstantiateContract2EncodeObject,
isMsgInstantiateContractEncodeObject,
isMsgMigrateEncodeObject,
isMsgStoreCodeEncodeObject,
isMsgUpdateAdminEncodeObject,
MsgClearAdminEncodeObject,
MsgExecuteContractEncodeObject,
MsgInstantiateContract2EncodeObject,
MsgInstantiateContractEncodeObject,
MsgMigrateContractEncodeObject,
MsgStoreCodeEncodeObject,

View File

@ -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<MsgInstantiateContract2>;
}
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<MsgUpdateAdmin>;

View File

@ -24,6 +24,7 @@ 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";
import {
@ -252,6 +253,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,
salt,
msg,
"My cool label--",
defaultInstantiateFee,
{
memo: "Let's see if the memo is used",
funds: funds,
},
);
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();

View File

@ -46,6 +46,7 @@ import {
MsgClearAdmin,
MsgExecuteContract,
MsgInstantiateContract,
MsgInstantiateContract2,
MsgMigrateContract,
MsgStoreCode,
MsgUpdateAdmin,
@ -59,6 +60,7 @@ import {
JsonObject,
MsgClearAdminEncodeObject,
MsgExecuteContractEncodeObject,
MsgInstantiateContract2EncodeObject,
MsgInstantiateContractEncodeObject,
MsgMigrateContractEncodeObject,
MsgStoreCodeEncodeObject,
@ -86,7 +88,7 @@ export interface UploadResult {
}
/**
* The options of an .instantiate() call.
* The options of .instantiate() and .instantiate2() call.
* All properties are optional.
*/
export interface InstantiateOptions {
@ -348,6 +350,45 @@ export class SigningCosmWasmClient extends CosmWasmClient {
};
}
public async instantiate2(
senderAddress: string,
codeId: number,
salt: Uint8Array,
msg: JsonObject,
label: string,
fee: StdFee | "auto" | number,
options: InstantiateOptions = {},
): Promise<InstantiateResult> {
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: salt,
fixMsg: false,
}),
};
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,