Skip to content
26 changes: 26 additions & 0 deletions packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,32 @@ describe("SigningCosmWasmClient", () => {
expect(gasUsed).toBeLessThanOrEqual(140_000);
client.disconnect();
});
it("works with explicitSignerData", async () => {
pendingWithoutWasmd();
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: wasmd.prefix });
const client = await SigningCosmWasmClient.connectWithSigner(
wasmd.endpoint,
wallet,
defaultSigningClientOptions,
);

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 { sequence } = await client.getSequence(alice.address0)

const gasUsed = await client.simulate(alice.address0, [executeContractMsg], memo, { sequence });
expect(gasUsed).toBeGreaterThanOrEqual(70_000);
expect(gasUsed).toBeLessThanOrEqual(140_000);
client.disconnect();
});
});

describe("upload", () => {
Expand Down
31 changes: 28 additions & 3 deletions packages/cosmwasm-stargate/src/signingcosmwasmclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
signerAddress: string,
messages: readonly EncodeObject[],
memo: string | undefined,
explicitSignerData?: Partial<SignerData>,
): Promise<number> {
const anyMsgs = messages.map((m) => this.registry.encodeAsAny(m));
const accountFromSigner = (await this.signer.getAccounts()).find(
Expand All @@ -283,7 +284,15 @@ export class SigningCosmWasmClient extends CosmWasmClient {
throw new Error("Failed to retrieve account from signer");
}
const pubkey = encodeSecp256k1Pubkey(accountFromSigner.pubkey);
const { sequence } = await this.getSequence(signerAddress);

let sequence: number

if (explicitSignerData?.sequence !== undefined) {
sequence = explicitSignerData.sequence;
} else {
sequence = (await this.getSequence(signerAddress)).sequence;
}

const { gasInfo } = await this.forceGetQueryClient().tx.simulate(anyMsgs, memo, pubkey, sequence);
assertDefined(gasInfo);
return Uint53.fromString(gasInfo.gasUsed.toString()).toNumber();
Expand Down Expand Up @@ -612,17 +621,33 @@ export class SigningCosmWasmClient extends CosmWasmClient {
fee: StdFee | "auto" | number,
memo = "",
timeoutHeight?: bigint,
explicitSignerData?: SignerData,
): Promise<DeliverTxResponse> {
let usedFee: StdFee;

let signerData: SignerData | undefined = explicitSignerData
const { sequence, accountNumber } = explicitSignerData ? explicitSignerData : await this.getSequence(signerAddress);

if (fee == "auto" || typeof fee === "number") {
assertDefined(this.gasPrice, "Gas price must be set in the client options when auto gas is used.");
const gasEstimation = await this.simulate(signerAddress, messages, memo);
const gasEstimation = await this.simulate(signerAddress, messages, memo, { sequence });
const multiplier = typeof fee === "number" ? fee : this.defaultGasMultiplier;
usedFee = calculateFee(Math.round(gasEstimation * multiplier), this.gasPrice);
} else {
usedFee = fee;
}
const txRaw = await this.sign(signerAddress, messages, usedFee, memo, undefined, timeoutHeight);

if (!signerData) {
const chainId = await this.getChainId();

signerData = {
accountNumber: accountNumber,
sequence: sequence,
chainId: chainId,
};
}

const txRaw = await this.sign(signerAddress, messages, usedFee, memo, signerData, timeoutHeight);
const txBytes = TxRaw.encode(txRaw).finish();
return this.broadcastTx(txBytes, this.broadcastTimeoutMs, this.broadcastPollIntervalMs);
}
Expand Down
27 changes: 27 additions & 0 deletions packages/stargate/src/signingstargateclient.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,33 @@ describe("SigningStargateClient", () => {
expect(gasUsed).toBeGreaterThanOrEqual(101_000);
expect(gasUsed).toBeLessThanOrEqual(200_000);

client.disconnect();
});
it("works with explicitSignerData", async () => {
pendingWithoutSimapp();
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic);
const client = await SigningStargateClient.connectWithSigner(
simapp.tendermintUrlHttp,
wallet,
defaultSigningClientOptions,
);

const msg = MsgDelegate.fromPartial({
delegatorAddress: faucet.address0,
validatorAddress: validator.validatorAddress,
amount: coin(1234, "ustake"),
});
const msgAny: MsgDelegateEncodeObject = {
typeUrl: "/cosmos.staking.v1beta1.MsgDelegate",
value: msg,
};
const memo = "Use your power wisely";

const { sequence } = await client.getSequence(faucet.address0)
const gasUsed = await client.simulate(faucet.address0, [msgAny], memo, { sequence });
expect(gasUsed).toBeGreaterThanOrEqual(101_000);
expect(gasUsed).toBeLessThanOrEqual(200_000);

client.disconnect();
});
});
Expand Down
33 changes: 29 additions & 4 deletions packages/stargate/src/signingstargateclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import {
createStakingAminoConverters,
createVestingAminoConverters,
} from "./modules";
import { DeliverTxResponse, StargateClient, StargateClientOptions } from "./stargateclient";
import { DeliverTxResponse, SequenceResponse, StargateClient, StargateClientOptions } from "./stargateclient";

