System logger for users (#2035)

* System logger

* remove outdated credits preference check on RECEIVE

* fix developer focused error message

---------

Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
Co-authored-by: k00b <k00b@stacker.news>
This commit is contained in:
ekzyis 2025-04-03 00:18:41 +02:00 committed by GitHub
parent d7a7273ca4
commit 644899469f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 30 additions and 21 deletions

View File

@ -1,5 +1,5 @@
import { PAID_ACTION_PAYMENT_METHODS } from '@/lib/constants'
import { toPositiveBigInt, numWithUnits, msatsToSats, satsToMsats } from '@/lib/format'
import { toPositiveBigInt, numWithUnits, msatsToSats } from '@/lib/format'
import { notifyDeposit } from '@/lib/webPush'
import { getInvoiceableWallets } from '@/wallets/server'
@ -23,10 +23,6 @@ export async function getInvoiceablePeer (_, { me, models, cost, paymentMethod }
return null
}
if (cost < satsToMsats(me.receiveCreditsBelowSats)) {
return null
}
return me.id
}

View File

@ -796,9 +796,9 @@ const logContextFromBolt11 = async (bolt11) => {
}
}
export const walletLogger = ({ wallet, models }) => {
// no-op logger if wallet is not provided
if (!wallet) {
export const walletLogger = ({ wallet, models, me }) => {
// no-op logger if no wallet or user provided
if (!wallet && !me) {
return {
ok: () => {},
info: () => {},
@ -822,8 +822,9 @@ export const walletLogger = ({ wallet, models }) => {
await models.walletLog.create({
data: {
userId: wallet.userId,
wallet: wallet.type,
userId: wallet?.userId ?? me.id,
// system logs have no wallet
wallet: wallet?.type,
level,
message,
context,

View File

@ -194,7 +194,7 @@ const typeDefs = `
type WalletLogEntry {
id: ID!
createdAt: Date!
wallet: ID!
wallet: ID
level: String!
message: String!
context: JSONObject

View File

@ -226,7 +226,7 @@ export function useWalletLogs (wallet, initialPage = 1, logsPerPage = 10) {
to = null
}
const { data } = await getWalletLogs({
const { data, error } = await getWalletLogs({
variables: {
type: walletDef?.walletType,
from,
@ -236,9 +236,14 @@ export function useWalletLogs (wallet, initialPage = 1, logsPerPage = 10) {
}
})
if (error) {
console.error('failed to query wallet logs:', error)
return { data: [], hasMore: false }
}
const newLogs = data.walletLogs.entries.map(({ createdAt, wallet: walletType, ...log }) => ({
ts: +new Date(createdAt),
wallet: walletTag(getWalletByType(walletType)),
wallet: walletType ? walletTag(getWalletByType(walletType)) : 'system',
...log,
// required to resolve recv status
context: {

View File

@ -4,10 +4,11 @@ import { lnurlPayDescriptionHashForUser, lnurlPayMetadataString, lnurlPayDescrip
import { schnorr } from '@noble/curves/secp256k1'
import { createHash } from 'crypto'
import { LNURLP_COMMENT_MAX_LENGTH, MAX_INVOICE_DESCRIPTION_LENGTH } from '@/lib/constants'
import { toPositiveBigInt } from '@/lib/format'
import { formatMsats, toPositiveBigInt } from '@/lib/format'
import assertGofacYourself from '@/api/resolvers/ofac'
import performPaidAction from '@/api/paidAction'
import { validateSchema, lud18PayerDataSchema } from '@/lib/validate'
import { walletLogger } from '@/api/resolvers/wallet'
export default async ({ query: { username, amount, nostr, comment, payerdata: payerData }, headers }, res) => {
const user = await models.user.findUnique({ where: { name: username } })
@ -15,6 +16,9 @@ export default async ({ query: { username, amount, nostr, comment, payerdata: pa
return res.status(400).json({ status: 'ERROR', reason: `user @${username} does not exist` })
}
const logger = walletLogger({ models, me: user })
logger.info(`${user.name}@stacker.news payment attempt`, { amount: formatMsats(amount), nostr, comment })
try {
await assertGofacYourself({ models, headers })
// if nostr, decode, validate sig, check tags, set description hash
@ -96,6 +100,7 @@ export default async ({ query: { username, amount, nostr, comment, payerdata: pa
})
} catch (error) {
console.log(error)
logger.error(`${user.name}@stacker.news payment failed: ${error.message}`)
res.status(400).json({ status: 'ERROR', reason: 'could not generate invoice to customer\'s attached wallet' })
}
}

View File

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "WalletLog" ALTER COLUMN "wallet" DROP NOT NULL;

View File

@ -264,18 +264,18 @@ model VaultEntry {
}
model WalletLog {
id Int @id @default(autoincrement())
createdAt DateTime @default(now()) @map("created_at")
id Int @id @default(autoincrement())
createdAt DateTime @default(now()) @map("created_at")
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
wallet WalletType
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
wallet WalletType?
level LogLevel
message String
invoiceId Int?
invoice Invoice? @relation(fields: [invoiceId], references: [id])
invoice Invoice? @relation(fields: [invoiceId], references: [id])
withdrawalId Int?
withdrawal Withdrawl? @relation(fields: [withdrawalId], references: [id])
context Json? @db.JsonB
withdrawal Withdrawl? @relation(fields: [withdrawalId], references: [id])
context Json? @db.JsonB
@@index([userId, createdAt])
}