From 0c10858f9353b7d8ffd7e0cdc3c6282e8e8789ef Mon Sep 17 00:00:00 2001 From: Gabriel Martinez Rodriguez Date: Wed, 11 Dec 2024 11:41:21 +0100 Subject: [PATCH 1/4] feat(txm): added on new block hook --- apps/randomness/src/index.ts | 17 ++++++---- packages/txm/lib/HookManager.ts | 47 ++++++++++++++++++++------ packages/txm/lib/TransactionManager.ts | 2 +- 3 files changed, 48 insertions(+), 18 deletions(-) diff --git a/apps/randomness/src/index.ts b/apps/randomness/src/index.ts index 30640d8fea..1509386f2b 100644 --- a/apps/randomness/src/index.ts +++ b/apps/randomness/src/index.ts @@ -30,6 +30,7 @@ class RandomnessService { async start() { await Promise.all([this.txm.start(), this.randomnessRepository.start()]) this.txm.addHook(this.onTransactionStatusChange.bind(this), TxmHookType.TransactionStatusChanged) + this.txm.addHook(this.onNewBlock.bind(this), TxmHookType.NewBlock) } private onTransactionStatusChange(payload: { transaction: Transaction }) { @@ -64,6 +65,15 @@ class RandomnessService { }) } + private async onNewBlock(payload: { block: LatestBlock }) { + this.handleRevealNotSubmittedOnTime(payload.block) + this.randomnessRepository.pruneRandomnesses(payload.block.timestamp).then((result) => { + if (result.isErr()) { + console.error("Failed to prune commitments", result.error) + } + }) + } + private async handleRevealNotSubmittedOnTime(block: LatestBlock) { const randomnesses = this.randomnessRepository.getRandomnessInStatus(RandomnessStatus.COMMITMENT_EXECUTED) @@ -142,13 +152,6 @@ class RandomnessService { } }) - // We don't await for pruning, because we don't want to block the transaction collection - this.randomnessRepository.pruneRandomnesses(block.timestamp).then((result) => { - if (result.isErr()) { - console.error("Failed to prune commitments", result.error) - } - }) - return transactions } } diff --git a/packages/txm/lib/HookManager.ts b/packages/txm/lib/HookManager.ts index bc71b89c3d..f38ab6661a 100644 --- a/packages/txm/lib/HookManager.ts +++ b/packages/txm/lib/HookManager.ts @@ -1,3 +1,4 @@ +import type { LatestBlock } from "./BlockMonitor" import { Topics, eventBus } from "./EventBus.js" import type { Transaction } from "./Transaction.js" @@ -5,14 +6,29 @@ export enum TxmHookType { All = "All", TransactionStatusChanged = "TransactionStatusChanged", TransactionSaveFailed = "TransactionSaveFailed", + NewBlock = "NewBlock", } -export type TxmHookPayload = { - type: TxmHookType +export type TxmTransactionStatusChangedHookPayload = { + type: TxmHookType.TransactionStatusChanged transaction: Transaction } -export type TxmHookHandler = (event: TxmHookPayload) => void +export type TxmNewBlockHookPayload = { + type: TxmHookType.NewBlock + block: LatestBlock +} + +export type TxmTransactionSaveFailedHookPayload = { + type: TxmHookType.TransactionSaveFailed + transaction: Transaction +} + +export type TxmHookPayload = TxmTransactionStatusChangedHookPayload | TxmNewBlockHookPayload | TxmTransactionSaveFailedHookPayload + +export type TxmHookHandler = ( + event: Extract extends never ? TxmHookPayload : Extract, +) => void /** * This module manages the hooks system. A hook in the transaction manager is a callback function that @@ -25,29 +41,31 @@ export type TxmHookHandler = (event: TxmHookPayload) => void * - The callback function that executes when the event occurs. */ export class HookManager { - private hooks: Record + private hooks: { + [T in TxmHookType]: TxmHookHandler[] + } constructor() { this.hooks = { [TxmHookType.All]: [], [TxmHookType.TransactionStatusChanged]: [], [TxmHookType.TransactionSaveFailed]: [], + [TxmHookType.NewBlock]: [], } eventBus.on(Topics.TransactionStatusChanged, this.onTransactionStatusChanged.bind(this)) eventBus.on(Topics.TransactionSaveFailed, this.onTransactionSaveFailed.bind(this)) + eventBus.on(Topics.NewBlock, this.onNewBlock.bind(this)) } - public async addHook(handler: TxmHookHandler, type: TxmHookType): Promise { + public async addHook(handler: TxmHookHandler, type: T): Promise { if (!this.hooks[type]) { this.hooks[type] = [] } this.hooks[type].push(handler) } - private async onTransactionStatusChanged(payload: { - transaction: Transaction - }): Promise { - this.hooks[TxmHookType.TransactionStatusChanged].concat(this.hooks[TxmHookType.All]).map((h) => + private async onTransactionStatusChanged(payload: { transaction: Transaction }): Promise { + ;[...this.hooks[TxmHookType.TransactionStatusChanged], ...this.hooks[TxmHookType.All]].forEach((h) => h({ type: TxmHookType.TransactionStatusChanged, transaction: payload.transaction, @@ -58,11 +76,20 @@ export class HookManager { private async onTransactionSaveFailed(payload: { transaction: Transaction }): Promise { - this.hooks[TxmHookType.TransactionSaveFailed].concat(this.hooks[TxmHookType.All]).map((h) => + ;[...this.hooks[TxmHookType.TransactionSaveFailed], ...this.hooks[TxmHookType.All]].forEach((h) => h({ type: TxmHookType.TransactionSaveFailed, transaction: payload.transaction, }), ) } + + private async onNewBlock(block: LatestBlock): Promise { + ;[...this.hooks[TxmHookType.NewBlock], ...this.hooks[TxmHookType.All]].forEach((h) => + h({ + type: TxmHookType.NewBlock, + block, + }), + ) + } } diff --git a/packages/txm/lib/TransactionManager.ts b/packages/txm/lib/TransactionManager.ts index 29ab15edd9..7a1829a1df 100644 --- a/packages/txm/lib/TransactionManager.ts +++ b/packages/txm/lib/TransactionManager.ts @@ -264,7 +264,7 @@ export class TransactionManager { * @param type - The type of hook to add. * @param handler - The handler function to add. */ - public async addHook(handler: TxmHookHandler, type: TxmHookType): Promise { + public async addHook(handler: TxmHookHandler, type: T): Promise { await this.hookManager.addHook(handler, type) } From 6b1beded11d658260dbf39b268f8cc0c92e4b7d3 Mon Sep 17 00:00:00 2001 From: Gabriel Martinez Rodriguez Date: Tue, 14 Jan 2025 14:27:58 +0100 Subject: [PATCH 2/4] chore(txm): rename h for hook --- packages/txm/lib/HookManager.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/txm/lib/HookManager.ts b/packages/txm/lib/HookManager.ts index f38ab6661a..b224247b7a 100644 --- a/packages/txm/lib/HookManager.ts +++ b/packages/txm/lib/HookManager.ts @@ -65,8 +65,8 @@ export class HookManager { } private async onTransactionStatusChanged(payload: { transaction: Transaction }): Promise { - ;[...this.hooks[TxmHookType.TransactionStatusChanged], ...this.hooks[TxmHookType.All]].forEach((h) => - h({ + ;[...this.hooks[TxmHookType.TransactionStatusChanged], ...this.hooks[TxmHookType.All]].forEach((hook) => + hook({ type: TxmHookType.TransactionStatusChanged, transaction: payload.transaction, }), From 749c5fa64f12f267e76475aba1e5976c7df5a747 Mon Sep 17 00:00:00 2001 From: Gabriel Martinez Rodriguez Date: Tue, 14 Jan 2025 14:53:09 +0100 Subject: [PATCH 3/4] chore(txm): format --- packages/txm/lib/HookManager.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/txm/lib/HookManager.ts b/packages/txm/lib/HookManager.ts index b224247b7a..d5cbde2933 100644 --- a/packages/txm/lib/HookManager.ts +++ b/packages/txm/lib/HookManager.ts @@ -24,7 +24,10 @@ export type TxmTransactionSaveFailedHookPayload = { transaction: Transaction } -export type TxmHookPayload = TxmTransactionStatusChangedHookPayload | TxmNewBlockHookPayload | TxmTransactionSaveFailedHookPayload +export type TxmHookPayload = + | TxmTransactionStatusChangedHookPayload + | TxmNewBlockHookPayload + | TxmTransactionSaveFailedHookPayload export type TxmHookHandler = ( event: Extract extends never ? TxmHookPayload : Extract, @@ -83,7 +86,7 @@ export class HookManager { }), ) } - + private async onNewBlock(block: LatestBlock): Promise { ;[...this.hooks[TxmHookType.NewBlock], ...this.hooks[TxmHookType.All]].forEach((h) => h({ From d6af5a2451fe6e25150be9b4b176677a53500015 Mon Sep 17 00:00:00 2001 From: Gabriel Martinez Rodriguez Date: Tue, 21 Jan 2025 14:39:58 +0100 Subject: [PATCH 4/4] chore(txm): pr review --- apps/randomness/src/index.ts | 30 +++++++++---------- packages/txm/lib/HookManager.ts | 41 +++++++++++++++----------- packages/txm/lib/TransactionManager.ts | 4 +-- 3 files changed, 40 insertions(+), 35 deletions(-) diff --git a/apps/randomness/src/index.ts b/apps/randomness/src/index.ts index 1509386f2b..90ac84ff04 100644 --- a/apps/randomness/src/index.ts +++ b/apps/randomness/src/index.ts @@ -29,31 +29,31 @@ class RandomnessService { async start() { await Promise.all([this.txm.start(), this.randomnessRepository.start()]) - this.txm.addHook(this.onTransactionStatusChange.bind(this), TxmHookType.TransactionStatusChanged) - this.txm.addHook(this.onNewBlock.bind(this), TxmHookType.NewBlock) + this.txm.addHook(TxmHookType.TransactionStatusChanged, this.onTransactionStatusChange.bind(this)) + this.txm.addHook(TxmHookType.NewBlock, this.onNewBlock.bind(this)) } - private onTransactionStatusChange(payload: { transaction: Transaction }) { - const randomness = this.randomnessRepository.getRandomnessForIntentId(payload.transaction.intentId) + private onTransactionStatusChange(transaction: Transaction) { + const randomness = this.randomnessRepository.getRandomnessForIntentId(transaction.intentId) if (!randomness) { - console.warn("Couldn't find randomness with intentId", payload.transaction.intentId) + console.warn("Couldn't find randomness with intentId", transaction.intentId) return } - if (payload.transaction.status === TransactionStatus.Success) { - if (randomness.commitmentTransactionIntentId === payload.transaction.intentId) { + if (transaction.status === TransactionStatus.Success) { + if (randomness.commitmentTransactionIntentId === transaction.intentId) { randomness.commitmentExecuted() - } else if (randomness.revealTransactionIntentId === payload.transaction.intentId) { + } else if (randomness.revealTransactionIntentId === transaction.intentId) { randomness.revealExecuted() } } else if ( - payload.transaction.status === TransactionStatus.Failed || - payload.transaction.status === TransactionStatus.Expired + transaction.status === TransactionStatus.Failed || + transaction.status === TransactionStatus.Expired ) { - if (randomness.commitmentTransactionIntentId === payload.transaction.intentId) { + if (randomness.commitmentTransactionIntentId === transaction.intentId) { randomness.commitmentFailed() - } else if (randomness.revealTransactionIntentId === payload.transaction.intentId) { + } else if (randomness.revealTransactionIntentId === transaction.intentId) { randomness.revealFailed() } } @@ -65,9 +65,9 @@ class RandomnessService { }) } - private async onNewBlock(payload: { block: LatestBlock }) { - this.handleRevealNotSubmittedOnTime(payload.block) - this.randomnessRepository.pruneRandomnesses(payload.block.timestamp).then((result) => { + private async onNewBlock(block: LatestBlock) { + this.handleRevealNotSubmittedOnTime(block) + this.randomnessRepository.pruneRandomnesses(block.timestamp).then((result) => { if (result.isErr()) { console.error("Failed to prune commitments", result.error) } diff --git a/packages/txm/lib/HookManager.ts b/packages/txm/lib/HookManager.ts index d5cbde2933..720faf982e 100644 --- a/packages/txm/lib/HookManager.ts +++ b/packages/txm/lib/HookManager.ts @@ -24,15 +24,14 @@ export type TxmTransactionSaveFailedHookPayload = { transaction: Transaction } -export type TxmHookPayload = - | TxmTransactionStatusChangedHookPayload - | TxmNewBlockHookPayload - | TxmTransactionSaveFailedHookPayload - -export type TxmHookHandler = ( - event: Extract extends never ? TxmHookPayload : Extract, -) => void +export type TxmHooksRecord = { + [TxmHookType.All]: ((event: { payload: LatestBlock | Transaction; type: TxmHookType }) => void)[] + [TxmHookType.TransactionStatusChanged]: ((transaction: Transaction) => void)[] + [TxmHookType.TransactionSaveFailed]: ((transaction: Transaction) => void)[] + [TxmHookType.NewBlock]: ((block: LatestBlock) => void)[] +} +export type TxmHookHandler = TxmHooksRecord[T][number] /** * This module manages the hooks system. A hook in the transaction manager is a callback function that * executes when specific events occur, such as when a transaction's status changes. @@ -60,7 +59,7 @@ export class HookManager { eventBus.on(Topics.NewBlock, this.onNewBlock.bind(this)) } - public async addHook(handler: TxmHookHandler, type: T): Promise { + public async addHook(type: T, handler: TxmHookHandler): Promise { if (!this.hooks[type]) { this.hooks[type] = [] } @@ -68,10 +67,12 @@ export class HookManager { } private async onTransactionStatusChanged(payload: { transaction: Transaction }): Promise { - ;[...this.hooks[TxmHookType.TransactionStatusChanged], ...this.hooks[TxmHookType.All]].forEach((hook) => - hook({ + this.hooks[TxmHookType.TransactionStatusChanged].forEach((handler) => handler(payload.transaction)) + + this.hooks[TxmHookType.All].forEach((handler) => + handler({ type: TxmHookType.TransactionStatusChanged, - transaction: payload.transaction, + payload: payload.transaction, }), ) } @@ -79,19 +80,23 @@ export class HookManager { private async onTransactionSaveFailed(payload: { transaction: Transaction }): Promise { - ;[...this.hooks[TxmHookType.TransactionSaveFailed], ...this.hooks[TxmHookType.All]].forEach((h) => - h({ + this.hooks[TxmHookType.TransactionSaveFailed].forEach((handler) => handler(payload.transaction)) + + this.hooks[TxmHookType.All].forEach((handler) => + handler({ type: TxmHookType.TransactionSaveFailed, - transaction: payload.transaction, + payload: payload.transaction, }), ) } private async onNewBlock(block: LatestBlock): Promise { - ;[...this.hooks[TxmHookType.NewBlock], ...this.hooks[TxmHookType.All]].forEach((h) => - h({ + this.hooks[TxmHookType.NewBlock].forEach((handler) => handler(block)) + + this.hooks[TxmHookType.All].forEach((handler) => + handler({ type: TxmHookType.NewBlock, - block, + payload: block, }), ) } diff --git a/packages/txm/lib/TransactionManager.ts b/packages/txm/lib/TransactionManager.ts index 7a1829a1df..25915a3d18 100644 --- a/packages/txm/lib/TransactionManager.ts +++ b/packages/txm/lib/TransactionManager.ts @@ -264,8 +264,8 @@ export class TransactionManager { * @param type - The type of hook to add. * @param handler - The handler function to add. */ - public async addHook(handler: TxmHookHandler, type: T): Promise { - await this.hookManager.addHook(handler, type) + public async addHook(type: T, handler: TxmHookHandler): Promise { + await this.hookManager.addHook(type, handler) } public async getTransaction(txIntentId: UUID): Promise {