From abc4877b59ac0aa55b2d0d0210606c57ddb6cdef Mon Sep 17 00:00:00 2001 From: Collins C Augustine Date: Thu, 30 Jul 2026 09:14:14 +0100 Subject: [PATCH] feat: implement a structured logging and error-reporting approach --- dongle/lib/logger.ts | 65 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 dongle/lib/logger.ts diff --git a/dongle/lib/logger.ts b/dongle/lib/logger.ts new file mode 100644 index 0000000..6d74101 --- /dev/null +++ b/dongle/lib/logger.ts @@ -0,0 +1,65 @@ +type LogLevel = "debug" | "info" | "warn" | "error"; + +const WALLET_ADDRESS_RE = /\bG[A-Z2-7]{55}\b/g; +const CONTRACT_ID_RE = /\bC[A-Z2-7]{55}\b/g; +const HASH_RE = /\b[a-f0-9]{64}\b/gi; + +function isEnabled(level: LogLevel): boolean { + if (level === "error" || level === "warn") return true; + return process.env.NODE_ENV === "development"; +} + +function redactMessage(message: string): string { + return message + .replace(WALLET_ADDRESS_RE, "[wallet]") + .replace(CONTRACT_ID_RE, "[contract]") + .replace(HASH_RE, (m) => `${m.slice(0, 6)}…${m.slice(-4)}`); +} + +function formatArg(arg: unknown): unknown { + if (typeof arg === "string") return redactMessage(arg); + if (arg instanceof Error) { + const err = arg as Error; + const safe = new Error(redactMessage(err.message)); + safe.name = err.name; + safe.stack = err.stack; + return safe; + } + return arg; +} + +function formatArgs(args: unknown[]): unknown[] { + return args.map(formatArg); +} + +export const logger = { + debug(...args: unknown[]) { + if (isEnabled("debug")) { + console.debug("[debug]", ...formatArgs(args)); + } + }, + + info(...args: unknown[]) { + if (isEnabled("info")) { + console.info("[info]", ...formatArgs(args)); + } + }, + + warn(...args: unknown[]) { + console.warn("[warn]", ...formatArgs(args)); + }, + + error(...args: unknown[]) { + console.error("[error]", ...formatArgs(args)); + }, +}; + +export function truncateHash(hash: string): string { + if (!hash || hash.length < 10) return hash ?? ""; + return `${hash.slice(0, 6)}…${hash.slice(-4)}`; +} + +export function truncateAddress(address: string): string { + if (!address || address.length < 8) return address ?? ""; + return `${address.slice(0, 4)}…${address.slice(-4)}`; +}