Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 21 additions & 18 deletions apps/randomness/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,30 +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(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()
}
}
Expand All @@ -64,6 +65,15 @@ class RandomnessService {
})
}

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)
}
})
}

private async handleRevealNotSubmittedOnTime(block: LatestBlock) {
const randomnesses = this.randomnessRepository.getRandomnessInStatus(RandomnessStatus.COMMITMENT_EXECUTED)

Expand Down Expand Up @@ -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
}
}
Expand Down
63 changes: 49 additions & 14 deletions packages/txm/lib/HookManager.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,37 @@
import type { LatestBlock } from "./BlockMonitor"
import { Topics, eventBus } from "./EventBus.js"
import type { Transaction } from "./Transaction.js"

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 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<T extends TxmHookType = TxmHookType.All> = 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.
Expand All @@ -25,43 +43,60 @@ export type TxmHookHandler = (event: TxmHookPayload) => void
* - The callback function that executes when the event occurs.
*/
export class HookManager {
private hooks: Record<TxmHookType, TxmHookHandler[]>
private hooks: {
[T in TxmHookType]: TxmHookHandler<T>[]
}

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<void> {
public async addHook<T extends TxmHookType>(type: T, handler: TxmHookHandler<T>): Promise<void> {
if (!this.hooks[type]) {
this.hooks[type] = []
}
this.hooks[type].push(handler)
}

private async onTransactionStatusChanged(payload: {
transaction: Transaction
}): Promise<void> {
this.hooks[TxmHookType.TransactionStatusChanged].concat(this.hooks[TxmHookType.All]).map((h) =>
h({
private async onTransactionStatusChanged(payload: { transaction: Transaction }): Promise<void> {
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,
}),
)
}

private async onTransactionSaveFailed(payload: {
transaction: Transaction
}): Promise<void> {
this.hooks[TxmHookType.TransactionSaveFailed].concat(this.hooks[TxmHookType.All]).map((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<void> {
this.hooks[TxmHookType.NewBlock].forEach((handler) => handler(block))

this.hooks[TxmHookType.All].forEach((handler) =>
handler({
type: TxmHookType.NewBlock,
payload: block,
}),
)
}
Expand Down
4 changes: 2 additions & 2 deletions packages/txm/lib/TransactionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: TxmHookType): Promise<void> {
await this.hookManager.addHook(handler, type)
public async addHook<T extends TxmHookType>(type: T, handler: TxmHookHandler<T>): Promise<void> {
await this.hookManager.addHook(type, handler)
}

public async getTransaction(txIntentId: UUID): Promise<Transaction | undefined> {
Expand Down