Skip to content

Commit

Permalink
Support JIT invoicing on donations to rewards pool
Browse files Browse the repository at this point in the history
Now you can just-in-time fund your account to donate to SN's reward pool.

You can also donate without an account via the @anon account, also using
JIT invoices.
  • Loading branch information
SatsAllDay committed Sep 23, 2023
1 parent 0eb28ef commit a78c647
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 12 deletions.
2 changes: 1 addition & 1 deletion api/resolvers/item.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export async function commentFilterClause (me, models) {
return clause
}

async function checkInvoice (models, hash, hmac, fee) {
export async function checkInvoice (models, hash, hmac, fee) {
if (!hmac) {
throw new GraphQLError('hmac required', { extensions: { code: 'BAD_INPUT' } })
}
Expand Down
34 changes: 28 additions & 6 deletions api/resolvers/rewards.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { GraphQLError } from 'graphql'
import { settleHodlInvoice } from 'ln-service'
import { amountSchema, ssValidate } from '../../lib/validate'
import serialize from './serial'
import { ANON_USER_ID } from '../../lib/constants'
import { getItem } from './item'
import { getItem, checkInvoice } from './item'

export default {
Query: {
Expand Down Expand Up @@ -102,17 +103,38 @@ export default {
}
},
Mutation: {
donateToRewards: async (parent, { sats }, { me, models }) => {
if (!me) {
throw new GraphQLError('you must be logged in', { extensions: { code: 'UNAUTHENTICATED' } })
donateToRewards: async (parent, { sats, hash, hmac }, { me, models, lnd }) => {
if (!me && !hash) {
throw new GraphQLError('you must be logged in or pay', { extensions: { code: 'FORBIDDEN' } })
}
let user
if (me) {
user = me
}

let invoice
if (hash) {
invoice = await checkInvoice(models, hash, hmac, sats)
user = invoice.user
}

await ssValidate(amountSchema, { amount: sats })

await serialize(models,
const trx = [
models.$queryRawUnsafe(
'SELECT donate($1::INTEGER, $2::INTEGER)',
sats, Number(me.id)))
sats, Number(user.id))
]

if (invoice) {
trx.unshift(models.$queryRaw`UPDATE users SET msats = msats + ${invoice.msatsReceived} WHERE id = ${user.id}`)
trx.push(models.invoice.update({ where: { hash: invoice.hash }, data: { confirmedAt: new Date() } }))
}
await serialize(models, ...trx)

if (invoice?.isHeld) {
await settleHodlInvoice({ secret: invoice.preimage, lnd })
}

return sats
}
Expand Down
2 changes: 1 addition & 1 deletion api/typeDefs/rewards.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default gql`
}
extend type Mutation {
donateToRewards(sats: Int!): Int!
donateToRewards(sats: Int!, hash: String, hmac: String): Int!
}
type Rewards {
Expand Down
11 changes: 7 additions & 4 deletions pages/rewards/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ export function DonateButton () {
const showModal = useShowModal()
const [donateToRewards] = useMutation(
gql`
mutation donateToRewards($sats: Int!) {
donateToRewards(sats: $sats)
mutation donateToRewards($sats: Int!, $hash: String, $hmac: String) {
donateToRewards(sats: $sats, hash: $hash, hmac: $hmac)
}`)

return (
Expand All @@ -102,10 +102,13 @@ export function DonateButton () {
amount: 1000
}}
schema={amountSchema}
onSubmit={async ({ amount }) => {
invoiceable
onSubmit={async ({ amount, hash, hmac }) => {
await donateToRewards({
variables: {
sats: Number(amount)
sats: Number(amount),
hash,
hmac
}
})
onClose()
Expand Down

0 comments on commit a78c647

Please sign in to comment.