From ed5f1d9524111066494ea7bbc133f1bf09b88d96 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Wed, 29 Jun 2022 08:52:00 +0200 Subject: [PATCH] Fix decoding of events with no attributes --- CHANGELOG.md | 2 ++ .../tendermint34/adaptor/responses.spec.ts | 30 +++++++++++++++++-- .../src/tendermint34/adaptor/responses.ts | 7 +++-- .../tendermint35/adaptor/responses.spec.ts | 28 ++++++++++++++++- .../src/tendermint35/adaptor/responses.ts | 7 +++-- 5 files changed, 65 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69dfbbce..41e0d930 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,10 +27,12 @@ and this project adheres to - @cosmjs/math: Check for negative values in `Decimal.fromAtomics` ([#1188]). - @cosmjs/tendermint-rpc: Fix `key` and `value` type in `RpcAbciQueryResponse` to also include the `null` option. +- @cosmjs/tendermint-rpc: Fix decoding events without attributes ([#1198]). [#1170]: https://github.com/cosmos/cosmjs/issues/1170 [#1177]: https://github.com/cosmos/cosmjs/issues/1177 [#1188]: https://github.com/cosmos/cosmjs/pull/1188 +[#1198]: https://github.com/cosmos/cosmjs/pull/1198 ### Changed diff --git a/packages/tendermint-rpc/src/tendermint34/adaptor/responses.spec.ts b/packages/tendermint-rpc/src/tendermint34/adaptor/responses.spec.ts index d00a3120..0ad26490 100644 --- a/packages/tendermint-rpc/src/tendermint34/adaptor/responses.spec.ts +++ b/packages/tendermint-rpc/src/tendermint34/adaptor/responses.spec.ts @@ -1,9 +1,35 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { fromBase64, fromHex } from "@cosmjs/encoding"; +import { fromBase64, fromHex, toUtf8 } from "@cosmjs/encoding"; -import { decodeValidatorGenesis, decodeValidatorInfo, decodeValidatorUpdate } from "./responses"; +import { decodeEvent, decodeValidatorGenesis, decodeValidatorInfo, decodeValidatorUpdate } from "./responses"; describe("Adaptor Responses", () => { + describe("decodeEvent", () => { + it("works with attributes", () => { + // from https://rpc.mainnet-1.tgrade.confio.run/tx?hash=0x2C44715748022DB2FB5F40105383719BFCFCEE51DBC02FF4088BE3F5924CD7BF + const event = decodeEvent({ + type: "coin_spent", + attributes: [ + { key: "c3BlbmRlcg==", value: "dGdyYWRlMWpzN2V6cm01NWZxZ3h1M3A2MmQ5eG42cGF0amt1Mno3bmU1ZHZn" }, + { key: "YW1vdW50", value: "NjAwMDAwMDAwMHV0Z2Q=" }, + ], + }); + expect(event.type).toEqual("coin_spent"); + expect(event.attributes).toEqual([ + { key: toUtf8("spender"), value: toUtf8("tgrade1js7ezrm55fqgxu3p62d9xn6patjku2z7ne5dvg") }, + { key: toUtf8("amount"), value: toUtf8("6000000000utgd") }, + ]); + }); + + it("works with no attribute", () => { + const event = decodeEvent({ + type: "cosmos.module.EmittedEvent", + }); + expect(event.type).toEqual("cosmos.module.EmittedEvent"); + expect(event.attributes).toEqual([]); + }); + }); + describe("decodeValidatorGenesis", () => { it("works for genesis format", () => { // from https://raw.githubusercontent.com/cosmos/mainnet/master/genesis.json diff --git a/packages/tendermint-rpc/src/tendermint34/adaptor/responses.ts b/packages/tendermint-rpc/src/tendermint34/adaptor/responses.ts index 93d3214f..85613baf 100644 --- a/packages/tendermint-rpc/src/tendermint34/adaptor/responses.ts +++ b/packages/tendermint-rpc/src/tendermint34/adaptor/responses.ts @@ -126,13 +126,14 @@ function decodeAttributes(attributes: readonly RpcAttribute[]): responses.Attrib interface RpcEvent { readonly type: string; - readonly attributes: readonly RpcAttribute[]; + /** Can be omitted (see https://github.com/cosmos/cosmjs/pull/1198) */ + readonly attributes?: readonly RpcAttribute[]; } -function decodeEvent(event: RpcEvent): responses.Event { +export function decodeEvent(event: RpcEvent): responses.Event { return { type: event.type, - attributes: decodeAttributes(event.attributes), + attributes: event.attributes ? decodeAttributes(event.attributes) : [], }; } diff --git a/packages/tendermint-rpc/src/tendermint35/adaptor/responses.spec.ts b/packages/tendermint-rpc/src/tendermint35/adaptor/responses.spec.ts index d00a3120..35e86679 100644 --- a/packages/tendermint-rpc/src/tendermint35/adaptor/responses.spec.ts +++ b/packages/tendermint-rpc/src/tendermint35/adaptor/responses.spec.ts @@ -1,9 +1,35 @@ /* eslint-disable @typescript-eslint/naming-convention */ import { fromBase64, fromHex } from "@cosmjs/encoding"; -import { decodeValidatorGenesis, decodeValidatorInfo, decodeValidatorUpdate } from "./responses"; +import { decodeEvent, decodeValidatorGenesis, decodeValidatorInfo, decodeValidatorUpdate } from "./responses"; describe("Adaptor Responses", () => { + describe("decodeEvent", () => { + it("works with attributes", () => { + // from https://rpc.mainnet-1.tgrade.confio.run/tx?hash=0x2C44715748022DB2FB5F40105383719BFCFCEE51DBC02FF4088BE3F5924CD7BF + const event = decodeEvent({ + type: "coin_spent", + attributes: [ + { key: "foo", value: "123" }, + { key: "bar", value: "456" }, + ], + }); + expect(event.type).toEqual("coin_spent"); + expect(event.attributes).toEqual([ + { key: "foo", value: "123" }, + { key: "bar", value: "456" }, + ]); + }); + + it("works with no attribute", () => { + const event = decodeEvent({ + type: "cosmos.module.EmittedEvent", + }); + expect(event.type).toEqual("cosmos.module.EmittedEvent"); + expect(event.attributes).toEqual([]); + }); + }); + describe("decodeValidatorGenesis", () => { it("works for genesis format", () => { // from https://raw.githubusercontent.com/cosmos/mainnet/master/genesis.json diff --git a/packages/tendermint-rpc/src/tendermint35/adaptor/responses.ts b/packages/tendermint-rpc/src/tendermint35/adaptor/responses.ts index dcc07ead..0aab89cc 100644 --- a/packages/tendermint-rpc/src/tendermint35/adaptor/responses.ts +++ b/packages/tendermint-rpc/src/tendermint35/adaptor/responses.ts @@ -127,13 +127,14 @@ function decodeAttributes(attributes: readonly RpcEventAttribute[]): responses.E interface RpcEvent { readonly type: string; - readonly attributes: readonly RpcEventAttribute[]; + /** Can be omitted (see https://github.com/cosmos/cosmjs/pull/1198) */ + readonly attributes?: readonly RpcEventAttribute[]; } -function decodeEvent(event: RpcEvent): responses.Event { +export function decodeEvent(event: RpcEvent): responses.Event { return { type: event.type, - attributes: decodeAttributes(event.attributes), + attributes: event.attributes ? decodeAttributes(event.attributes) : [], }; }