Skip to content

Commit

Permalink
code cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
riccardobl committed Nov 9, 2024
1 parent 76034b3 commit 994b69d
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 47 deletions.
71 changes: 27 additions & 44 deletions api/paidAction/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const paidActions = {
BUY_CREDITS
}

async function checkUser (userId, { models, tx, me }, minSats) {
async function checkUser (userId, { models, tx, me }, minSats, minCreds) {
// count pending invoices and bail if we're over the limit
const pendingInvoices = await ((tx ?? models).invoice.count({
where: {
Expand All @@ -52,11 +52,14 @@ async function checkUser (userId, { models, tx, me }, minSats) {

console.log('pending paid actions', pendingInvoices)
if (pendingInvoices >= MAX_PENDING_PAID_ACTIONS_PER_USER) {
throw new Error('You have too many pending paid actions, cancel some or wait for them to expire')
throw new Error('you have too many pending paid actions, cancel some or wait for them to expire')
}

if (minSats !== undefined && toPositiveBigInt(minSats) > (me?.msats ?? 0n)) {
throw new Error('You do not have enough sats to perform this action')
if (minSats != null && toPositiveBigInt(minSats) > (me?.msats ?? 0n)) {
throw new Error('you do not have enough sats to perform this action')
}
if (minCreds != null && toPositiveBigInt(minCreds) > (me?.mcredits ?? 0n)) {
throw new Error('you do not have enough credits to perform this action')
}
}

Expand All @@ -66,7 +69,7 @@ export default async function performPaidAction (actionType, args, context) {
console.group('performPaidAction', actionType, args)
const paidAction = paidActions[actionType]
if (!paidAction) {
throw new Error(`Invalid action type ${actionType}`)
throw new Error(`ynvalid action type ${actionType}`)
}

context.me = context.me ? await context.models.user.findUnique({ where: { id: context.me.id } }) : undefined
Expand All @@ -75,10 +78,10 @@ export default async function performPaidAction (actionType, args, context) {
context.prioritizeInternal = context.prioritizeInternal ?? false

context.cost = await paidAction.getCost(args, context) ?? 0n
if (context.cost < 0n) throw new Error('Cost cannot be negative')
if (context.cost < 0n) throw new Error('cost cannot be negative')

context.sybilFeePercent = paidAction.getSybilFeePercent ? await paidAction.getSybilFeePercent(args, context) : undefined
if (context.sybilFeePercent !== undefined && context.sybilFeePercent < 0n) throw new Error('Sybil fee percent cannot be negative')
if (context.sybilFeePercent !== undefined && context.sybilFeePercent < 0n) throw new Error('sybil fee percent cannot be negative')

context.description = context.me?.hideInvoiceDesc ? undefined : await paidAction.describe(args, context)
context.descriptionHash = paidAction.describeHash ? await paidAction.describeHash(args, context) : undefined
Expand Down Expand Up @@ -128,11 +131,10 @@ export default async function performPaidAction (actionType, args, context) {
supportedPaymentMethods = supportedPaymentMethods.sort((a, b) => {
return (priority[a] || 0) - (priority[b] || 0)
})
console.log('Prioritize internal payment methods', supportedPaymentMethods)
}

for (const paymentMethod of supportedPaymentMethods) {
console.log('Trying payment method', paymentMethod)
console.log('trying payment method', paymentMethod)
if (paymentMethod === PAID_ACTION_PAYMENT_METHODS.FEE_CREDIT) {
if (me && (me.mcredits ?? 0n) >= cost) {
try {
Expand Down Expand Up @@ -191,7 +193,7 @@ export default async function performPaidAction (actionType, args, context) {
return await performPessimisticAction(invoiceData, actionType, paidAction, args, context)
}
}
throw new Error('No payment method available')
throw new Error('no payment method available')
} catch (e) {
console.error('performPaidAction failed', e)
throw e
Expand All @@ -210,10 +212,10 @@ async function performAction (invoiceEntry, paidAction, args, context) {
}

async function performInternalAction (cost, actionType, paidAction, paymentMethod, args, context) {
const { me, models, retryForInvoice } = context
const { me, models } = context
const run = async tx => {
const subContext = { ...context, tx }
await checkUser(me?.id ?? USER_ID.anon, subContext, cost)
await checkUser(me?.id ?? USER_ID.anon, subContext, paymentMethod === 'REWARD_SATS' ? cost : 0n, paymentMethod === 'FEE_CREDIT' ? cost : 0n)

try {
if (paymentMethod !== PAID_ACTION_PAYMENT_METHODS.ZERO_COST) {
Expand All @@ -228,10 +230,10 @@ async function performInternalAction (cost, actionType, paidAction, paymentMetho
? { msats: { decrement: cost } }
: { mcredits: { decrement: cost } }
})
console.log('Paid action with ' + paymentMethod)
} else throw new Error('Invalid payment method ' + paymentMethod)
console.log('action paid with ' + paymentMethod)
} else throw new Error('invalid payment method ' + paymentMethod)
} else {
console.log('No cost paid action')
console.log('no cost paid action')
}

const result = await performAction(null, paidAction, args, subContext)
Expand All @@ -243,27 +245,15 @@ async function performInternalAction (cost, actionType, paidAction, paymentMetho
retriableWithWallet: false
}
} catch (e) {
console.error('internal paid action failed', e)
// if it is retrying a fee credit action, we mark it as failed so it can be retried imeediately
if (retryForInvoice) {
await tx.invoice.update({
where: {
id: retryForInvoice.id
},
data: {
actionState: 'FAILED'
}
})
}
console.error('action failed', e)
throw e
}
}
const result = context.tx
? await run(context.tx)
: await models.$transaction(run, { isolationLevel: Prisma.TransactionIsolationLevel.Serializable })

// run non critical side effects in the background
// after the transaction has been committed
// run non critical side effects in the background after the transaction has been committed
paidAction.nonCriticalSideEffects?.(result.result, context).catch(console.error)
return result
}
Expand All @@ -273,7 +263,6 @@ async function performOptimisticAction (invoiceData, actionType, paidAction, arg
const performInvoicedAction = async tx => {
const subContext = { ...context, tx, optimistic: true }
await checkUser(me?.id ?? USER_ID.anon, subContext)

const invoiceEntry = await createDbInvoice(invoiceData, {
actionType,
actionId,
Expand All @@ -296,7 +285,6 @@ async function performPessimisticAction (invoiceData, actionType, paidAction, ar
const performInvoicedAction = async tx => {
const subContext = { ...context, tx, optimistic: false }
await checkUser(me?.id ?? USER_ID.anon, subContext)

const invoiceEntry = await createDbInvoice(invoiceData, {
actionType,
actionId,
Expand All @@ -320,31 +308,28 @@ export async function retryPaidAction ({ invoiceId, forceInternal, resetAttempts
const subContext = { ...context, tx }
const failedInvoice = await models.invoice.findUnique({ where: { id: invoiceId, userId: me?.id ?? USER_ID.anon } })
if (!failedInvoice) {
throw new Error('Invoice not found')
throw new Error('invoice not found')
}

if (
failedInvoice.actionState !== 'FAILED' &&
failedInvoice.actionState !== 'PENDING' &&
failedInvoice.actionState !== 'PENDING_HELD'
) {
throw new Error(`Invoice is not in a retriable state: ${failedInvoice.actionState}`)
throw new Error(`actions is not in a retriable state: ${failedInvoice.actionState}`)
}

// cancel the previous invoice
await finalizeHodlInvoice({ data: { hash: failedInvoice.hash }, lnd, models, boss })

const actionType = failedInvoice.actionType

console.log('retryPaidAction', actionType, failedInvoice)

const paidAction = paidActions[actionType]
if (!paidAction) {
throw new Error(`retryPaidAction - invalid action type ${actionType}`)
throw new Error(`invalid action type ${actionType}`)
}

if (!failedInvoice) {
throw new Error(`retryPaidAction - missing invoice ${actionType}`)
throw new Error(`missing invoice ${actionType}`)
}

const { msatsRequested, actionId, actionArgs } = failedInvoice
Expand Down Expand Up @@ -393,15 +378,14 @@ export async function createDbInvoice (
const { actionId, actionType, optimistic: isOptimisticAction, args } = actionData

const db = tx ?? models

const servedInvoice = await parsePaymentRequest({ request: servedBolt11 })

const expiresAt = new Date(servedInvoice.expires_at)

// sanity checks
if (servedInvoice.mtokens < 1000n) {
throw new Error('The amount must be at least 1 sat')
throw new Error('the amount must be at least 1 sat')
}

if (!isWrapped) {
if (isHodl && isOptimisticAction) throw new Error('optimistic actions should not use hodl invoices')
if (!isOptimisticAction && !isHodl) throw new Error('pessimistic actions should use hodl invoices')
Expand Down Expand Up @@ -466,10 +450,9 @@ export async function createDbInvoice (
async function createSNInvoice ({ description, descriptionHash, cost, expiry = INVOICE_EXPIRE_SECS, isHodl }, { lnd }) {
// sanity check
cost = toPositiveBigInt(cost)
if (cost < 1000n) throw new Error('The cost of the action must be at least 1 sat')
if (cost < 1000n) throw new Error('the cost of the action must be at least 1 sat')
const expiresAt = datePivot(new Date(), { seconds: expiry ?? INVOICE_EXPIRE_SECS })

console.log('createSNInvoice', { description, descriptionHash, cost, expiry, isHodl })
let invoice
const mtokens = String(cost)
if (!isHodl) {
Expand All @@ -489,7 +472,7 @@ async function createSNInvoice ({ description, descriptionHash, cost, expiry = I
expires_at: expiresAt
})
}
console.log('invoice created', invoice)

return {
invoice: invoice.request,
preimage: invoice.secret,
Expand Down
3 changes: 0 additions & 3 deletions components/use-paid-mutation.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ export function usePaidMutation (mutation,
}

// every wallet failed, but we can still retry, so let's ask for a better invoice
console.log(response)
if (response.retriableWithWallet) {
console.log('could not pay with any wallet, will retry with a new invoice...')
} else {
Expand All @@ -110,7 +109,6 @@ export function usePaidMutation (mutation,
}

// we try an internal payment
console.log(response)
try {
console.log('could not pay with any wallet, will try with an internal payment...')
const retry = await retryPaidAction({ variables: { invoiceId: parseInt(invoice.id), prioritizeInternal: true } })
Expand All @@ -129,7 +127,6 @@ export function usePaidMutation (mutation,
}

// last resort, show qr code or fail
console.log(response)
if ((alwaysShowQROnFailure || usableWallets.length === 0)) {
console.log('show qr code for manual payment')
await refreshInvoice()
Expand Down

0 comments on commit 994b69d

Please sign in to comment.