ekzyis ba370eeda6
wallet logger fixes (#2296)
* Fix createdAt in logger context

* Remove duplicate WalletLogEntry field resolver

* Include invoice in wallet logger context if invoice owned by user

* Also only include withdrawal in context if withdrawal owned by user
2025-07-18 14:24:29 -05:00

74 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 = ['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)
}
}
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
}
}