export const defaultRegistryTypes: ReadonlyArray<[string, GeneratedType]> = [
["/cosmos.base.v1beta1.Coin", Coin],
Expand Down Expand Up @@ -179,6 +179,7 @@ export class SigningStargateClient extends StargateClient {
signerAddress: string,
messages: readonly EncodeObject[],
memo: string | undefined,
explicitSignerData?: Partial<SignerData>,
): Promise<number> {
const anyMsgs = messages.map((m) => this.registry.encodeAsAny(m));
const accountFromSigner = (await this.signer.getAccounts()).find(
Expand All @@ -188,7 +189,15 @@ export class SigningStargateClient extends StargateClient {
throw new Error("Failed to retrieve account from signer");
}
const pubkey = encodeSecp256k1Pubkey(accountFromSigner.pubkey);
const { sequence } = await this.getSequence(signerAddress);

let sequence: number

if (explicitSignerData?.sequence !== undefined) {
sequence = explicitSignerData.sequence;
} else {
sequence = (await this.getSequence(signerAddress)).sequence;
}

const { gasInfo } = await this.forceGetQueryClient().tx.simulate(anyMsgs, memo, pubkey, sequence);
assertDefined(gasInfo);
return Uint53.fromString(gasInfo.gasUsed.toString()).toNumber();
Expand Down Expand Up @@ -306,17 +315,33 @@ export class SigningStargateClient extends StargateClient {
fee: StdFee | "auto" | number,
memo = "",
timeoutHeight?: bigint,
explicitSignerData?: SignerData,
): Promise<DeliverTxResponse> {
let usedFee: StdFee;

let signerData: SignerData | undefined = explicitSignerData
const { sequence, accountNumber } = explicitSignerData ? explicitSignerData : await this.getSequence(signerAddress);

if (fee == "auto" || typeof fee === "number") {
assertDefined(this.gasPrice, "Gas price must be set in the client options when auto gas is used.");
const gasEstimation = await this.simulate(signerAddress, messages, memo);
const gasEstimation = await this.simulate(signerAddress, messages, memo, { sequence });
const multiplier = typeof fee === "number" ? fee : this.defaultGasMultiplier;
usedFee = calculateFee(Math.round(gasEstimation * multiplier), this.gasPrice);
} else {
usedFee = fee;
}
const txRaw = await this.sign(signerAddress, messages, usedFee, memo, undefined, timeoutHeight);

if (!signerData) {
const chainId = await this.getChainId();

signerData = {
accountNumber: accountNumber,
sequence: sequence,
chainId: chainId,
};
}

const txRaw = await this.sign(signerAddress, messages, usedFee, memo, signerData, timeoutHeight);
const txBytes = TxRaw.encode(txRaw).finish();
return this.broadcastTx(txBytes, this.broadcastTimeoutMs, this.broadcastPollIntervalMs);
}
Expand Down