limit pending invoices

This commit is contained in:
keyan 2022-05-31 17:17:48 -05:00
parent ba4644463f
commit c061f4a6f0
3 changed files with 30 additions and 2 deletions

View File

@ -1,11 +1,29 @@
import { createInvoice, decodePaymentRequest, payViaPaymentRequest } from 'ln-service' import { createInvoice, decodePaymentRequest, payViaPaymentRequest } from 'ln-service'
import { UserInputError, AuthenticationError } from 'apollo-server-micro' import { UserInputError, AuthenticationError, ForbiddenError } from 'apollo-server-micro'
import serialize from './serial' import serialize from './serial'
import { decodeCursor, LIMIT, nextCursorEncoded } from '../../lib/cursor' import { decodeCursor, LIMIT, nextCursorEncoded } from '../../lib/cursor'
import lnpr from 'bolt11' import lnpr from 'bolt11'
import { SELECT } from './item' import { SELECT } from './item'
import { lnurlPayDescriptionHash } from '../../lib/lnurl' import { lnurlPayDescriptionHash } from '../../lib/lnurl'
const INVOICE_LIMIT = 10
export async function belowInvoiceLimit (models, userId) {
// make sure user has not exceeded INVOICE_LIMIT
const count = await models.invoice.count({
where: {
userId,
expiresAt: {
gt: new Date()
},
confirmedAt: null,
cancelled: false
}
})
return count < INVOICE_LIMIT
}
export async function getInvoice (parent, { id }, { me, models }) { export async function getInvoice (parent, { id }, { me, models }) {
if (!me) { if (!me) {
throw new AuthenticationError('you must be logged in') throw new AuthenticationError('you must be logged in')
@ -181,6 +199,10 @@ export default {
const user = await models.user.findUnique({ where: { id: me.id } }) const user = await models.user.findUnique({ where: { id: me.id } })
if (!await belowInvoiceLimit(models, me.id)) {
throw new ForbiddenError('too many pending invoices')
}
// set expires at to 3 hours into future // set expires at to 3 hours into future
const expiresAt = new Date(new Date().setHours(new Date().getHours() + 3)) const expiresAt = new Date(new Date().setHours(new Date().getHours() + 3))
const description = `${amount} sats for @${user.name} on stacker.news` const description = `${amount} sats for @${user.name} on stacker.news`

View File

@ -3,6 +3,7 @@ import lnd from '../../../../api/lnd'
import { createInvoice } from 'ln-service' import { createInvoice } from 'ln-service'
import { lnurlPayDescriptionHashForUser } from '../../../../lib/lnurl' import { lnurlPayDescriptionHashForUser } from '../../../../lib/lnurl'
import serialize from '../../../../api/resolvers/serial' import serialize from '../../../../api/resolvers/serial'
import { belowInvoiceLimit } from '../../../../api/resolvers/wallet'
export default async ({ query: { username, amount } }, res) => { export default async ({ query: { username, amount } }, res) => {
const user = await models.user.findUnique({ where: { name: username } }) const user = await models.user.findUnique({ where: { name: username } })
@ -14,8 +15,12 @@ export default async ({ query: { username, amount } }, res) => {
return res.status(400).json({ status: 'ERROR', reason: 'amount must be >=1000 msats' }) return res.status(400).json({ status: 'ERROR', reason: 'amount must be >=1000 msats' })
} }
if (!await belowInvoiceLimit(models, user.id)) {
return res.status(400).json({ status: 'ERROR', reason: 'too many pending invoices' })
}
// generate invoice // generate invoice
const expiresAt = new Date(new Date().setHours(new Date().getHours() + 3)) const expiresAt = new Date(new Date().setMinutes(new Date().getMinutes() + 1))
const description = `${amount} msats for @${user.name} on stacker.news` const description = `${amount} msats for @${user.name} on stacker.news`
const descriptionHash = lnurlPayDescriptionHashForUser(username) const descriptionHash = lnurlPayDescriptionHashForUser(username)
try { try {

View File

@ -114,6 +114,7 @@ export function FundForm () {
initial={{ initial={{
amount: 1000 amount: 1000
}} }}
initialError={error?.toString()}
schema={FundSchema} schema={FundSchema}
onSubmit={async ({ amount }) => { onSubmit={async ({ amount }) => {
const { data } = await createInvoice({ variables: { amount: Number(amount) } }) const { data } = await createInvoice({ variables: { amount: Number(amount) } })