From f4e6786f5b5965c5538ee9e023cdb4ce46adcba2 Mon Sep 17 00:00:00 2001 From: willclarktech Date: Wed, 14 Apr 2021 16:19:01 +0200 Subject: [PATCH 1/5] stargate: Adjust variable name --- packages/stargate/src/signingstargateclient.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/stargate/src/signingstargateclient.ts b/packages/stargate/src/signingstargateclient.ts index c1215de6..31c81f24 100644 --- a/packages/stargate/src/signingstargateclient.ts +++ b/packages/stargate/src/signingstargateclient.ts @@ -297,8 +297,8 @@ export class SigningStargateClient extends StargateClient { memo = "", ): Promise { const txRaw = await this.sign(signerAddress, messages, fee, memo); - const signedTx = Uint8Array.from(TxRaw.encode(txRaw).finish()); - return this.broadcastTx(signedTx); + const txBytes = Uint8Array.from(TxRaw.encode(txRaw).finish()); + return this.broadcastTx(txBytes); } /** From db4ffc545ea2197dc6f5abb38e571fbd25888698 Mon Sep 17 00:00:00 2001 From: willclarktech Date: Wed, 14 Apr 2021 16:19:36 +0200 Subject: [PATCH 2/5] cosmwasm-stargate: Add sign method to SigningCosmWasmClient --- .../src/signingcosmwasmclient.ts | 104 +++++++++++++----- 1 file changed, 75 insertions(+), 29 deletions(-) diff --git a/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts b/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts index 8da3742c..d8451599 100644 --- a/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts +++ b/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts @@ -36,6 +36,7 @@ import { GasPrice, isBroadcastTxFailure, logs, + SignerData, StdFee, } from "@cosmjs/stargate"; import { MsgWithdrawDelegatorReward } from "@cosmjs/stargate/build/codec/cosmos/distribution/v1beta1/tx"; @@ -43,6 +44,7 @@ import { MsgDelegate, MsgUndelegate } from "@cosmjs/stargate/build/codec/cosmos/ import { SignMode } from "@cosmjs/stargate/build/codec/cosmos/tx/signing/v1beta1/signing"; import { TxRaw } from "@cosmjs/stargate/build/codec/cosmos/tx/v1beta1/tx"; import { Tendermint34Client } from "@cosmjs/tendermint-rpc"; +import { assert } from "@cosmjs/utils"; import Long from "long"; import pako from "pako"; @@ -402,6 +404,44 @@ export class SigningCosmWasmClient extends CosmWasmClient { fee: StdFee, memo = "", ): Promise { + const txRaw = await this.sign(signerAddress, messages, fee, memo); + const txBytes = Uint8Array.from(TxRaw.encode(txRaw).finish()); + return this.broadcastTx(txBytes); + } + + public async sign( + signerAddress: string, + messages: readonly EncodeObject[], + fee: StdFee, + memo: string, + explicitSignerData?: SignerData, + ): Promise { + let signerData: SignerData; + if (explicitSignerData) { + signerData = explicitSignerData; + } else { + const { accountNumber, sequence } = await this.getSequence(signerAddress); + const chainId = await this.getChainId(); + signerData = { + accountNumber: accountNumber, + sequence: sequence, + chainId: chainId, + }; + } + + return isOfflineDirectSigner(this.signer) + ? this.signDirect(signerAddress, messages, fee, memo, signerData) + : this.signAmino(signerAddress, messages, fee, memo, signerData); + } + + private async signAmino( + signerAddress: string, + messages: readonly EncodeObject[], + fee: StdFee, + memo: string, + { accountNumber, sequence, chainId }: SignerData, + ): Promise { + assert(!isOfflineDirectSigner(this.signer)); const accountFromSigner = (await this.signer.getAccounts()).find( (account) => account.address === signerAddress, ); @@ -409,32 +449,6 @@ export class SigningCosmWasmClient extends CosmWasmClient { throw new Error("Failed to retrieve account from signer"); } const pubkey = encodePubkey(encodeSecp256k1Pubkey(accountFromSigner.pubkey)); - const { accountNumber, sequence } = await this.getSequence(signerAddress); - const chainId = await this.getChainId(); - const txBody = { - messages: messages, - memo: memo, - }; - const txBodyBytes = this.registry.encode({ - typeUrl: "/cosmos.tx.v1beta1.TxBody", - value: txBody, - }); - const gasLimit = Int53.fromString(fee.gas).toNumber(); - - if (isOfflineDirectSigner(this.signer)) { - const authInfoBytes = makeAuthInfoBytes([pubkey], fee.amount, gasLimit, sequence); - const signDoc = makeSignDoc(txBodyBytes, authInfoBytes, chainId, accountNumber); - const { signature, signed } = await this.signer.signDirect(signerAddress, signDoc); - const txRaw = TxRaw.fromPartial({ - bodyBytes: signed.bodyBytes, - authInfoBytes: signed.authInfoBytes, - signatures: [fromBase64(signature.signature)], - }); - const signedTx = Uint8Array.from(TxRaw.encode(txRaw).finish()); - return this.broadcastTx(signedTx); - } - - // Amino signer const signMode = SignMode.SIGN_MODE_LEGACY_AMINO_JSON; const msgs = messages.map((msg) => this.aminoTypes.toAmino(msg)); const signDoc = makeSignDocAmino(msgs, fee, chainId, memo, accountNumber, sequence); @@ -456,12 +470,44 @@ export class SigningCosmWasmClient extends CosmWasmClient { signedSequence, signMode, ); - const txRaw = TxRaw.fromPartial({ + return TxRaw.fromPartial({ bodyBytes: signedTxBodyBytes, authInfoBytes: signedAuthInfoBytes, signatures: [fromBase64(signature.signature)], }); - const signedTx = Uint8Array.from(TxRaw.encode(txRaw).finish()); - return this.broadcastTx(signedTx); + } + + private async signDirect( + signerAddress: string, + messages: readonly EncodeObject[], + fee: StdFee, + memo: string, + { accountNumber, sequence, chainId }: SignerData, + ): Promise { + assert(isOfflineDirectSigner(this.signer)); + const accountFromSigner = (await this.signer.getAccounts()).find( + (account) => account.address === signerAddress, + ); + if (!accountFromSigner) { + throw new Error("Failed to retrieve account from signer"); + } + const pubkey = encodePubkey(encodeSecp256k1Pubkey(accountFromSigner.pubkey)); + const txBody = { + messages: messages, + memo: memo, + }; + const txBodyBytes = this.registry.encode({ + typeUrl: "/cosmos.tx.v1beta1.TxBody", + value: txBody, + }); + const gasLimit = Int53.fromString(fee.gas).toNumber(); + const authInfoBytes = makeAuthInfoBytes([pubkey], fee.amount, gasLimit, sequence); + const signDoc = makeSignDoc(txBodyBytes, authInfoBytes, chainId, accountNumber); + const { signature, signed } = await this.signer.signDirect(signerAddress, signDoc); + return TxRaw.fromPartial({ + bodyBytes: signed.bodyBytes, + authInfoBytes: signed.authInfoBytes, + signatures: [fromBase64(signature.signature)], + }); } } From a39a818b5c77eb6ac23106875276ae85705c4d9b Mon Sep 17 00:00:00 2001 From: willclarktech Date: Wed, 14 Apr 2021 16:19:45 +0200 Subject: [PATCH 3/5] cosmwasm-stargate: Add tests for sign method --- .../src/signingcosmwasmclient.spec.ts | 300 +++++++++++++++++- 1 file changed, 283 insertions(+), 17 deletions(-) diff --git a/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts b/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts index ea76b5da..de0ad3dc 100644 --- a/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts +++ b/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts @@ -15,7 +15,7 @@ import { import { DeepPartial, MsgSend } from "@cosmjs/stargate/build/codec/cosmos/bank/v1beta1/tx"; import { Coin } from "@cosmjs/stargate/build/codec/cosmos/base/v1beta1/coin"; import { MsgDelegate } from "@cosmjs/stargate/build/codec/cosmos/staking/v1beta1/tx"; -import { Tx } from "@cosmjs/stargate/build/codec/cosmos/tx/v1beta1/tx"; +import { AuthInfo, Tx, TxBody, TxRaw } from "@cosmjs/stargate/build/codec/cosmos/tx/v1beta1/tx"; import { assert, sleep } from "@cosmjs/utils"; import Long from "long"; import pako from "pako"; @@ -547,11 +547,9 @@ describe("SigningCosmWasmClient", () => { describe("direct mode", () => { it("works", async () => { pendingWithoutWasmd(); - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: wasmd.prefix }); + const options = { prefix: wasmd.prefix }; + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, options); const msgDelegateTypeUrl = "/cosmos.staking.v1beta1.MsgDelegate"; - const registry = new Registry(); - registry.register(msgDelegateTypeUrl, MsgDelegate); - const options = { prefix: wasmd.prefix, registry: registry }; const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options); const msg = MsgDelegate.fromPartial({ @@ -574,13 +572,9 @@ describe("SigningCosmWasmClient", () => { it("works with a modifying signer", async () => { pendingWithoutWasmd(); - const wallet = await ModifyingDirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, { - prefix: wasmd.prefix, - }); + const options = { prefix: wasmd.prefix }; + const wallet = await ModifyingDirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, options); const msgDelegateTypeUrl = "/cosmos.staking.v1beta1.MsgDelegate"; - const registry = new Registry(); - registry.register(msgDelegateTypeUrl, MsgDelegate); - const options = { prefix: wasmd.prefix, registry: registry }; const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options); const msg = MsgDelegate.fromPartial({ @@ -615,8 +609,8 @@ describe("SigningCosmWasmClient", () => { describe("legacy Amino mode", () => { it("works with bank MsgSend", async () => { pendingWithoutWasmd(); - const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: wasmd.prefix }); const options = { prefix: wasmd.prefix }; + const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic, options); const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options); const msgSend: MsgSend = { @@ -639,8 +633,8 @@ describe("SigningCosmWasmClient", () => { it("works with staking MsgDelegate", async () => { pendingWithoutWasmd(); - const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: wasmd.prefix }); const options = { prefix: wasmd.prefix }; + const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic, options); const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options); const msgDelegate: MsgDelegate = { @@ -663,8 +657,8 @@ describe("SigningCosmWasmClient", () => { it("works with wasm MsgStoreCode", async () => { pendingWithoutWasmd(); - const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: wasmd.prefix }); const options = { prefix: wasmd.prefix }; + const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic, options); const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options); const { data, builder, source } = getHackatom(); @@ -808,10 +802,8 @@ describe("SigningCosmWasmClient", () => { it("works with a modifying signer", async () => { pendingWithoutWasmd(); - const wallet = await ModifyingSecp256k1HdWallet.fromMnemonic(alice.mnemonic, { - prefix: wasmd.prefix, - }); const options = { prefix: wasmd.prefix }; + const wallet = await ModifyingSecp256k1HdWallet.fromMnemonic(alice.mnemonic, options); const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options); const msg = { @@ -843,4 +835,278 @@ describe("SigningCosmWasmClient", () => { }); }); }); + + describe("sign", () => { + describe("direct mode", () => { + it("works", async () => { + pendingWithoutWasmd(); + const options = { prefix: wasmd.prefix }; + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, options); + const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options); + + const msg = MsgDelegate.fromPartial({ + delegatorAddress: alice.address0, + validatorAddress: validator.validatorAddress, + amount: coin(1234, "ustake"), + }); + const msgAny = { + typeUrl: "/cosmos.staking.v1beta1.MsgDelegate", + value: msg, + }; + const fee = { + amount: coins(2000, "ucosm"), + gas: "180000", // 180k + }; + const memo = "Use your power wisely"; + const signed = await client.sign(alice.address0, [msgAny], fee, memo); + + // ensure signature is valid + const result = await client.broadcastTx(Uint8Array.from(TxRaw.encode(signed).finish())); + assertIsBroadcastTxSuccess(result); + }); + + it("works with a modifying signer", async () => { + pendingWithoutWasmd(); + const options = { prefix: wasmd.prefix }; + const wallet = await ModifyingDirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, options); + const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options); + + const msg = MsgDelegate.fromPartial({ + delegatorAddress: alice.address0, + validatorAddress: validator.validatorAddress, + amount: coin(1234, "ustake"), + }); + const msgAny = { + typeUrl: "/cosmos.staking.v1beta1.MsgDelegate", + value: msg, + }; + const fee = { + amount: coins(2000, "ucosm"), + gas: "180000", // 180k + }; + const memo = "Use your power wisely"; + const signed = await client.sign(alice.address0, [msgAny], fee, memo); + + const body = TxBody.decode(signed.bodyBytes); + const authInfo = AuthInfo.decode(signed.authInfoBytes); + // From ModifyingDirectSecp256k1HdWallet + expect(body.memo).toEqual("This was modified"); + expect({ ...authInfo.fee!.amount[0] }).toEqual(coin(3000, "ucosm")); + expect(authInfo.fee!.gasLimit.toNumber()).toEqual(333333); + + // ensure signature is valid + const result = await client.broadcastTx(Uint8Array.from(TxRaw.encode(signed).finish())); + assertIsBroadcastTxSuccess(result); + }); + }); + + describe("legacy Amino mode", () => { + it("works with bank MsgSend", async () => { + pendingWithoutWasmd(); + const options = { prefix: wasmd.prefix }; + const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic, options); + const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options); + + const msgSend: MsgSend = { + fromAddress: alice.address0, + toAddress: makeRandomAddress(), + amount: coins(1234, "ucosm"), + }; + const msgAny = { + typeUrl: "/cosmos.bank.v1beta1.MsgSend", + value: msgSend, + }; + const fee = { + amount: coins(2000, "ucosm"), + gas: "200000", + }; + const memo = "Use your tokens wisely"; + const signed = await client.sign(alice.address0, [msgAny], fee, memo); + + // ensure signature is valid + const result = await client.broadcastTx(Uint8Array.from(TxRaw.encode(signed).finish())); + assertIsBroadcastTxSuccess(result); + }); + + it("works with staking MsgDelegate", async () => { + pendingWithoutWasmd(); + const options = { prefix: wasmd.prefix }; + const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic, options); + const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options); + + const msgDelegate: MsgDelegate = { + delegatorAddress: alice.address0, + validatorAddress: validator.validatorAddress, + amount: coin(1234, "ustake"), + }; + const msgAny = { + typeUrl: "/cosmos.staking.v1beta1.MsgDelegate", + value: msgDelegate, + }; + const fee = { + amount: coins(2000, "ustake"), + gas: "200000", + }; + const memo = "Use your tokens wisely"; + const signed = await client.sign(alice.address0, [msgAny], fee, memo); + + // ensure signature is valid + const result = await client.broadcastTx(Uint8Array.from(TxRaw.encode(signed).finish())); + assertIsBroadcastTxSuccess(result); + }); + + it("works with a custom registry and custom message", async () => { + pendingWithoutWasmd(); + const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: wasmd.prefix }); + + const customRegistry = new Registry(); + const msgDelegateTypeUrl = "/cosmos.staking.v1beta1.MsgDelegate"; + interface CustomMsgDelegate { + customDelegatorAddress?: string; + customValidatorAddress?: string; + customAmount?: Coin; + } + const baseCustomMsgDelegate: CustomMsgDelegate = { + customDelegatorAddress: "", + customValidatorAddress: "", + }; + const CustomMsgDelegate = { + // Adapted from autogenerated MsgDelegate implementation + encode( + message: CustomMsgDelegate, + writer: protobuf.Writer = protobuf.Writer.create(), + ): protobuf.Writer { + writer.uint32(10).string(message.customDelegatorAddress ?? ""); + writer.uint32(18).string(message.customValidatorAddress ?? ""); + if (message.customAmount !== undefined && message.customAmount !== undefined) { + Coin.encode(message.customAmount, writer.uint32(26).fork()).ldelim(); + } + return writer; + }, + + decode(): CustomMsgDelegate { + throw new Error("decode method should not be required"); + }, + + fromJSON(): CustomMsgDelegate { + throw new Error("fromJSON method should not be required"); + }, + + fromPartial(object: DeepPartial): CustomMsgDelegate { + const message = { ...baseCustomMsgDelegate } as CustomMsgDelegate; + if (object.customDelegatorAddress !== undefined && object.customDelegatorAddress !== null) { + message.customDelegatorAddress = object.customDelegatorAddress; + } else { + message.customDelegatorAddress = ""; + } + if (object.customValidatorAddress !== undefined && object.customValidatorAddress !== null) { + message.customValidatorAddress = object.customValidatorAddress; + } else { + message.customValidatorAddress = ""; + } + if (object.customAmount !== undefined && object.customAmount !== null) { + message.customAmount = Coin.fromPartial(object.customAmount); + } else { + message.customAmount = undefined; + } + return message; + }, + + toJSON(): unknown { + throw new Error("toJSON method should not be required"); + }, + }; + customRegistry.register(msgDelegateTypeUrl, CustomMsgDelegate); + const customAminoTypes = new AminoTypes({ + additions: { + "/cosmos.staking.v1beta1.MsgDelegate": { + aminoType: "cosmos-sdk/MsgDelegate", + toAmino: ({ + customDelegatorAddress, + customValidatorAddress, + customAmount, + }: CustomMsgDelegate): AminoMsgDelegate["value"] => { + assert(customDelegatorAddress, "missing customDelegatorAddress"); + assert(customValidatorAddress, "missing validatorAddress"); + assert(customAmount, "missing amount"); + return { + delegator_address: customDelegatorAddress, + validator_address: customValidatorAddress, + amount: { + amount: customAmount.amount, + denom: customAmount.denom, + }, + }; + }, + fromAmino: ({ + delegator_address, + validator_address, + amount, + }: AminoMsgDelegate["value"]): CustomMsgDelegate => ({ + customDelegatorAddress: delegator_address, + customValidatorAddress: validator_address, + customAmount: Coin.fromPartial(amount), + }), + }, + }, + }); + const options = { registry: customRegistry, aminoTypes: customAminoTypes }; + const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options); + + const msg: CustomMsgDelegate = { + customDelegatorAddress: alice.address0, + customValidatorAddress: validator.validatorAddress, + customAmount: coin(1234, "ustake"), + }; + const msgAny = { + typeUrl: "/cosmos.staking.v1beta1.MsgDelegate", + value: msg, + }; + const fee = { + amount: coins(2000, "ucosm"), + gas: "200000", + }; + const memo = "Use your power wisely"; + const signed = await client.sign(alice.address0, [msgAny], fee, memo); + + // ensure signature is valid + const result = await client.broadcastTx(Uint8Array.from(TxRaw.encode(signed).finish())); + assertIsBroadcastTxSuccess(result); + }); + + it("works with a modifying signer", async () => { + pendingWithoutWasmd(); + const options = { prefix: wasmd.prefix }; + const wallet = await ModifyingSecp256k1HdWallet.fromMnemonic(alice.mnemonic, options); + const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options); + + const msg: MsgDelegate = { + delegatorAddress: alice.address0, + validatorAddress: validator.validatorAddress, + amount: coin(1234, "ustake"), + }; + const msgAny = { + typeUrl: "/cosmos.staking.v1beta1.MsgDelegate", + value: msg, + }; + const fee = { + amount: coins(2000, "ucosm"), + gas: "200000", + }; + const memo = "Use your power wisely"; + const signed = await client.sign(alice.address0, [msgAny], fee, memo); + + const body = TxBody.decode(signed.bodyBytes); + const authInfo = AuthInfo.decode(signed.authInfoBytes); + // From ModifyingSecp256k1HdWallet + expect(body.memo).toEqual("This was modified"); + expect({ ...authInfo.fee!.amount[0] }).toEqual(coin(3000, "ucosm")); + expect(authInfo.fee!.gasLimit.toNumber()).toEqual(333333); + + // ensure signature is valid + const result = await client.broadcastTx(Uint8Array.from(TxRaw.encode(signed).finish())); + assertIsBroadcastTxSuccess(result); + }); + }); + }); }); From 4c0c614a328edeb78348ed74daa6a0e3d615edcc Mon Sep 17 00:00:00 2001 From: willclarktech Date: Wed, 14 Apr 2021 16:22:04 +0200 Subject: [PATCH 4/5] Update CHANGELOG for SigningCosmWasmClient.sign --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49c08b41..8653a1af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,7 +41,11 @@ and this project adheres to - @cosmjs/stargate: Add `SigningStargateClient.sign`, which allows you to create signed transactions without broadcasting them directly. The new type `SignerData` can be passed into `.sign` to skip querying account number, - sequence and chain ID. + sequence and chain ID +- @cosmjs/cosmwasm-stargate: Add `SigningCosmWasmClient.sign`, which allows you + to create signed transactions without broadcasting them directly. The new type + `SignerData` from @cosmjs/stargate can be passed into `.sign` to skip querying + account number, sequence and chain ID. - @cosmjs/stargate: Add constructor `SigningStargateClient.offline` which does not connect to Tendermint. This allows offline signing. - @cosmjs/stargate: Add `makeMultisignedTx` which allows you to assemble a From d09c5fbaf921510c21dd62d7039d8e88c6e0b664 Mon Sep 17 00:00:00 2001 From: willclarktech Date: Wed, 14 Apr 2021 16:48:49 +0200 Subject: [PATCH 5/5] Remove unnecessary Uint8Array conversions --- packages/cosmwasm-stargate/src/signingcosmwasmclient.ts | 2 +- packages/stargate/src/signingstargateclient.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts b/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts index d8451599..b6dd254b 100644 --- a/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts +++ b/packages/cosmwasm-stargate/src/signingcosmwasmclient.ts @@ -405,7 +405,7 @@ export class SigningCosmWasmClient extends CosmWasmClient { memo = "", ): Promise { const txRaw = await this.sign(signerAddress, messages, fee, memo); - const txBytes = Uint8Array.from(TxRaw.encode(txRaw).finish()); + const txBytes = TxRaw.encode(txRaw).finish(); return this.broadcastTx(txBytes); } diff --git a/packages/stargate/src/signingstargateclient.ts b/packages/stargate/src/signingstargateclient.ts index 31c81f24..6267ddc6 100644 --- a/packages/stargate/src/signingstargateclient.ts +++ b/packages/stargate/src/signingstargateclient.ts @@ -297,7 +297,7 @@ export class SigningStargateClient extends StargateClient { memo = "", ): Promise { const txRaw = await this.sign(signerAddress, messages, fee, memo); - const txBytes = Uint8Array.from(TxRaw.encode(txRaw).finish()); + const txBytes = TxRaw.encode(txRaw).finish(); return this.broadcastTx(txBytes); }