From 726542ffdbf3f2ae5a2d67e631c391352b9bdf25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 3 Apr 2024 23:01:29 +0300 Subject: [PATCH] Find by first topic. Additional tests. --- .../resources.spec.ts | 69 +++++++++++++++++++ src/transactionsOutcomeParsers/resources.ts | 4 ++ .../transactionEventsParser.spec.ts | 65 ++++++++++++++++- .../transactionEventsParser.ts | 4 +- 4 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 src/transactionsOutcomeParsers/resources.spec.ts diff --git a/src/transactionsOutcomeParsers/resources.spec.ts b/src/transactionsOutcomeParsers/resources.spec.ts new file mode 100644 index 000000000..1d8fbd8ea --- /dev/null +++ b/src/transactionsOutcomeParsers/resources.spec.ts @@ -0,0 +1,69 @@ +import { assert } from "chai"; +import { + SmartContractResult, + TransactionEvent, + TransactionLogs, + TransactionOutcome, + findEventsByFirstTopic, + findEventsByIdentifier, +} from "./resources"; + +describe("test resources", () => { + it("finds events by identifier, by first topic", async function () { + const outcome = new TransactionOutcome({ + logs: new TransactionLogs({ + events: [ + new TransactionEvent({ + identifier: "foo", + topics: [Buffer.from("a")], + }), + ], + }), + smartContractResults: [ + new SmartContractResult({ + logs: new TransactionLogs({ + events: [ + new TransactionEvent({ + identifier: "foo", + topics: [Buffer.from("b")], + }), + new TransactionEvent({ + identifier: "bar", + topics: [Buffer.from("c")], + }), + ], + }), + }), + ], + }); + + const foundByIdentifierFoo = findEventsByIdentifier(outcome, "foo"); + const foundByIdentifierBar = findEventsByIdentifier(outcome, "bar"); + const foundByTopic = findEventsByFirstTopic(outcome, "b"); + + assert.deepEqual(foundByIdentifierFoo, [ + new TransactionEvent({ + identifier: "foo", + topics: [Buffer.from("a")], + }), + new TransactionEvent({ + identifier: "foo", + topics: [Buffer.from("b")], + }), + ]); + + assert.deepEqual(foundByIdentifierBar, [ + new TransactionEvent({ + identifier: "bar", + topics: [Buffer.from("c")], + }), + ]); + + assert.deepEqual(foundByTopic, [ + new TransactionEvent({ + identifier: "foo", + topics: [Buffer.from("b")], + }), + ]); + }); +}); diff --git a/src/transactionsOutcomeParsers/resources.ts b/src/transactionsOutcomeParsers/resources.ts index 93a4d1e5f..b30bd2f1c 100644 --- a/src/transactionsOutcomeParsers/resources.ts +++ b/src/transactionsOutcomeParsers/resources.ts @@ -83,6 +83,10 @@ export function findEventsByIdentifier(transactionOutcome: TransactionOutcome, i return findEventsByPredicate(transactionOutcome, (event) => event.identifier == identifier); } +export function findEventsByFirstTopic(transactionOutcome: TransactionOutcome, topic: string): TransactionEvent[] { + return findEventsByPredicate(transactionOutcome, (event) => event.topics[0]?.toString() == topic); +} + export function gatherAllEvents(transactionOutcome: TransactionOutcome): TransactionEvent[] { const allEvents = []; diff --git a/src/transactionsOutcomeParsers/transactionEventsParser.spec.ts b/src/transactionsOutcomeParsers/transactionEventsParser.spec.ts index d31e2ee81..9ed01c91c 100644 --- a/src/transactionsOutcomeParsers/transactionEventsParser.spec.ts +++ b/src/transactionsOutcomeParsers/transactionEventsParser.spec.ts @@ -13,7 +13,7 @@ import { Address } from "../address"; import { TransactionsConverter } from "../converters/transactionsConverter"; import { AbiRegistry } from "../smartcontracts"; import { loadAbiRegistry } from "../testutils"; -import { TransactionEvent, findEventsByIdentifier } from "./resources"; +import { TransactionEvent, findEventsByFirstTopic } from "./resources"; import { TransactionEventsParser } from "./transactionEventsParser"; describe("test transaction events parser", () => { @@ -39,7 +39,7 @@ describe("test transaction events parser", () => { ]); }); - it("parses events", async function () { + it("parses events (esdt-safe, deposit)", async function () { const parser = new TransactionEventsParser({ abi: await loadAbiRegistry("src/testdata/esdt-safe.abi.json"), }); @@ -69,7 +69,7 @@ describe("test transaction events parser", () => { }); const transactionOutcome = transactionsConverter.transactionOnNetworkToOutcome(transactionOnNetwork); - const events = findEventsByIdentifier(transactionOutcome, "deposit"); + const events = findEventsByFirstTopic(transactionOutcome, "deposit"); const parsed = parser.parseEvents({ events }); assert.deepEqual(parsed, [ @@ -92,6 +92,65 @@ describe("test transaction events parser", () => { ]); }); + it("parses events (multisig, startPerformAction)", async function () { + const parser = new TransactionEventsParser({ + abi: await loadAbiRegistry("src/testdata/multisig-full.abi.json"), + }); + + const transactionsConverter = new TransactionsConverter(); + const transactionOnNetwork = new TransactionOnNetwork({ + nonce: 7, + contractResults: new ContractResults([ + new ContractResultItem({ + nonce: 8, + data: "@6f6b", + }), + ]), + logs: new TransactionLogsOnNetwork({ + events: [ + new TransactionEventOnNetwork({ + identifier: "performAction", + topics: [new TransactionEventTopic("c3RhcnRQZXJmb3JtQWN0aW9u")], + dataPayload: new TransactionEventData( + Buffer.from( + "00000001000000000500000000000000000500d006f73c4221216fa679bc559005584c4f1160e569e1000000000000000003616464000000010000000107000000010139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "hex", + ), + ), + }), + ], + }), + }); + + const transactionOutcome = transactionsConverter.transactionOnNetworkToOutcome(transactionOnNetwork); + const events = findEventsByFirstTopic(transactionOutcome, "startPerformAction"); + const parsed = parser.parseEvents({ events }); + + assert.deepEqual(parsed, [ + { + data: { + action_id: new BigNumber("1"), + group_id: new BigNumber("0"), + action_data: { + name: "SendTransferExecuteEgld", + fields: [ + { + to: Address.fromBech32( + "erd1qqqqqqqqqqqqqpgq6qr0w0zzyysklfneh32eqp2cf383zc89d8sstnkl60", + ), + egld_amount: new BigNumber("0"), + opt_gas_limit: null, + endpoint_name: Buffer.from("add"), + arguments: [Buffer.from("07", "hex")], + }, + ], + }, + signers: [Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th")], + }, + }, + ]); + }); + it("cannot parse events, when definition is missing", async function () { const parser = new TransactionEventsParser({ abi: await loadAbiRegistry("src/testdata/esdt-safe.abi.json"), diff --git a/src/transactionsOutcomeParsers/transactionEventsParser.ts b/src/transactionsOutcomeParsers/transactionEventsParser.ts index 4288d8812..4d568e077 100644 --- a/src/transactionsOutcomeParsers/transactionEventsParser.ts +++ b/src/transactionsOutcomeParsers/transactionEventsParser.ts @@ -35,14 +35,14 @@ export class TransactionEventsParser { parseEvent(options: { event: TransactionEvent }): any { const topics = options.event.topics.map((topic) => Buffer.from(topic)); - const eventIdentifier = this.firstTopicIsIdentifier ? topics[0]?.toString() : options.event.identifier; + const abiIdentifier = this.firstTopicIsIdentifier ? topics[0]?.toString() : options.event.identifier; if (this.firstTopicIsIdentifier) { topics.shift(); } const dataItems = options.event.dataItems.map((dataItem) => Buffer.from(dataItem)); - const eventDefinition = this.abi.getEvent(eventIdentifier); + const eventDefinition = this.abi.getEvent(abiIdentifier); const parsedEvent = this.legacyResultsParser.doParseEvent({ topics: topics,