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:
parent
d7a7273ca4
commit
644899469f
@ -1,5 +1,5 @@
|
|||||||
import { PAID_ACTION_PAYMENT_METHODS } from '@/lib/constants'
|
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 { notifyDeposit } from '@/lib/webPush'
|
||||||
import { getInvoiceableWallets } from '@/wallets/server'
|
import { getInvoiceableWallets } from '@/wallets/server'
|
||||||
|
|
||||||
@ -23,10 +23,6 @@ export async function getInvoiceablePeer (_, { me, models, cost, paymentMethod }
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cost < satsToMsats(me.receiveCreditsBelowSats)) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return me.id
|
return me.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -796,9 +796,9 @@ const logContextFromBolt11 = async (bolt11) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const walletLogger = ({ wallet, models }) => {
|
export const walletLogger = ({ wallet, models, me }) => {
|
||||||
// no-op logger if wallet is not provided
|
// no-op logger if no wallet or user provided
|
||||||
if (!wallet) {
|
if (!wallet && !me) {
|
||||||
return {
|
return {
|
||||||
ok: () => {},
|
ok: () => {},
|
||||||
info: () => {},
|
info: () => {},
|
||||||
@ -822,8 +822,9 @@ export const walletLogger = ({ wallet, models }) => {
|
|||||||
|
|
||||||
await models.walletLog.create({
|
await models.walletLog.create({
|
||||||
data: {
|
data: {
|
||||||
userId: wallet.userId,
|
userId: wallet?.userId ?? me.id,
|
||||||
wallet: wallet.type,
|
// system logs have no wallet
|
||||||
|
wallet: wallet?.type,
|
||||||
level,
|
level,
|
||||||
message,
|
message,
|
||||||
context,
|
context,
|
||||||
|
@ -194,7 +194,7 @@ const typeDefs = `
|
|||||||
type WalletLogEntry {
|
type WalletLogEntry {
|
||||||
id: ID!
|
id: ID!
|
||||||
createdAt: Date!
|
createdAt: Date!
|
||||||
wallet: ID!
|
wallet: ID
|
||||||
level: String!
|
level: String!
|
||||||
message: String!
|
message: String!
|
||||||
context: JSONObject
|
context: JSONObject
|
||||||
|
@ -226,7 +226,7 @@ export function useWalletLogs (wallet, initialPage = 1, logsPerPage = 10) {
|
|||||||
to = null
|
to = null
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data } = await getWalletLogs({
|
const { data, error } = await getWalletLogs({
|
||||||
variables: {
|
variables: {
|
||||||
type: walletDef?.walletType,
|
type: walletDef?.walletType,
|
||||||
from,
|
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 }) => ({
|
const newLogs = data.walletLogs.entries.map(({ createdAt, wallet: walletType, ...log }) => ({
|
||||||
ts: +new Date(createdAt),
|
ts: +new Date(createdAt),
|
||||||
wallet: walletTag(getWalletByType(walletType)),
|
wallet: walletType ? walletTag(getWalletByType(walletType)) : 'system',
|
||||||
...log,
|
...log,
|
||||||
// required to resolve recv status
|
// required to resolve recv status
|
||||||
context: {
|
context: {
|
||||||
|
@ -4,10 +4,11 @@ import { lnurlPayDescriptionHashForUser, lnurlPayMetadataString, lnurlPayDescrip
|
|||||||
import { schnorr } from '@noble/curves/secp256k1'
|
import { schnorr } from '@noble/curves/secp256k1'
|
||||||
import { createHash } from 'crypto'
|
import { createHash } from 'crypto'
|
||||||
import { LNURLP_COMMENT_MAX_LENGTH, MAX_INVOICE_DESCRIPTION_LENGTH } from '@/lib/constants'
|
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 assertGofacYourself from '@/api/resolvers/ofac'
|
||||||
import performPaidAction from '@/api/paidAction'
|
import performPaidAction from '@/api/paidAction'
|
||||||
import { validateSchema, lud18PayerDataSchema } from '@/lib/validate'
|
import { validateSchema, lud18PayerDataSchema } from '@/lib/validate'
|
||||||
|
import { walletLogger } from '@/api/resolvers/wallet'
|
||||||
|
|
||||||
export default async ({ query: { username, amount, nostr, comment, payerdata: payerData }, headers }, res) => {
|
export default async ({ query: { username, amount, nostr, comment, payerdata: payerData }, headers }, res) => {
|
||||||
const user = await models.user.findUnique({ where: { name: username } })
|
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` })
|
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 {
|
try {
|
||||||
await assertGofacYourself({ models, headers })
|
await assertGofacYourself({ models, headers })
|
||||||
// if nostr, decode, validate sig, check tags, set description hash
|
// 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) {
|
} catch (error) {
|
||||||
console.log(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' })
|
res.status(400).json({ status: 'ERROR', reason: 'could not generate invoice to customer\'s attached wallet' })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "WalletLog" ALTER COLUMN "wallet" DROP NOT NULL;
|
@ -264,18 +264,18 @@ model VaultEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model WalletLog {
|
model WalletLog {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
createdAt DateTime @default(now()) @map("created_at")
|
createdAt DateTime @default(now()) @map("created_at")
|
||||||
userId Int
|
userId Int
|
||||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
wallet WalletType
|
wallet WalletType?
|
||||||
level LogLevel
|
level LogLevel
|
||||||
message String
|
message String
|
||||||
invoiceId Int?
|
invoiceId Int?
|
||||||
invoice Invoice? @relation(fields: [invoiceId], references: [id])
|
invoice Invoice? @relation(fields: [invoiceId], references: [id])
|
||||||
withdrawalId Int?
|
withdrawalId Int?
|
||||||
withdrawal Withdrawl? @relation(fields: [withdrawalId], references: [id])
|
withdrawal Withdrawl? @relation(fields: [withdrawalId], references: [id])
|
||||||
context Json? @db.JsonB
|
context Json? @db.JsonB
|
||||||
|
|
||||||
@@index([userId, createdAt])
|
@@index([userId, createdAt])
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user