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
33 changes: 26 additions & 7 deletions packages/txm/lib/BlockMonitor.ts
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use the new logger.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { LogTag, Logger } from "@happy.tech/common"
import type { Block } from "viem"
import { Topics, eventBus } from "./EventBus.js"
import type { TransactionManager } from "./TransactionManager.js"

/**
* A type alias for {@link Block} with the `blockTag` set to `"latest"`, ensuring type definitions correspond to the latest block.
*/
Expand All @@ -14,23 +14,42 @@ export type LatestBlock = Block<bigint, false, "latest">
*/
export class BlockMonitor {
private txmgr: TransactionManager
private unwatch: (() => void) | undefined
private blockTimeout: ReturnType<typeof setTimeout> | undefined

constructor(_transactionManager: TransactionManager) {
this.txmgr = _transactionManager
}

async start() {
this.txmgr.viemClient.watchBlocks({
this.scheduleTimeout()
this.unwatch = this.txmgr.viemClient.watchBlocks({
onBlock: this.onNewBlock.bind(this),
...(this.txmgr.transportProtocol === "http"
? {
pollingInterval: this.txmgr.pollingInterval,
}
: {}),
...(this.txmgr.transportProtocol === "http" ? { pollingInterval: this.txmgr.pollingInterval } : {}),
onError: (error) => {
Logger.instance.error(LogTag.TXM, "Error watching blocks", error)
this.resetBlockSubscription()
},
})
}

private onNewBlock(block: LatestBlock) {
if (this.blockTimeout) clearTimeout(this.blockTimeout)
eventBus.emit(Topics.NewBlock, block)
this.scheduleTimeout()
}

private scheduleTimeout() {
this.blockTimeout = setTimeout(() => {
Logger.instance.warn(LogTag.TXM, "Timeout reached. Resetting block subscription.")
this.resetBlockSubscription()
}, this.txmgr.blockInactivityTimeout)
}

private resetBlockSubscription() {
if (this.unwatch) {
this.unwatch()
}
this.start()
}
}
3 changes: 2 additions & 1 deletion packages/txm/lib/TransactionCollector.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { LogTag, Logger } from "@happy.tech/common"
import type { LatestBlock } from "./BlockMonitor.js"
import { Topics, eventBus } from "./EventBus.js"
import { AttemptType } from "./Transaction.js"
Expand Down Expand Up @@ -36,7 +37,7 @@ export class TransactionCollector {
for (const transaction of transactionsBatch) {
eventBus.emit(Topics.TransactionSaveFailed, { transaction })
}
console.error("Error saving transactions", saveResult.error)
Logger.instance.error(LogTag.TXM, "Error saving transactions", saveResult.error)
return
}

Expand Down
8 changes: 8 additions & 0 deletions packages/txm/lib/TransactionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ export type TransactionManagerConfig = {
* Defaults to 1/2 of the block time.
*/
pollingInterval?: number

/**
* The time without blocks before closing the connection to the RPC node and reconnecting.
* Defaults to 4000 milliseconds.
*/
blockInactivityTimeout?: number
}
/** The private key of the account used for signing transactions. */
privateKey: Hex
Expand Down Expand Up @@ -167,6 +173,7 @@ export class TransactionManager {
public readonly finalizedTransactionPurgeTime: number
public readonly pollingInterval: number
public readonly transportProtocol: "http" | "websocket"
public readonly blockInactivityTimeout: number

constructor(_config: TransactionManagerConfig) {
this.collectors = []
Expand Down Expand Up @@ -259,6 +266,7 @@ export class TransactionManager {
this.finalizedTransactionPurgeTime = _config.finalizedTransactionPurgeTime || 2 * 60 * 1000

this.pollingInterval = _config.rpc.pollingInterval || (Number(this.blockTime) * 1000) / 2
this.blockInactivityTimeout = _config.rpc.blockInactivityTimeout || 4000
}

/**
Expand Down
4 changes: 3 additions & 1 deletion packages/txm/lib/TransactionSubmitter.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { LogTag } from "@happy.tech/common"
import { Logger } from "@happy.tech/common"
import { type Result, err, ok } from "neverthrow"
import type { Hash, Hex, TransactionRequestEIP1559 } from "viem"
import { encodeFunctionData, keccak256 } from "viem"
Expand Down Expand Up @@ -72,7 +74,7 @@ export class TransactionSubmitter {
const abi = this.txmgr.abiManager.get(transaction.contractName)

if (!abi) {
console.error(`ABI not found for contract ${transaction.contractName}`)
Logger.instance.error(LogTag.TXM, `ABI not found for contract ${transaction.contractName}`)
return err({
cause: AttemptSubmissionErrorCause.ABINotFound,
description: `ABI not found for contract ${transaction.contractName}`,
Expand Down
21 changes: 13 additions & 8 deletions packages/txm/lib/TxMonitor.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { bigIntMax, promiseWithResolvers, unknownToError } from "@happy.tech/common"
import { LogTag, Logger, bigIntMax, promiseWithResolvers, unknownToError } from "@happy.tech/common"
import { type Result, ResultAsync, err, ok } from "neverthrow"
import { type GetTransactionReceiptErrorType, type TransactionReceipt, TransactionReceiptNotFoundError } from "viem"
import type { LatestBlock } from "./BlockMonitor.js"
Expand Down Expand Up @@ -54,7 +54,7 @@ export class TxMonitor {
try {
await this.handleNewBlock(block)
} catch (error) {
console.error("Error in handleNewBlock: ", error)
Logger.instance.error(LogTag.TXM, "Error in handleNewBlock: ", error)
}
this.locked = false

Expand Down Expand Up @@ -113,7 +113,10 @@ export class TxMonitor {
that the transaction was executed and we don’t know
*/
if (attemptOrResults.some((v) => v.isErr())) {
console.error(`Failed to get transaction receipt for transaction ${transaction.intentId}`)
Logger.instance.error(
LogTag.TXM,
`Failed to get transaction receipt for transaction ${transaction.intentId}`,
)
return
}

Expand All @@ -126,7 +129,7 @@ export class TxMonitor {

if (receipt.status === "success") {
if (attempt.type === AttemptType.Cancellation) {
console.error(`Transaction ${transaction.intentId} was cancelled`)
Logger.instance.error(LogTag.TXM, `Transaction ${transaction.intentId} was cancelled`)
return transaction.changeStatus(TransactionStatus.Cancelled)
}
return transaction.changeStatus(TransactionStatus.Success)
Expand All @@ -140,7 +143,7 @@ export class TxMonitor {
)

if (!shouldRetry) {
console.error(`Transaction ${transaction.intentId} failed`)
Logger.instance.error(LogTag.TXM, `Transaction ${transaction.intentId} failed`)
return transaction.changeStatus(TransactionStatus.Failed)
}

Expand All @@ -155,7 +158,7 @@ export class TxMonitor {
)

if (result.isErr()) {
console.error("Error flushing transactions in onNewBlock")
Logger.instance.error(LogTag.TXM, "Error flushing transactions in onNewBlock")
}
}

Expand All @@ -182,7 +185,8 @@ export class TxMonitor {
const attempt = transaction.lastAttempt

if (!attempt) {
console.error(
Logger.instance.error(
LogTag.TXM,
`Transaction ${transaction.intentId} inconsistent state: no attempt found in handleExpiredTransaction`,
)
return
Expand All @@ -207,7 +211,8 @@ export class TxMonitor {
const attempt = transaction.lastAttempt

if (!attempt) {
console.error(
Logger.instance.error(
LogTag.TXM,
`Transaction ${transaction.intentId} inconsistent state: no attempt found in handleStuckTransaction`,
)
return
Expand Down
2 changes: 1 addition & 1 deletion support/common/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export { useIsHydrated } from "./hooks/isHydrated"

// === UTILS =======================================================================================

export { Logger } from "./utils/logger"
export { Logger, LogTag } from "./utils/logger"

export { atomWithCompare, atomWithCompareAndStorage, accessorsFromAtom, createBigIntStorage } from "./utils/jotai"

Expand Down
1 change: 1 addition & 0 deletions support/common/lib/utils/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export enum LogLevel {
*/
export enum LogTag {
ALL = "All",
TXM = "Txm",
}

/**
Expand Down
Loading