From cacf8627fabbd64ead9f08bff5ab764fea7684c2 Mon Sep 17 00:00:00 2001 From: Nelson Taveras <4562733+nvtaveras@users.noreply.github.com> Date: Fri, 26 Jul 2024 13:50:13 -0400 Subject: [PATCH 1/5] refactor: add event type --- src/index.ts | 7 ++++--- src/types.ts | 9 +++++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/index.ts b/src/index.ts index 0b198a9..7830677 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,6 +4,7 @@ import type { Request, Response, } from "@google-cloud/functions-framework"; +import { EventType } from "./types.js"; import parseTransactionReceipts from "./parse-transaction-receipts"; import sendDiscordNotification from "./send-discord-notification"; import sendTelegramNotification from "./send-telegram-notification"; @@ -17,16 +18,16 @@ export const watchdogNotifier: HttpFunction = async ( for (const parsedEvent of parsedEvents) { switch (parsedEvent.event.eventName) { - case "ProposalCreated": + case EventType.ProposalCreated: await sendDiscordNotification(parsedEvent.event, parsedEvent.txHash); await sendTelegramNotification(parsedEvent.event, parsedEvent.txHash); break; - case "MedianUpdated": + case EventType.MedianUpdated: // Acts a health check/heartbeat for the service, as it's a frequently emitted event console.info("[HealthCheck]: Block", parsedEvent.block); break; default: - throw new Error("Unknown event type", parsedEvent.event); + throw new Error("Unknown event type"); } } diff --git a/src/types.ts b/src/types.ts index 24ca96f..bd62686 100644 --- a/src/types.ts +++ b/src/types.ts @@ -26,8 +26,13 @@ export interface LogsEntity { transactionIndex: string; } +export enum EventType { + ProposalCreated = "ProposalCreated", + MedianUpdated = "MedianUpdated", +} + export interface ProposalCreatedEvent { - eventName: "ProposalCreated"; + eventName: EventType.ProposalCreated; args: { calldatas: readonly `0x${string}`[]; description: string; @@ -43,7 +48,7 @@ export interface ProposalCreatedEvent { } export interface HealthCheckEvent { - eventName: "MedianUpdated"; + eventName: EventType.MedianUpdated; block: number; args: { token: `0x${string}`; From 0fba369dbdae484127e524a729fcc4df1ea989d5 Mon Sep 17 00:00:00 2001 From: Nelson Taveras <4562733+nvtaveras@users.noreply.github.com> Date: Fri, 26 Jul 2024 14:24:15 -0400 Subject: [PATCH 2/5] fix: better error handling while parsing events --- src/index.ts | 4 +- src/parse-transaction-receipts.ts | 84 +++++++++++++++++-------------- src/types.ts | 1 + src/utils/get-event-by-topic.ts | 14 ++++++ 4 files changed, 64 insertions(+), 39 deletions(-) create mode 100644 src/utils/get-event-by-topic.ts diff --git a/src/index.ts b/src/index.ts index 7830677..4a5cdc6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,5 @@ +import assert from "assert/strict"; + // Types import type { HttpFunction, @@ -27,7 +29,7 @@ export const watchdogNotifier: HttpFunction = async ( console.info("[HealthCheck]: Block", parsedEvent.block); break; default: - throw new Error("Unknown event type"); + assert(false, `Unknown event type from payload: ${req.body}`); } } diff --git a/src/parse-transaction-receipts.ts b/src/parse-transaction-receipts.ts index 57125fa..3b2854e 100644 --- a/src/parse-transaction-receipts.ts +++ b/src/parse-transaction-receipts.ts @@ -1,10 +1,13 @@ +import assert from "assert/strict"; + // External import { decodeEventLog } from "viem"; // Internal import GovernorABI from "./governor-abi.js"; -import { HealthCheckEvent, ProposalCreatedEvent } from "./types.js"; +import { EventType, HealthCheckEvent, ProposalCreatedEvent } from "./types.js"; import hasLogs from "./utils/has-logs.js"; +import getEventByTopic from "./utils/get-event-by-topic.js"; import isHealthCheckEvent from "./utils/is-health-check-event.js"; import isProposalCreatedEvent from "./utils/is-proposal-created-event.js"; import isTransactionReceipt from "./utils/is-transaction-receipt.js"; @@ -45,48 +48,53 @@ export default function parseTransactionReceipts( } for (const log of receipt.logs) { - if (!log.topics) { - throw new Error("No topics found in log"); - } + assert(log.topics && log.topics.length > 0, "No topics found in log"); - try { - const event = decodeEventLog({ - abi: GovernorABI, - data: log.data as `0x${string}`, - topics: log.topics as [ - signature: `0x${string}`, - ...args: `0x${string}`[], - ], - }); + const eventSignature = log.topics[0]; + const eventType = getEventByTopic(eventSignature); - if (isProposalCreatedEvent(event)) { - result.push({ - event, - txHash: log.transactionHash, + switch (eventType) { + case EventType.Unknown: + // It can happen that a single transaction fired multiple events, some of which we are not interested in + continue; + case EventType.ProposalCreated: + const proposalEvent = decodeEventLog({ + abi: GovernorABI, + data: log.data as `0x${string}`, + topics: log.topics as [ + signature: `0x${string}`, + ...args: `0x${string}`[], + ], }); - } - // eslint-disable-next-line no-empty - } catch {} - - try { - const event = decodeEventLog({ - abi: SortedOraclesABI, - data: log.data as `0x${string}`, - topics: log.topics as [ - signature: `0x${string}`, - ...args: `0x${string}`[], - ], - }); - if (isHealthCheckEvent(event)) { - result.push({ - block: Number(receipt.blockNumber), - event, - txHash: log.transactionHash, + if (isProposalCreatedEvent(proposalEvent)) { + result.push({ + event: proposalEvent, + txHash: log.transactionHash, + }); + } + break; + case EventType.MedianUpdated: + const healthCheckEvent = decodeEventLog({ + abi: SortedOraclesABI, + data: log.data as `0x${string}`, + topics: log.topics as [ + signature: `0x${string}`, + ...args: `0x${string}`[], + ], }); - } - // eslint-disable-next-line no-empty - } catch {} + + if (isHealthCheckEvent(healthCheckEvent)) { + result.push({ + block: Number(receipt.blockNumber), + event: healthCheckEvent, + txHash: log.transactionHash, + }); + } + break; + default: + assert(false, `Unknown event type: ${eventType}`); + } } } diff --git a/src/types.ts b/src/types.ts index bd62686..47390d4 100644 --- a/src/types.ts +++ b/src/types.ts @@ -27,6 +27,7 @@ export interface LogsEntity { } export enum EventType { + Unknown = "Unknown", ProposalCreated = "ProposalCreated", MedianUpdated = "MedianUpdated", } diff --git a/src/utils/get-event-by-topic.ts b/src/utils/get-event-by-topic.ts new file mode 100644 index 0000000..0c20180 --- /dev/null +++ b/src/utils/get-event-by-topic.ts @@ -0,0 +1,14 @@ +import { EventType } from "../types"; + +export default function getEventByTopic(topic: string): EventType { + switch (topic) { + // keccak256(abi.encodePacked("ProposalCreated(uint256,address,address[],uint256[],string[],bytes[],uint256,uint256,string)")) + case "0x7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e0": + return EventType.ProposalCreated; + // keccak256(abi.encodePacked("MedianUpdated(address,uint256)")) + case "0xa9981ebfc3b766a742486e898f54959b050a66006dbce1a4155c1f84a08bcf41": + return EventType.MedianUpdated; + default: + return EventType.Unknown; + } +} From e358efd3d8fcf233482c6ea029596b3781af91e0 Mon Sep 17 00:00:00 2001 From: Nelson Taveras <4562733+nvtaveras@users.noreply.github.com> Date: Fri, 26 Jul 2024 14:34:17 -0400 Subject: [PATCH 3/5] chore: linter --- src/index.ts | 5 ++++- src/parse-transaction-receipts.ts | 18 ++++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/index.ts b/src/index.ts index 4a5cdc6..e08370e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -29,7 +29,10 @@ export const watchdogNotifier: HttpFunction = async ( console.info("[HealthCheck]: Block", parsedEvent.block); break; default: - assert(false, `Unknown event type from payload: ${req.body}`); + assert( + false, + `Unknown event type from payload: ${JSON.stringify(req.body)}`, + ); } } diff --git a/src/parse-transaction-receipts.ts b/src/parse-transaction-receipts.ts index 3b2854e..a590c2f 100644 --- a/src/parse-transaction-receipts.ts +++ b/src/parse-transaction-receipts.ts @@ -57,8 +57,8 @@ export default function parseTransactionReceipts( case EventType.Unknown: // It can happen that a single transaction fired multiple events, some of which we are not interested in continue; - case EventType.ProposalCreated: - const proposalEvent = decodeEventLog({ + case EventType.ProposalCreated: { + const event = decodeEventLog({ abi: GovernorABI, data: log.data as `0x${string}`, topics: log.topics as [ @@ -67,15 +67,16 @@ export default function parseTransactionReceipts( ], }); - if (isProposalCreatedEvent(proposalEvent)) { + if (isProposalCreatedEvent(event)) { result.push({ - event: proposalEvent, + event, txHash: log.transactionHash, }); } break; - case EventType.MedianUpdated: - const healthCheckEvent = decodeEventLog({ + } + case EventType.MedianUpdated: { + const event = decodeEventLog({ abi: SortedOraclesABI, data: log.data as `0x${string}`, topics: log.topics as [ @@ -84,14 +85,15 @@ export default function parseTransactionReceipts( ], }); - if (isHealthCheckEvent(healthCheckEvent)) { + if (isHealthCheckEvent(event)) { result.push({ block: Number(receipt.blockNumber), - event: healthCheckEvent, + event, txHash: log.transactionHash, }); } break; + } default: assert(false, `Unknown event type: ${eventType}`); } From ef1516503be067e51f2b464c8dc75b0d12cfa3bb Mon Sep 17 00:00:00 2001 From: Nelson Taveras <4562733+nvtaveras@users.noreply.github.com> Date: Fri, 26 Jul 2024 15:48:22 -0400 Subject: [PATCH 4/5] chore: linter2 --- src/parse-transaction-receipts.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/parse-transaction-receipts.ts b/src/parse-transaction-receipts.ts index a590c2f..695db4b 100644 --- a/src/parse-transaction-receipts.ts +++ b/src/parse-transaction-receipts.ts @@ -95,7 +95,10 @@ export default function parseTransactionReceipts( break; } default: - assert(false, `Unknown event type: ${eventType}`); + assert( + false, + `Unknown event type. Did you forget to add a new event?`, + ); } } } From 2bd48db6e147899e13b7663ef91e20bb31b93c72 Mon Sep 17 00:00:00 2001 From: Nelson Taveras <4562733+nvtaveras@users.noreply.github.com> Date: Fri, 26 Jul 2024 15:49:55 -0400 Subject: [PATCH 5/5] chore: separate comment in two lines --- src/parse-transaction-receipts.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/parse-transaction-receipts.ts b/src/parse-transaction-receipts.ts index 695db4b..42c7151 100644 --- a/src/parse-transaction-receipts.ts +++ b/src/parse-transaction-receipts.ts @@ -55,7 +55,8 @@ export default function parseTransactionReceipts( switch (eventType) { case EventType.Unknown: - // It can happen that a single transaction fired multiple events, some of which we are not interested in + // It can happen that a single transaction fires multiple events, + // some of which we are not interested in continue; case EventType.ProposalCreated: { const event = decodeEventLog({