diff --git a/packages/stargate/src/encodeobjects.ts b/packages/stargate/src/encodeobjects.ts new file mode 100644 index 00000000..9978d858 --- /dev/null +++ b/packages/stargate/src/encodeobjects.ts @@ -0,0 +1,62 @@ +import { EncodeObject } from "@cosmjs/proto-signing"; + +import { MsgSend } from "./codec/cosmos/bank/v1beta1/tx"; +import { MsgWithdrawDelegatorReward } from "./codec/cosmos/distribution/v1beta1/tx"; +import { MsgDelegate, MsgUndelegate } from "./codec/cosmos/staking/v1beta1/tx"; +import { MsgTransfer } from "./codec/ibc/applications/transfer/v1/tx"; + +export interface MsgSendEncodeObject extends EncodeObject { + readonly typeUrl: "/cosmos.bank.v1beta1.MsgSend"; + readonly value: Partial; +} + +export function isMsgSendEncodeObject(encodeObject: EncodeObject): encodeObject is MsgSendEncodeObject { + return (encodeObject as MsgSendEncodeObject).typeUrl === "/cosmos.bank.v1beta1.MsgSend"; +} + +export interface MsgDelegateEncodeObject extends EncodeObject { + readonly typeUrl: "/cosmos.staking.v1beta1.MsgDelegate"; + readonly value: Partial; +} + +export function isMsgDelegateEncodeObject( + encodeObject: EncodeObject, +): encodeObject is MsgDelegateEncodeObject { + return (encodeObject as MsgDelegateEncodeObject).typeUrl === "/cosmos.staking.v1beta1.MsgDelegate"; +} + +export interface MsgUndelegateEncodeObject extends EncodeObject { + readonly typeUrl: "/cosmos.staking.v1beta1.MsgUndelegate"; + readonly value: Partial; +} + +export function isMsgUndelegateEncodeObject( + encodeObject: EncodeObject, +): encodeObject is MsgUndelegateEncodeObject { + return (encodeObject as MsgUndelegateEncodeObject).typeUrl === "/cosmos.staking.v1beta1.MsgUndelegate"; +} + +export interface MsgWithdrawDelegatorRewardEncodeObject extends EncodeObject { + readonly typeUrl: "/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward"; + readonly value: Partial; +} + +export function isMsgWithdrawDelegatorRewardEncodeObject( + encodeObject: EncodeObject, +): encodeObject is MsgWithdrawDelegatorRewardEncodeObject { + return ( + (encodeObject as MsgWithdrawDelegatorRewardEncodeObject).typeUrl === + "/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward" + ); +} + +export interface MsgTransferEncodeObject extends EncodeObject { + readonly typeUrl: "/ibc.applications.transfer.v1.MsgTransfer"; + readonly value: Partial; +} + +export function isMsgTransferEncodeObject( + encodeObject: EncodeObject, +): encodeObject is MsgTransferEncodeObject { + return (encodeObject as MsgTransferEncodeObject).typeUrl === "/ibc.applications.transfer.v1.MsgTransfer"; +} diff --git a/packages/stargate/src/index.ts b/packages/stargate/src/index.ts index 81ef92da..4f3a074f 100644 --- a/packages/stargate/src/index.ts +++ b/packages/stargate/src/index.ts @@ -39,6 +39,18 @@ export { isAminoMsgWithdrawValidatorCommission, } from "./aminomsgs"; export { AminoConverter, AminoTypes } from "./aminotypes"; +export { + isMsgDelegateEncodeObject, + isMsgSendEncodeObject, + isMsgTransferEncodeObject, + isMsgUndelegateEncodeObject, + isMsgWithdrawDelegatorRewardEncodeObject, + MsgDelegateEncodeObject, + MsgSendEncodeObject, + MsgTransferEncodeObject, + MsgUndelegateEncodeObject, + MsgWithdrawDelegatorRewardEncodeObject, +} from "./encodeobjects"; export { buildFeeTable, FeeTable, GasLimits, GasPrice } from "./fee"; export * as logs from "./logs"; export { makeMultisignedTx } from "./multisignature"; diff --git a/packages/stargate/src/multisignature.spec.ts b/packages/stargate/src/multisignature.spec.ts index 319ee75c..5f65a302 100644 --- a/packages/stargate/src/multisignature.spec.ts +++ b/packages/stargate/src/multisignature.spec.ts @@ -10,6 +10,7 @@ import { assert } from "@cosmjs/utils"; import { MsgSend } from "./codec/cosmos/bank/v1beta1/tx"; import { TxRaw } from "./codec/cosmos/tx/v1beta1/tx"; +import { MsgSendEncodeObject } from "./encodeobjects"; import { makeCompactBitArray, makeMultisignedTx } from "./multisignature"; import { SignerData, SigningStargateClient } from "./signingstargateclient"; import { assertIsBroadcastTxSuccess, StargateClient } from "./stargateclient"; @@ -185,7 +186,7 @@ describe("multisignature", () => { toAddress: "cosmos19rvl6ja9h0erq9dc2xxfdzypc739ej8k5esnhg", amount: coins(1234, "ucosm"), }; - const msg = { + const msg: MsgSendEncodeObject = { typeUrl: "/cosmos.bank.v1beta1.MsgSend", value: msgSend, }; diff --git a/packages/stargate/src/queries/distribution.spec.ts b/packages/stargate/src/queries/distribution.spec.ts index 05b300c3..244f67fd 100644 --- a/packages/stargate/src/queries/distribution.spec.ts +++ b/packages/stargate/src/queries/distribution.spec.ts @@ -4,6 +4,7 @@ import { Tendermint34Client } from "@cosmjs/tendermint-rpc"; import { sleep } from "@cosmjs/utils"; import { MsgDelegate } from "../codec/cosmos/staking/v1beta1/tx"; +import { MsgDelegateEncodeObject } from "../encodeobjects"; import { SigningStargateClient } from "../signingstargateclient"; import { assertIsBroadcastTxSuccess } from "../stargateclient"; import { faucet, pendingWithoutSimapp, simapp, simappEnabled, validator } from "../testutils.spec"; @@ -33,7 +34,7 @@ describe("DistributionExtension", () => { validatorAddress: validator.validatorAddress, amount: coin(25000, "ustake"), }; - const msgAny = { + const msgAny: MsgDelegateEncodeObject = { typeUrl: "/cosmos.staking.v1beta1.MsgDelegate", value: msg, }; diff --git a/packages/stargate/src/queries/staking.spec.ts b/packages/stargate/src/queries/staking.spec.ts index 212913c4..8abdf3f0 100644 --- a/packages/stargate/src/queries/staking.spec.ts +++ b/packages/stargate/src/queries/staking.spec.ts @@ -4,6 +4,7 @@ import { Tendermint34Client } from "@cosmjs/tendermint-rpc"; import { sleep } from "@cosmjs/utils"; import { MsgDelegate, MsgUndelegate } from "../codec/cosmos/staking/v1beta1/tx"; +import { MsgDelegateEncodeObject, MsgUndelegateEncodeObject } from "../encodeobjects"; import { SigningStargateClient } from "../signingstargateclient"; import { assertIsBroadcastTxSuccess } from "../stargateclient"; import { faucet, pendingWithoutSimapp, simapp, simappEnabled, validator } from "../testutils.spec"; @@ -34,7 +35,7 @@ describe("StakingExtension", () => { validatorAddress: validator.validatorAddress, amount: coin(25000, "ustake"), }; - const msgAny = { + const msgAny: MsgDelegateEncodeObject = { typeUrl: "/cosmos.staking.v1beta1.MsgDelegate", value: msg, }; @@ -48,7 +49,7 @@ describe("StakingExtension", () => { validatorAddress: validator.validatorAddress, amount: coin(100, "ustake"), }; - const msgAny = { + const msgAny: MsgUndelegateEncodeObject = { typeUrl: "/cosmos.staking.v1beta1.MsgUndelegate", value: msg, }; diff --git a/packages/stargate/src/signingstargateclient.spec.ts b/packages/stargate/src/signingstargateclient.spec.ts index 45f42772..acf5591e 100644 --- a/packages/stargate/src/signingstargateclient.spec.ts +++ b/packages/stargate/src/signingstargateclient.spec.ts @@ -10,6 +10,7 @@ import { MsgSend } from "./codec/cosmos/bank/v1beta1/tx"; import { Coin } from "./codec/cosmos/base/v1beta1/coin"; import { DeepPartial, MsgDelegate } from "./codec/cosmos/staking/v1beta1/tx"; import { AuthInfo, Tx, TxBody, TxRaw } from "./codec/cosmos/tx/v1beta1/tx"; +import { MsgDelegateEncodeObject, MsgSendEncodeObject } from "./encodeobjects"; import { GasPrice } from "./fee"; import { PrivateSigningStargateClient, SigningStargateClient } from "./signingstargateclient"; import { assertIsBroadcastTxSuccess } from "./stargateclient"; @@ -331,7 +332,7 @@ describe("SigningStargateClient", () => { validatorAddress: validator.validatorAddress, amount: coin(1234, "ustake"), }); - const msgAny = { + const msgAny: MsgDelegateEncodeObject = { typeUrl: "/cosmos.staking.v1beta1.MsgDelegate", value: msg, }; @@ -354,7 +355,7 @@ describe("SigningStargateClient", () => { validatorAddress: validator.validatorAddress, amount: coin(1234, "ustake"), }); - const msgAny = { + const msgAny: MsgDelegateEncodeObject = { typeUrl: "/cosmos.staking.v1beta1.MsgDelegate", value: msg, }; @@ -389,7 +390,7 @@ describe("SigningStargateClient", () => { toAddress: makeRandomAddress(), amount: coins(1234, "ucosm"), }; - const msgAny = { + const msgAny: MsgSendEncodeObject = { typeUrl: "/cosmos.bank.v1beta1.MsgSend", value: msgSend, }; @@ -412,7 +413,7 @@ describe("SigningStargateClient", () => { validatorAddress: validator.validatorAddress, amount: coin(1234, "ustake"), }; - const msgAny = { + const msgAny: MsgDelegateEncodeObject = { typeUrl: "/cosmos.staking.v1beta1.MsgDelegate", value: msgDelegate, }; @@ -551,7 +552,7 @@ describe("SigningStargateClient", () => { validatorAddress: validator.validatorAddress, amount: coin(1234, "ustake"), }; - const msgAny = { + const msgAny: MsgDelegateEncodeObject = { typeUrl: "/cosmos.staking.v1beta1.MsgDelegate", value: msg, }; @@ -588,7 +589,7 @@ describe("SigningStargateClient", () => { validatorAddress: validator.validatorAddress, amount: coin(1234, "ustake"), }); - const msgAny = { + const msgAny: MsgDelegateEncodeObject = { typeUrl: "/cosmos.staking.v1beta1.MsgDelegate", value: msg, }; @@ -614,7 +615,7 @@ describe("SigningStargateClient", () => { validatorAddress: validator.validatorAddress, amount: coin(1234, "ustake"), }); - const msgAny = { + const msgAny: MsgDelegateEncodeObject = { typeUrl: "/cosmos.staking.v1beta1.MsgDelegate", value: msg, }; @@ -649,7 +650,7 @@ describe("SigningStargateClient", () => { toAddress: makeRandomAddress(), amount: coins(1234, "ucosm"), }; - const msgAny = { + const msgAny: MsgSendEncodeObject = { typeUrl: "/cosmos.bank.v1beta1.MsgSend", value: msgSend, }; @@ -675,7 +676,7 @@ describe("SigningStargateClient", () => { validatorAddress: validator.validatorAddress, amount: coin(1234, "ustake"), }; - const msgAny = { + const msgAny: MsgDelegateEncodeObject = { typeUrl: "/cosmos.staking.v1beta1.MsgDelegate", value: msgDelegate, }; @@ -820,7 +821,7 @@ describe("SigningStargateClient", () => { validatorAddress: validator.validatorAddress, amount: coin(1234, "ustake"), }; - const msgAny = { + const msgAny: MsgDelegateEncodeObject = { typeUrl: "/cosmos.staking.v1beta1.MsgDelegate", value: msg, }; diff --git a/packages/stargate/src/signingstargateclient.ts b/packages/stargate/src/signingstargateclient.ts index 6267ddc6..452cd065 100644 --- a/packages/stargate/src/signingstargateclient.ts +++ b/packages/stargate/src/signingstargateclient.ts @@ -10,6 +10,7 @@ import { makeSignDoc, OfflineSigner, Registry, + TxBodyEncodeObject, } from "@cosmjs/proto-signing"; import { Tendermint34Client } from "@cosmjs/tendermint-rpc"; import { assert } from "@cosmjs/utils"; @@ -59,6 +60,13 @@ import { MsgConnectionOpenInit, MsgConnectionOpenTry, } from "./codec/ibc/core/connection/v1/tx"; +import { + MsgDelegateEncodeObject, + MsgSendEncodeObject, + MsgTransferEncodeObject, + MsgUndelegateEncodeObject, + MsgWithdrawDelegatorRewardEncodeObject, +} from "./encodeobjects"; import { buildFeeTable, FeeTable, GasLimits, GasPrice } from "./fee"; import { BroadcastTxResponse, StargateClient } from "./stargateclient"; @@ -201,12 +209,12 @@ export class SigningStargateClient extends StargateClient { transferAmount: readonly Coin[], memo = "", ): Promise { - const sendMsg = { + const sendMsg: MsgSendEncodeObject = { typeUrl: "/cosmos.bank.v1beta1.MsgSend", value: { fromAddress: senderAddress, toAddress: recipientAddress, - amount: transferAmount, + amount: [...transferAmount], }, }; return this.signAndBroadcast(senderAddress, [sendMsg], this.fees.send, memo); @@ -218,7 +226,7 @@ export class SigningStargateClient extends StargateClient { amount: Coin, memo = "", ): Promise { - const delegateMsg = { + const delegateMsg: MsgDelegateEncodeObject = { typeUrl: "/cosmos.staking.v1beta1.MsgDelegate", value: MsgDelegate.fromPartial({ delegatorAddress: delegatorAddress, @@ -235,7 +243,7 @@ export class SigningStargateClient extends StargateClient { amount: Coin, memo = "", ): Promise { - const undelegateMsg = { + const undelegateMsg: MsgUndelegateEncodeObject = { typeUrl: "/cosmos.staking.v1beta1.MsgUndelegate", value: MsgUndelegate.fromPartial({ delegatorAddress: delegatorAddress, @@ -251,7 +259,7 @@ export class SigningStargateClient extends StargateClient { validatorAddress: string, memo = "", ): Promise { - const withdrawMsg = { + const withdrawMsg: MsgWithdrawDelegatorRewardEncodeObject = { typeUrl: "/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward", value: MsgWithdrawDelegatorReward.fromPartial({ delegatorAddress: delegatorAddress, @@ -275,7 +283,7 @@ export class SigningStargateClient extends StargateClient { const timeoutTimestampNanoseconds = timeoutTimestamp ? Long.fromNumber(timeoutTimestamp).multiply(1_000_000_000) : undefined; - const transferMsg = { + const transferMsg: MsgTransferEncodeObject = { typeUrl: "/ibc.applications.transfer.v1.MsgTransfer", value: MsgTransfer.fromPartial({ sourcePort: sourcePort, @@ -359,10 +367,11 @@ export class SigningStargateClient extends StargateClient { messages: signed.msgs.map((msg) => this.aminoTypes.fromAmino(msg)), memo: signed.memo, }; - const signedTxBodyBytes = this.registry.encode({ + const signedTxBodyEncodeObject: TxBodyEncodeObject = { typeUrl: "/cosmos.tx.v1beta1.TxBody", value: signedTxBody, - }); + }; + const signedTxBodyBytes = this.registry.encode(signedTxBodyEncodeObject); const signedGasLimit = Int53.fromString(signed.fee.gas).toNumber(); const signedSequence = Int53.fromString(signed.sequence).toNumber(); const signedAuthInfoBytes = makeAuthInfoBytes( @@ -394,14 +403,14 @@ export class SigningStargateClient extends StargateClient { 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({ + const txBodyEncodeObject: TxBodyEncodeObject = { typeUrl: "/cosmos.tx.v1beta1.TxBody", - value: txBody, - }); + value: { + messages: messages, + memo: memo, + }, + }; + const txBodyBytes = this.registry.encode(txBodyEncodeObject); const gasLimit = Int53.fromString(fee.gas).toNumber(); const authInfoBytes = makeAuthInfoBytes([pubkey], fee.amount, gasLimit, sequence); const signDoc = makeSignDoc(txBodyBytes, authInfoBytes, chainId, accountNumber); diff --git a/packages/stargate/src/stargateclient.searchtx.spec.ts b/packages/stargate/src/stargateclient.searchtx.spec.ts index bc4da931..ba684c0d 100644 --- a/packages/stargate/src/stargateclient.searchtx.spec.ts +++ b/packages/stargate/src/stargateclient.searchtx.spec.ts @@ -6,11 +6,13 @@ import { makeAuthInfoBytes, makeSignDoc, Registry, + TxBodyEncodeObject, } from "@cosmjs/proto-signing"; import { assert, sleep } from "@cosmjs/utils"; import { Coin } from "./codec/cosmos/base/v1beta1/coin"; import { Tx, TxRaw } from "./codec/cosmos/tx/v1beta1/tx"; +import { isMsgSendEncodeObject } from "./encodeobjects"; import { BroadcastTxResponse, isBroadcastTxFailure, @@ -50,7 +52,7 @@ async function sendTokens( type: "tendermint/PubKeySecp256k1", value: toBase64(pubkeyBytes), }); - const txBodyFields = { + const txBodyFields: TxBodyEncodeObject = { typeUrl: "/cosmos.tx.v1beta1.TxBody", value: { messages: [ @@ -230,9 +232,9 @@ describe("StargateClient.getTx and .searchTx", () => { // Check basic structure of all results for (const result of results) { const tx = Tx.decode(result.tx); - const filteredMsgs = tx.body!.messages.filter(({ typeUrl: typeUrl, value }) => { - if (typeUrl !== "/cosmos.bank.v1beta1.MsgSend") return false; - const decoded = registry.decode({ typeUrl: typeUrl, value: value }); + const filteredMsgs = tx.body!.messages.filter((msg) => { + if (!isMsgSendEncodeObject(msg)) return false; + const decoded = registry.decode(msg); return decoded.fromAddress === sendSuccessful?.sender; }); expect(filteredMsgs.length).toBeGreaterThanOrEqual(1); @@ -258,9 +260,9 @@ describe("StargateClient.getTx and .searchTx", () => { // Check basic structure of all results for (const result of results) { const tx = Tx.decode(result.tx); - const filteredMsgs = tx.body!.messages.filter(({ typeUrl: typeUrl, value }) => { - if (typeUrl !== "/cosmos.bank.v1beta1.MsgSend") return false; - const decoded = registry.decode({ typeUrl: typeUrl, value: value }); + const filteredMsgs = tx.body!.messages.filter((msg) => { + if (!isMsgSendEncodeObject(msg)) return false; + const decoded = registry.decode(msg); return decoded.toAddress === sendSuccessful?.recipient; }); expect(filteredMsgs.length).toBeGreaterThanOrEqual(1); @@ -344,9 +346,9 @@ describe("StargateClient.getTx and .searchTx", () => { // Check basic structure of all results for (const result of results) { const tx = Tx.decode(result.tx); - const { typeUrl, value } = fromOneElementArray(tx.body!.messages); - expect(typeUrl).toEqual("/cosmos.bank.v1beta1.MsgSend"); - const decoded = registry.decode({ typeUrl: typeUrl, value: value }); + const msg = fromOneElementArray(tx.body!.messages); + expect(msg.typeUrl).toEqual("/cosmos.bank.v1beta1.MsgSend"); + const decoded = registry.decode(msg); expect(decoded.toAddress).toEqual(sendSuccessful.recipient); } diff --git a/packages/stargate/src/stargateclient.spec.ts b/packages/stargate/src/stargateclient.spec.ts index 9565df05..c12f1199 100644 --- a/packages/stargate/src/stargateclient.spec.ts +++ b/packages/stargate/src/stargateclient.spec.ts @@ -6,6 +6,7 @@ import { makeAuthInfoBytes, makeSignDoc, Registry, + TxBodyEncodeObject, } from "@cosmjs/proto-signing"; import { assert, sleep } from "@cosmjs/utils"; import { ReadonlyDate } from "readonly-date"; @@ -289,7 +290,7 @@ describe("StargateClient", () => { value: toBase64(pubkeyBytes), }); const registry = new Registry(); - const txBodyFields = { + const txBodyFields: TxBodyEncodeObject = { typeUrl: "/cosmos.tx.v1beta1.TxBody", value: { messages: [ @@ -350,7 +351,7 @@ describe("StargateClient", () => { value: toBase64(pubkeyBytes), }); const registry = new Registry(); - const txBodyFields = { + const txBodyFields: TxBodyEncodeObject = { typeUrl: "/cosmos.tx.v1beta1.TxBody", value: { messages: [