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 { 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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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,
 | 
			
		||||
 | 
			
		||||
@ -194,7 +194,7 @@ const typeDefs = `
 | 
			
		||||
  type WalletLogEntry {
 | 
			
		||||
    id: ID!
 | 
			
		||||
    createdAt: Date!
 | 
			
		||||
    wallet: ID!
 | 
			
		||||
    wallet: ID
 | 
			
		||||
    level: String!
 | 
			
		||||
    message: String!
 | 
			
		||||
    context: JSONObject
 | 
			
		||||
 | 
			
		||||
@ -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: {
 | 
			
		||||
 | 
			
		||||
@ -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' })
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,2 @@
 | 
			
		||||
-- AlterTable
 | 
			
		||||
ALTER TABLE "WalletLog" ALTER COLUMN "wallet" DROP NOT NULL;
 | 
			
		||||
@ -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])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user