complete nip 57 support
This commit is contained in:
parent
ef5346000b
commit
93d4581360
|
@ -7689,6 +7689,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"noble-secp256k1": {
|
||||
"version": "1.2.14",
|
||||
"resolved": "https://registry.npmjs.org/noble-secp256k1/-/noble-secp256k1-1.2.14.tgz",
|
||||
"integrity": "sha512-GSCXyoZBUaaPwVWdYncMEmzlSUjF9J/YeEHpklYJCyg8wPuJP3NzDx0BkiwArzINkdX2HJHvUJhL6vVWPOQQcg=="
|
||||
},
|
||||
"node-abort-controller": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz",
|
||||
|
@ -7821,6 +7826,15 @@
|
|||
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-7.2.0.tgz",
|
||||
"integrity": "sha512-uhXOdZry0L6M2UIo9BTt7FdpBDiAGN/7oItedQwPKh8jh31ZlvC8U9Xl/EJ3aijDHaywXTW3QbZ6LuCocur1YA=="
|
||||
},
|
||||
"nostr": {
|
||||
"version": "0.2.7",
|
||||
"resolved": "https://registry.npmjs.org/nostr/-/nostr-0.2.7.tgz",
|
||||
"integrity": "sha512-Yq5tkiCTJtohs7H7Fx+Ki83bR8b3xapdwYi17HunhW5EQfZ9rI0cIXFyihj2ZRkv/0YYvVBiCp/KIaLYt5LyfQ==",
|
||||
"requires": {
|
||||
"noble-secp256k1": "^1.2.14",
|
||||
"ws": "^8.8.1"
|
||||
}
|
||||
},
|
||||
"nprogress": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz",
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
"next-seo": "^4.29.0",
|
||||
"nextjs-progressbar": "0.0.16",
|
||||
"node-s3-url-encode": "^0.0.4",
|
||||
"nostr": "^0.2.7",
|
||||
"opentimestamps": "^0.4.9",
|
||||
"page-metadata-parser": "^1.1.4",
|
||||
"pageres": "^7.1.0",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import models from '../../../../api/models'
|
||||
import lnd from '../../../../api/lnd'
|
||||
import { createInvoice } from 'ln-service'
|
||||
import { lnurlPayDescriptionHashForUser } from '../../../../lib/lnurl'
|
||||
import { lnurlPayDescriptionHashForUser, lnurlPayMetadataString } from '../../../../lib/lnurl'
|
||||
import serialize from '../../../../api/resolvers/serial'
|
||||
import * as secp256k1 from '@noble/secp256k1'
|
||||
import { createHash } from 'crypto'
|
||||
|
@ -21,14 +21,14 @@ export default async ({ query: { username, amount, nostr } }, res) => {
|
|||
const hasETag = note.tags?.filter(t => t[0] === 'e').length <= 1
|
||||
if (await secp256k1.schnorr.verify(note.sig, note.id, note.pubkey) &&
|
||||
hasPTag && hasETag) {
|
||||
description = user.hideInvoiceDesc ? undefined : `${amount} msats for @${user.name} on stacker.news via NIP-57`
|
||||
description = noteStr
|
||||
descriptionHash = createHash('sha256').update(noteStr).digest('hex')
|
||||
} else {
|
||||
res.status(400).json({ status: 'ERROR', reason: 'invalid NIP-57 note' })
|
||||
return
|
||||
}
|
||||
} else {
|
||||
description = user.hideInvoiceDesc ? undefined : `${amount} msats for @${user.name} on stacker.news`
|
||||
description = user.hideInvoiceDesc ? undefined : lnurlPayMetadataString(username)
|
||||
descriptionHash = lnurlPayDescriptionHashForUser(username)
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,10 @@ const { ApolloClient, HttpLink, InMemoryCache } = require('@apollo/client')
|
|||
const { indexItem, indexAllItems } = require('./search')
|
||||
const { timestampItem } = require('./ots')
|
||||
const { computeStreaks, checkStreak } = require('./streak')
|
||||
const { nip57 } = require('./nostr')
|
||||
|
||||
const fetch = require('cross-fetch')
|
||||
const { authenticatedLndGrpc } = require('ln-service')
|
||||
|
||||
async function work () {
|
||||
const boss = new PgBoss(process.env.DATABASE_URL)
|
||||
|
@ -34,7 +37,13 @@ async function work () {
|
|||
}
|
||||
})
|
||||
|
||||
const args = { boss, models, apollo }
|
||||
const { lnd } = authenticatedLndGrpc({
|
||||
cert: process.env.LND_CERT,
|
||||
macaroon: process.env.LND_MACAROON,
|
||||
socket: process.env.LND_SOCKET
|
||||
})
|
||||
|
||||
const args = { boss, models, apollo, lnd }
|
||||
|
||||
boss.on('error', error => console.error(error))
|
||||
|
||||
|
@ -50,6 +59,7 @@ async function work () {
|
|||
await boss.work('earn', earn(args))
|
||||
await boss.work('streak', computeStreaks(args))
|
||||
await boss.work('checkStreak', checkStreak(args))
|
||||
await boss.work('nip57', nip57(args))
|
||||
|
||||
console.log('working jobs')
|
||||
}
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
const { getInvoice } = require('ln-service')
|
||||
const { Relay, signId, calculateId, getPublicKey } = require('nostr')
|
||||
|
||||
const nostrOptions = { startAfter: 5, retryLimit: 21, retryBackoff: true }
|
||||
|
||||
function nip57 ({ boss, lnd }) {
|
||||
return async function ({ data: { hash } }) {
|
||||
console.log('running nip57')
|
||||
|
||||
let inv
|
||||
try {
|
||||
inv = await getInvoice({ id: hash, lnd })
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
// on lnd related errors, we manually retry which so we don't exponentially backoff
|
||||
await boss.send('nip57', { hash }, nostrOptions)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const desc = JSON.parse(inv.description)
|
||||
const ptag = desc.tags.filter(t => t?.length >= 2 && t[0] === 'p')[0]
|
||||
const etag = desc.tags.filter(t => t?.length >= 2 && t[0] === 'e')[0]
|
||||
const relays = desc.tags.find(t => t?.length >= 2 && t[0] === 'relays').slice(1)
|
||||
|
||||
const tags = [ptag]
|
||||
if (etag) {
|
||||
tags.push(etag)
|
||||
}
|
||||
tags.push(['bolt11', inv.request])
|
||||
tags.push(['description', inv.description])
|
||||
tags.push(['preimage', inv.secret])
|
||||
|
||||
const e = {
|
||||
kind: 9735,
|
||||
pubkey: getPublicKey(process.env.NOSTR_PRIVATE_KEY),
|
||||
created_at: Math.floor(new Date(inv.confirmed_at).getTime() / 1000),
|
||||
content: '',
|
||||
tags
|
||||
}
|
||||
e.id = await calculateId(e)
|
||||
e.sig = await signId(process.env.NOSTR_PRIVATE_KEY, e.id)
|
||||
|
||||
relays.forEach(r => {
|
||||
const timeout = 1000
|
||||
const relay = Relay(r)
|
||||
|
||||
function timedout () {
|
||||
relay.close()
|
||||
}
|
||||
|
||||
let timer = setTimeout(timedout, timeout)
|
||||
|
||||
relay.on('open', () => {
|
||||
clearTimeout(timer)
|
||||
timer = setTimeout(timedout, timeout)
|
||||
relay.send(['EVENT', e])
|
||||
})
|
||||
|
||||
relay.on('ok', () => {
|
||||
clearTimeout(timer)
|
||||
relay.close()
|
||||
})
|
||||
})
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
console.log('dont running nip57')
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { nip57 }
|
|
@ -1,14 +1,9 @@
|
|||
const serialize = require('../api/resolvers/serial')
|
||||
const { authenticatedLndGrpc, getInvoice, getPayment } = require('ln-service')
|
||||
const { getInvoice, getPayment } = require('ln-service')
|
||||
|
||||
const { lnd } = authenticatedLndGrpc({
|
||||
cert: process.env.LND_CERT,
|
||||
macaroon: process.env.LND_MACAROON,
|
||||
socket: process.env.LND_SOCKET
|
||||
})
|
||||
const walletOptions = { startAfter: 5, retryLimit: 21, retryBackoff: true }
|
||||
|
||||
function checkInvoice ({ boss, models }) {
|
||||
function checkInvoice ({ boss, models, lnd }) {
|
||||
return async function ({ data: { hash } }) {
|
||||
let inv
|
||||
try {
|
||||
|
@ -24,6 +19,10 @@ function checkInvoice ({ boss, models }) {
|
|||
if (inv.is_confirmed) {
|
||||
await serialize(models,
|
||||
models.$executeRaw`SELECT confirm_invoice(${inv.id}, ${Number(inv.received_mtokens)})`)
|
||||
try {
|
||||
JSON.parse(inv.description)
|
||||
await boss.send('nip57', { hash })
|
||||
} catch {}
|
||||
} else if (inv.is_canceled) {
|
||||
// mark as cancelled
|
||||
await serialize(models,
|
||||
|
@ -42,7 +41,7 @@ function checkInvoice ({ boss, models }) {
|
|||
}
|
||||
}
|
||||
|
||||
function checkWithdrawal ({ boss, models }) {
|
||||
function checkWithdrawal ({ boss, models, lnd }) {
|
||||
return async function ({ data: { id, hash } }) {
|
||||
let wdrwl
|
||||
let notFound = false
|
||||
|
|
Loading…
Reference in New Issue