Add SigningCosmWasmClient.simulate

This commit is contained in:
Simon Warta 2021-11-17 20:20:41 +01:00
parent 5511c242c1
commit 4bf33f24ea
3 changed files with 60 additions and 8 deletions

View File

@ -19,7 +19,9 @@ import {
SequenceResponse,
setupAuthExtension,
setupBankExtension,
setupTxExtension,
TimeoutError,
TxExtension,
} from "@cosmjs/stargate";
import { Tendermint34Client, toRfc3339WithNanoseconds } from "@cosmjs/tendermint-rpc";
import { assert, sleep } from "@cosmjs/utils";
@ -75,12 +77,16 @@ export interface ContractCodeHistoryEntry {
/** Use for testing only */
export interface PrivateCosmWasmClient {
readonly tmClient: Tendermint34Client | undefined;
readonly queryClient: (QueryClient & AuthExtension & BankExtension & WasmExtension) | undefined;
readonly queryClient:
| (QueryClient & AuthExtension & BankExtension & TxExtension & WasmExtension)
| undefined;
}
export class CosmWasmClient {
private readonly tmClient: Tendermint34Client | undefined;
private readonly queryClient: (QueryClient & AuthExtension & BankExtension & WasmExtension) | undefined;
private readonly queryClient:
| (QueryClient & AuthExtension & BankExtension & TxExtension & WasmExtension)
| undefined;
private readonly codesCache = new Map<number, CodeDetails>();
private chainId: string | undefined;
@ -97,6 +103,7 @@ export class CosmWasmClient {
setupAuthExtension,
setupBankExtension,
setupWasmExtension,
setupTxExtension,
);
}
}
@ -114,11 +121,13 @@ export class CosmWasmClient {
return this.tmClient;
}
protected getQueryClient(): (QueryClient & AuthExtension & BankExtension & WasmExtension) | undefined {
protected getQueryClient():
| (QueryClient & AuthExtension & BankExtension & TxExtension & WasmExtension)
| undefined {
return this.queryClient;
}
protected forceGetQueryClient(): QueryClient & AuthExtension & BankExtension & WasmExtension {
protected forceGetQueryClient(): QueryClient & AuthExtension & BankExtension & TxExtension & WasmExtension {
if (!this.queryClient) {
throw new Error("Query client not available. You cannot use online functionality in offline mode.");
}

View File

@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { Secp256k1HdWallet } from "@cosmjs/amino";
import { sha256 } from "@cosmjs/crypto";
import { toHex } from "@cosmjs/encoding";
import { toHex, toUtf8 } from "@cosmjs/encoding";
import { decodeTxRaw, DirectSecp256k1HdWallet, Registry } from "@cosmjs/proto-signing";
import {
AminoMsgDelegate,
@ -17,12 +17,12 @@ import { DeepPartial, MsgSend } from "cosmjs-types/cosmos/bank/v1beta1/tx";
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 { MsgStoreCode } from "cosmjs-types/cosmwasm/wasm/v1/tx";
import { MsgExecuteContract, MsgStoreCode } from "cosmjs-types/cosmwasm/wasm/v1/tx";
import Long from "long";
import pako from "pako";
import protobuf from "protobufjs/minimal";
import { MsgStoreCodeEncodeObject } from "./encodeobjects";
import { MsgExecuteContractEncodeObject, MsgStoreCodeEncodeObject } from "./encodeobjects";
import { SigningCosmWasmClient } from "./signingcosmwasmclient";
import {
alice,
@ -71,6 +71,30 @@ describe("SigningCosmWasmClient", () => {
});
});
describe("simulate", () => {
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 executeContractMsg: MsgExecuteContractEncodeObject = {
typeUrl: "/cosmwasm.wasm.v1.MsgExecuteContract",
value: MsgExecuteContract.fromPartial({
sender: alice.address0,
contract: deployedHackatom.instances[0].address,
msg: toUtf8(`{"release":{}}`),
funds: [],
}),
};
const memo = "Go go go";
const gasUsed = await client.simulate(alice.address0, [executeContractMsg], memo);
expect(gasUsed).toBeGreaterThanOrEqual(101_000);
expect(gasUsed).toBeLessThanOrEqual(106_000);
client.disconnect();
});
});
describe("upload", () => {
it("works", async () => {
pendingWithoutWasmd();

View File

@ -29,7 +29,7 @@ import {
StdFee,
} from "@cosmjs/stargate";
import { Tendermint34Client } from "@cosmjs/tendermint-rpc";
import { assert } from "@cosmjs/utils";
import { assert, assertDefined } from "@cosmjs/utils";
import { MsgWithdrawDelegatorReward } from "cosmjs-types/cosmos/distribution/v1beta1/tx";
import { MsgDelegate, MsgUndelegate } from "cosmjs-types/cosmos/staking/v1beta1/tx";
import { SignMode } from "cosmjs-types/cosmos/tx/signing/v1beta1/signing";
@ -196,6 +196,25 @@ export class SigningCosmWasmClient extends CosmWasmClient {
this.broadcastPollIntervalMs = options.broadcastPollIntervalMs;
}
public async simulate(
signerAddress: string,
messages: readonly EncodeObject[],
memo: string | undefined,
): Promise<number> {
const anyMsgs = messages.map((m) => this.registry.encodeAsAny(m));
const accountFromSigner = (await this.signer.getAccounts()).find(
(account) => account.address === signerAddress,
);
if (!accountFromSigner) {
throw new Error("Failed to retrieve account from signer");
}
const pubkey = encodeSecp256k1Pubkey(accountFromSigner.pubkey);
const { sequence } = await this.getSequence(signerAddress);
const { gasInfo } = await this.forceGetQueryClient().tx.simulate(anyMsgs, memo, pubkey, sequence);
assertDefined(gasInfo);
return Uint53.fromString(gasInfo.gasUsed.toString()).toNumber();
}
/** Uploads code and returns a receipt, including the code ID */
public async upload(
senderAddress: string,