Skip to content

Commit

Permalink
Adjust parseEvent, add extra unit tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
andreibancioiu committed Oct 27, 2023
1 parent d347ef1 commit bf49ac2
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 12 deletions.
58 changes: 52 additions & 6 deletions src/smartcontracts/resultsParser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { loadAbiRegistry } from "../testutils";
import { ArgSerializer } from "./argSerializer";
import { ResultsParser } from "./resultsParser";
import { ReturnCode } from "./returnCode";
import { BigUIntType, BigUIntValue, EndpointDefinition, EndpointModifiers, EndpointParameterDefinition, StringType, StringValue, TypedValue, U32Type, U32Value, U64Type, U64Value, VariadicType, VariadicValue } from "./typesystem";
import { AbiRegistry, BigUIntType, BigUIntValue, EndpointDefinition, EndpointModifiers, EndpointParameterDefinition, StringType, StringValue, TypedValue, U32Type, U32Value, U64Type, U64Value, VariadicType, VariadicValue } from "./typesystem";
import { BytesType, BytesValue } from "./typesystem/bytes";

const KnownReturnCodes: string[] = [
Expand Down Expand Up @@ -242,12 +242,11 @@ describe("test smart contract results parser", () => {
assert.deepEqual(bundle.values, []);
});

it.only("should parse contract event", async () => {
const registry = await loadAbiRegistry("src/testdata/esdt-safe.abi.json");
const depositEvent = registry.getEvent("deposit");
it("should parse contract event", async () => {
const abiRegistry = await loadAbiRegistry("src/testdata/esdt-safe.abi.json");
const eventDefinition = abiRegistry.getEvent("deposit");

const event = new TransactionEvent({
identifier: "deposit",
topics: [
new TransactionEventTopic("ZGVwb3NpdA=="),
new TransactionEventTopic("cmzC1LRt1r10pMhNAnFb+FyudjGMq4G8CefCYdQUmmc="),
Expand All @@ -256,7 +255,7 @@ describe("test smart contract results parser", () => {
dataPayload: new TransactionEventData(Buffer.from("AAAAAAAAA9sAAAA=", "base64"))
});

const bundle = parser.parseEvent(event, depositEvent);
const bundle = parser.parseEvent(event, eventDefinition);

assert.equal((<IAddress>bundle.dest_address).bech32(), "erd1wfkv9495dhtt6a9yepxsyu2mlpw2ua333j4cr0qfulpxr4q5nfnshgyqun");
assert.equal(bundle.tokens[0].token_identifier, "WEGLD-01e49d");
Expand All @@ -268,6 +267,53 @@ describe("test smart contract results parser", () => {
assert.isNull(bundle.event_data.opt_gas_limit);
});

it("should parse contract event (with multi-values)", async () => {
const abiRegistry = AbiRegistry.create({
"events": [
{
"identifier": "foobar",
"inputs": [
{
"name": "a",
"type": "multi<u8, utf-8 string, u8, utf-8 string>",
"indexed": true
},
{
"name": "b",
"type": "multi<utf-8 string, u8>",
"indexed": true
},
{
"name": "c",
"type": "variadic<u8>",
"indexed": false
}
]
}
]
});

const eventDefinition = abiRegistry.getEvent("foobar");

const event = new TransactionEvent({
topics: [
new TransactionEventTopic(Buffer.from("not used").toString("base64")),
new TransactionEventTopic(Buffer.from([42]).toString("base64")),
new TransactionEventTopic(Buffer.from("test").toString("base64")),
new TransactionEventTopic(Buffer.from([43]).toString("base64")),
new TransactionEventTopic(Buffer.from("test").toString("base64")),
new TransactionEventTopic(Buffer.from("test").toString("base64")),
new TransactionEventTopic(Buffer.from([44]).toString("base64")),
],
dataPayload: new TransactionEventData(Buffer.from("01@02@03@04", "hex"))
});

const bundle = parser.parseEvent(event, eventDefinition);
assert.deepEqual(bundle.a, [new BigNumber(42), "test", new BigNumber(43), "test"]);
assert.deepEqual(bundle.b, ["test", new BigNumber(44)]);
assert.deepEqual(bundle.c, [new BigNumber(1), new BigNumber(2), new BigNumber(3), new BigNumber(4)]);
});

// This test should be enabled manually and run against a set of sample transactions.
// 2022-04-03: test ran against ~1800 transactions sampled from devnet.
it.skip("should parse real-world contract outcomes", async () => {
Expand Down
15 changes: 9 additions & 6 deletions src/smartcontracts/resultsParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,21 +329,24 @@ export class ResultsParser {

parseEvent(transactionEvent: ITransactionEvent, eventDefinition: { inputs: IEventInputDefinition[] }): any {
const result: any = {};
const topics = transactionEvent.topics.map(topic => Buffer.from(topic.hex(), "hex"));

// We skip the first topic, because that's the event identifier.
const topics = transactionEvent.topics.map(topic => Buffer.from(topic.hex(), "hex")).slice(1);
const data = transactionEvent.dataPayload?.valueOf() || Buffer.from([]);
const dataHex = data.toString("hex");

// "Indexed" ABI "event.inputs" correspond to "event.topics[1:]":
const indexedInputs = eventDefinition.inputs.filter(input => input.indexed);
const nonIndexedInputs = eventDefinition.inputs.filter(input => !input.indexed);

// We skip the first topic, because it's the event identifier.
const decodedTopics = this.argsSerializer.buffersToValues(topics.slice(1), indexedInputs);
const decodedDataParts = this.argsSerializer.stringToValues(dataHex, nonIndexedInputs);
const decodedTopics = this.argsSerializer.buffersToValues(topics, indexedInputs);

for (let i = 0; i < indexedInputs.length; i++) {
result[indexedInputs[i].name] = decodedTopics[i].valueOf();
}

// "Non-indexed" ABI "event.inputs" correspond to "event.data":
const nonIndexedInputs = eventDefinition.inputs.filter(input => !input.indexed);
const decodedDataParts = this.argsSerializer.stringToValues(dataHex, nonIndexedInputs);

for (let i = 0; i < nonIndexedInputs.length; i++) {
result[nonIndexedInputs[i].name] = decodedDataParts[i].valueOf();
}
Expand Down

0 comments on commit bf49ac2

Please sign in to comment.