ekzyis 243b094fcd
Wallet debug logs (#2307)
* Add wallet debug logs

* Add checkbox to toggle diagnostics

* Require authentication for /wallets/debug

* Update debug log messages

* Use me.privates.diagnostics as source of truth
2025-07-23 10:42:14 -05:00

75 lines
2.3 KiB
JavaScript

import { formatMsats } from '@/lib/format'
import { parsePaymentRequest } from 'ln-service'
export function walletLogger ({
models,
protocolId,
userId,
invoiceId,
withdrawalId
}) {
// server implementation of wallet logger interface on client
const log = (level) => async (message, context = {}) => {
// if no timestamp is given, set createdAt to time when logger was called to keep logs in order
// since logs are created asynchronously and thus might get inserted out of order
// however, millisecond precision is not always enough ...
const createdAt = context?.createdAt ?? new Date()
delete context?.createdAt
const updateStatus = protocolId && ['OK', 'ERROR', 'WARNING'].includes(level) && (invoiceId || withdrawalId || context.bolt11 || context?.updateStatus)
delete context?.updateStatus
try {
if (context.bolt11) {
// automatically populate context from bolt11 to avoid duplicating this code
// (this is needed because in some cases we want to log before we have an invoice or withdrawal id)
context = {
...context,
...await logContextFromBolt11(context.bolt11)
}
}
await models.$transaction([
models.walletLog.create({
data: {
userId,
protocolId,
level,
message,
context,
invoiceId,
withdrawalId,
createdAt
}
}),
updateStatus && models.walletProtocol.update({
where: { id: protocolId },
data: { status: level }
})
].filter(Boolean))
} catch (err) {
console.error('error creating wallet log:', err)
}
}
return {
ok: (message, context) => log('OK')(message, context),
info: (message, context) => log('INFO')(message, context),
error: (message, context) => log('ERROR')(message, context),
warn: (message, context) => log('WARNING')(message, context),
debug: (message, context) => log('DEBUG')(message, context)
}
}
export async function logContextFromBolt11 (bolt11) {
const decoded = await parsePaymentRequest({ request: bolt11 })
return {
bolt11,
amount: formatMsats(decoded.mtokens),
payment_hash: decoded.id,
created_at: decoded.created_at,
expires_at: decoded.expires_at,
description: decoded.description
}
}