check invoice description hash against lnurl pay metadata
This commit is contained in:
parent
9c8396670a
commit
6a8fba14eb
@ -4,6 +4,7 @@ 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'
|
||||||
|
|
||||||
export async function getInvoice (parent, { id }, { me, models }) {
|
export async function getInvoice (parent, { id }, { me, models }) {
|
||||||
if (!me) {
|
if (!me) {
|
||||||
@ -230,6 +231,19 @@ export default {
|
|||||||
throw new Error(res2.reason)
|
throw new Error(res2.reason)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// decode invoice
|
||||||
|
let decoded
|
||||||
|
try {
|
||||||
|
decoded = await decodePaymentRequest({ lnd, request: res2.pr })
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
throw new Error('could not decode invoice')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decoded.description_hash !== lnurlPayDescriptionHash(res1.metadata)) {
|
||||||
|
throw new Error('description hash does not match')
|
||||||
|
}
|
||||||
|
|
||||||
// take pr and createWithdrawl
|
// take pr and createWithdrawl
|
||||||
return await createWithdrawal(parent, { invoice: res2.pr, maxFee }, { me, models, lnd })
|
return await createWithdrawal(parent, { invoice: res2.pr, maxFee }, { me, models, lnd })
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,10 @@ export function lnurlPayMetadataString (username) {
|
|||||||
]])
|
]])
|
||||||
}
|
}
|
||||||
|
|
||||||
export function lnurlPayDescriptionHash (username) {
|
export function lnurlPayDescriptionHashForUser (username) {
|
||||||
return createHash('sha256').update(lnurlPayMetadataString(username)).digest('hex')
|
return lnurlPayDescriptionHash(lnurlPayMetadataString(username))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function lnurlPayDescriptionHash (data) {
|
||||||
|
return createHash('sha256').update(data).digest('hex')
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ export default async ({ query: { username } }, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return res.status(200).json({
|
return res.status(200).json({
|
||||||
callback: `https://stacker.news/api/lnurlp/${username}/pay`, // The URL from LN SERVICE which will accept the pay request parameters
|
callback: `${process.env.PUBLIC_URL}/api/lnurlp/${username}/pay`, // The URL from LN SERVICE which will accept the pay request parameters
|
||||||
minSendable: 1000, // Min amount LN SERVICE is willing to receive, can not be less than 1 or more than `maxSendable`
|
minSendable: 1000, // Min amount LN SERVICE is willing to receive, can not be less than 1 or more than `maxSendable`
|
||||||
maxSendable: Number.MAX_SAFE_INTEGER,
|
maxSendable: Number.MAX_SAFE_INTEGER,
|
||||||
metadata: lnurlPayMetadataString(username), // Metadata json which must be presented as raw string here, this is required to pass signature verification at a later step
|
metadata: lnurlPayMetadataString(username), // Metadata json which must be presented as raw string here, this is required to pass signature verification at a later step
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import models from '../../../../api/models'
|
import models from '../../../../api/models'
|
||||||
import lnd from '../../../../api/lnd'
|
import lnd from '../../../../api/lnd'
|
||||||
import { createInvoice } from 'ln-service'
|
import { createInvoice } from 'ln-service'
|
||||||
import { lnurlPayDescriptionHash } from '../../../../lib/lnurl'
|
import { lnurlPayDescriptionHashForUser } from '../../../../lib/lnurl'
|
||||||
import serialize from '../../../../api/resolvers/serial'
|
import serialize from '../../../../api/resolvers/serial'
|
||||||
|
|
||||||
export default async ({ query: { username, amount } }, res) => {
|
export default async ({ query: { username, amount } }, res) => {
|
||||||
@ -17,7 +17,7 @@ export default async ({ query: { username, amount } }, res) => {
|
|||||||
// generate invoice
|
// generate invoice
|
||||||
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} msats for @${user.name} on stacker.news`
|
const description = `${amount} msats for @${user.name} on stacker.news`
|
||||||
const descriptionHash = lnurlPayDescriptionHash(username)
|
const descriptionHash = lnurlPayDescriptionHashForUser(username)
|
||||||
try {
|
try {
|
||||||
const invoice = await createInvoice({
|
const invoice = await createInvoice({
|
||||||
description,
|
description,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user