diff --git a/CHANGELOG.md b/CHANGELOG.md index d8bf757a..bb059965 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,10 @@ and this project adheres to ### Added - @cosmjs/cosmwasm-stargate: Add `SigningCosmWasmClient.instantiate2` ([#1407]). +- @cosmjs/stargate: `IndexedTx` and `DeliverTxResponse` now have a + `msgResponses` field ([#1305]). +[#1305]: https://github.com/cosmos/cosmjs/issues/1305 [#1407]: https://github.com/cosmos/cosmjs/pull/1407 ### Changed diff --git a/packages/cosmwasm-stargate/src/cosmwasmclient.ts b/packages/cosmwasm-stargate/src/cosmwasmclient.ts index c3c73c6a..9864ce66 100644 --- a/packages/cosmwasm-stargate/src/cosmwasmclient.ts +++ b/packages/cosmwasm-stargate/src/cosmwasmclient.ts @@ -29,6 +29,7 @@ import { toRfc3339WithNanoseconds, } from "@cosmjs/tendermint-rpc"; import { assert, sleep } from "@cosmjs/utils"; +import { TxMsgData } from "cosmjs-types/cosmos/base/abci/v1beta1/abci"; import { CodeInfoResponse, QueryCodesResponse, @@ -287,6 +288,7 @@ export class CosmWasmClient { rawLog: result.rawLog, transactionHash: txId, events: result.events, + msgResponses: result.msgResponses, gasUsed: result.gasUsed, gasWanted: result.gasWanted, } @@ -461,7 +463,8 @@ export class CosmWasmClient { private async txsQuery(query: string): Promise { const results = await this.forceGetTmClient().txSearchAll({ query: query }); - return results.txs.map((tx) => { + return results.txs.map((tx): IndexedTx => { + const txMsgData = TxMsgData.decode(tx.result.data ?? new Uint8Array()); return { height: tx.height, txIndex: tx.index, @@ -470,6 +473,7 @@ export class CosmWasmClient { events: tx.result.events.map(fromTendermintEvent), rawLog: tx.result.log || "", tx: tx.tx, + msgResponses: txMsgData.msgResponses, gasUsed: tx.result.gasUsed, gasWanted: tx.result.gasWanted, }; diff --git a/packages/stargate/src/stargateclient.searchtx.spec.ts b/packages/stargate/src/stargateclient.searchtx.spec.ts index 8062ba5b..57803107 100644 --- a/packages/stargate/src/stargateclient.searchtx.spec.ts +++ b/packages/stargate/src/stargateclient.searchtx.spec.ts @@ -10,6 +10,7 @@ import { TxBodyEncodeObject, } from "@cosmjs/proto-signing"; import { assert, sleep } from "@cosmjs/utils"; +import { MsgSendResponse } from "cosmjs-types/cosmos/bank/v1beta1/tx"; import { Coin } from "cosmjs-types/cosmos/base/v1beta1/coin"; import { TxRaw } from "cosmjs-types/cosmos/tx/v1beta1/tx"; @@ -22,6 +23,7 @@ import { makeRandomAddress, pendingWithoutSimapp, simapp, + simapp44Enabled, simappEnabled, } from "./testutils.spec"; @@ -156,6 +158,7 @@ describe("StargateClient.getTx and .searchTx", () => { assert(sendSuccessful, "value must be set in beforeAll()"); const client = await StargateClient.connect(simapp.tendermintUrl); const result = await client.getTx(sendSuccessful.hash); + assert(result); expect(result).toEqual( jasmine.objectContaining({ height: sendSuccessful.height, @@ -164,6 +167,14 @@ describe("StargateClient.getTx and .searchTx", () => { tx: sendSuccessful.tx, }), ); + + // works on SDK 0.46+ + if (!simapp44Enabled()) { + expect(result.msgResponses.length).toEqual(1); + expect(result.msgResponses[0].typeUrl).toEqual("/cosmos.bank.v1beta1.MsgSendResponse"); + const _response = MsgSendResponse.decode(result.msgResponses[0].value); + // MsgSendResponse has no fields to check 🤷‍♂️ + } }); it("can get unsuccessful tx by ID", async () => { @@ -171,6 +182,7 @@ describe("StargateClient.getTx and .searchTx", () => { assert(sendUnsuccessful, "value must be set in beforeAll()"); const client = await StargateClient.connect(simapp.tendermintUrl); const result = await client.getTx(sendUnsuccessful.hash); + assert(result); expect(result).toEqual( jasmine.objectContaining({ height: sendUnsuccessful.height, @@ -179,6 +191,12 @@ describe("StargateClient.getTx and .searchTx", () => { tx: sendUnsuccessful.tx, }), ); + + // works on SDK 0.46+ + if (!simapp44Enabled()) { + // unsuccessful tx should not have responses + expect(result.msgResponses.length).toEqual(0); + } }); it("can get by ID (non existent)", async () => { @@ -205,6 +223,14 @@ describe("StargateClient.getTx and .searchTx", () => { tx: sendSuccessful.tx, }), ); + + // works on SDK 0.46+ + if (!simapp44Enabled()) { + expect(result[0].msgResponses.length).toEqual(1); + expect(result[0].msgResponses[0].typeUrl).toEqual("/cosmos.bank.v1beta1.MsgSendResponse"); + const _response = MsgSendResponse.decode(result[0].msgResponses[0].value); + // MsgSendResponse has no fields to check 🤷‍♂️ + } }); it("can search unsuccessful tx by height", async () => { diff --git a/packages/stargate/src/stargateclient.spec.ts b/packages/stargate/src/stargateclient.spec.ts index e7d28ef2..c7f0df94 100644 --- a/packages/stargate/src/stargateclient.spec.ts +++ b/packages/stargate/src/stargateclient.spec.ts @@ -45,6 +45,7 @@ const resultFailure: DeliverTxResponse = { "failed to execute message; message index: 0: 1855527000ufct is smaller than 20000000000000000000000ufct: insufficient funds", transactionHash: "FDC4FB701AABD465935F7D04AE490D1EF5F2BD4B227601C4E98B57EB077D9B7D", events: [], + msgResponses: [], gasUsed: 54396, gasWanted: 200000, }; @@ -56,6 +57,7 @@ const resultSuccess: DeliverTxResponse = { '[{"events":[{"type":"message","attributes":[{"key":"action","value":"send"},{"key":"sender","value":"firma1trqyle9m2nvyafc2n25frkpwed2504y6avgfzr"},{"key":"module","value":"bank"}]},{"type":"transfer","attributes":[{"key":"recipient","value":"firma12er8ls2sf5zess3jgjxz59xat9xtf8hz0hk6n4"},{"key":"sender","value":"firma1trqyle9m2nvyafc2n25frkpwed2504y6avgfzr"},{"key":"amount","value":"2000000ufct"}]}]}]', transactionHash: "C0B416CA868C55C2B8C1BBB8F3CFA233854F13A5CB15D3E9599F50CAF7B3D161", events: [], + msgResponses: [], gasUsed: 61556, gasWanted: 200000, }; diff --git a/packages/stargate/src/stargateclient.ts b/packages/stargate/src/stargateclient.ts index 7f437573..7b21cbe0 100644 --- a/packages/stargate/src/stargateclient.ts +++ b/packages/stargate/src/stargateclient.ts @@ -10,7 +10,7 @@ import { toRfc3339WithNanoseconds, } from "@cosmjs/tendermint-rpc"; import { assert, sleep } from "@cosmjs/utils"; -import { MsgData } from "cosmjs-types/cosmos/base/abci/v1beta1/abci"; +import { MsgData, TxMsgData } from "cosmjs-types/cosmos/base/abci/v1beta1/abci"; import { Coin } from "cosmjs-types/cosmos/base/v1beta1/coin"; import { QueryDelegatorDelegationsResponse } from "cosmjs-types/cosmos/staking/v1beta1/query"; import { DelegationResponse } from "cosmjs-types/cosmos/staking/v1beta1/staking"; @@ -91,6 +91,12 @@ export interface IndexedTx { * Use `decodeTxRaw` from @cosmjs/proto-signing to decode this. */ readonly tx: Uint8Array; + /** + * The message responses of the [TxMsgData](https://github.com/cosmos/cosmos-sdk/blob/v0.46.3/proto/cosmos/base/abci/v1beta1/abci.proto#L128-L140) + * as `Any`s. + * This field is an empty list for chains running Cosmos SDK < 0.46. + */ + readonly msgResponses: Array<{ readonly typeUrl: string; readonly value: Uint8Array }>; readonly gasUsed: number; readonly gasWanted: number; } @@ -120,7 +126,14 @@ export interface DeliverTxResponse { * field instead. */ readonly rawLog?: string; + /** @deprecated Use `msgResponses` instead. */ readonly data?: readonly MsgData[]; + /** + * The message responses of the [TxMsgData](https://github.com/cosmos/cosmos-sdk/blob/v0.46.3/proto/cosmos/base/abci/v1beta1/abci.proto#L128-L140) + * as `Any`s. + * This field is an empty list for chains running Cosmos SDK < 0.46. + */ + readonly msgResponses: Array<{ readonly typeUrl: string; readonly value: Uint8Array }>; readonly gasUsed: number; readonly gasWanted: number; } @@ -444,6 +457,7 @@ export class StargateClient { events: result.events, rawLog: result.rawLog, transactionHash: txId, + msgResponses: result.msgResponses, gasUsed: result.gasUsed, gasWanted: result.gasWanted, } @@ -473,7 +487,8 @@ export class StargateClient { private async txsQuery(query: string): Promise { const results = await this.forceGetTmClient().txSearchAll({ query: query }); - return results.txs.map((tx) => { + return results.txs.map((tx): IndexedTx => { + const txMsgData = TxMsgData.decode(tx.result.data ?? new Uint8Array()); return { height: tx.height, txIndex: tx.index, @@ -482,6 +497,7 @@ export class StargateClient { events: tx.result.events.map(fromTendermintEvent), rawLog: tx.result.log || "", tx: tx.tx, + msgResponses: txMsgData.msgResponses, gasUsed: tx.result.gasUsed, gasWanted: tx.result.gasWanted, };