Add nip57

This commit is contained in:
Jonathan Staab 2023-09-09 11:41:48 -07:00
parent 70c94f9aa9
commit d5c4fcd227
5 changed files with 148 additions and 2 deletions

View File

@ -95,7 +95,6 @@ export type Handle = {
}
export type Zapper = {
pubkey: string
lnurl: string
callback: string
minSendable: number
@ -117,7 +116,7 @@ export type Person = {
handle_updated_at?: number
handle: Handle
zapper_updated_at?: number
zapper: Handle
zapper: Zapper
}
export type Channel = {

View File

@ -2,6 +2,7 @@ import "./nip02"
import "./nip05"
import "./nip24"
import "./nip28"
import "./nip57"
import "./nip65"
import "./alerts"

View File

@ -0,0 +1,56 @@
import {Fetch, tryFunc} from "hurdak"
import {tryJson, hexToBech32, bech32ToHex} from "src/util/misc"
import {people} from "src/engine2/state"
import {dufflepud} from "src/engine2/queries"
import {projections, updateKey} from "src/engine2/projections/core"
projections.addHandler(0, e => {
tryJson(async () => {
const {
kind0: {lud16, lud06},
} = JSON.parse(e.content)
const address = (lud16 || lud06 || "").toLowerCase()
if (!address) {
return
}
const lnurl = getLnUrl(address)
if (!lnurl) {
return
}
const result = await tryFunc(() => Fetch.postJson(dufflepud("zapper/info"), {lnurl}))
if (!result?.allowsNostr || !result?.nostrPubkey) {
return
}
updateKey(people.key(e.pubkey), e.created_at, {
zapper: {
lnurl: hexToBech32("lnurl", lnurl),
callback: result.callback,
minSendable: result.minSendable,
maxSendable: result.maxSendable,
nostrPubkey: result.nostrPubkey,
},
})
})
})
function getLnUrl(address: string): string {
// Try to parse it as a lud06 LNURL
if (address.startsWith("lnurl1")) {
return tryFunc(() => bech32ToHex(address)) as string
}
// Try to parse it as a lud16 address
if (address.includes("@")) {
const [name, domain] = address.split("@")
if (domain && name) {
return `https://${domain}/.well-known/lnurlp/${name}`
}
}
}

View File

@ -1,6 +1,8 @@
export * from "./session"
export * from "./settings"
export * from "./nip02"
export * from "./nip05"
export * from "./nip57"
export * from "./nip65"
export * from "./alerts"
export * from "./channels"

View File

@ -0,0 +1,88 @@
import {Fetch} from "hurdak"
import {tryJson} from "src/util/misc"
import {invoiceAmount} from "src/util/lightning"
import {warn} from "src/util/logger"
import {Tags} from "src/util/nostr"
import type {Event, ZapEvent} from "src/engine2/model"
import {people} from "src/engine2/state"
export function processZaps(zaps: Event[], pubkey: string) {
const {zapper} = people.key(pubkey).get() || {}
if (!zapper) {
return []
}
return zaps
.map((zap: Event) => {
const zapMeta = Tags.from(zap).asMeta() as {
bolt11: string
description: string
}
return tryJson(() => ({
...zap,
invoiceAmount: invoiceAmount(zapMeta.bolt11),
request: JSON.parse(zapMeta.description),
})) as ZapEvent
})
.filter((zap: ZapEvent) => {
if (!zap) {
return false
}
// Don't count zaps that the user sent himself
if (zap.request.pubkey === pubkey) {
return false
}
const {invoiceAmount, request} = zap
const reqMeta = Tags.from(request).asMeta() as {
amount?: string
lnurl?: string
}
// Verify that the zapper actually sent the requested amount (if it was supplied)
if (reqMeta.amount && parseInt(reqMeta.amount) !== invoiceAmount) {
return false
}
// If the sending client provided an lnurl tag, verify that too
if (reqMeta.lnurl && reqMeta.lnurl !== zapper.lnurl) {
return false
}
// Verify that the zap note actually came from the recipient's zapper
if (zapper.nostrPubkey !== zap.pubkey) {
return false
}
return true
})
}
export async function fetchInvoice(zapper, event, amount) {
const {callback, lnurl} = zapper
const s = encodeURI(JSON.stringify(event))
const res = await Fetch.fetchJson(`${callback}?amount=${amount}&nostr=${s}&lnurl=${lnurl}`)
if (!res.pr) {
warn(JSON.stringify(res))
}
return res?.pr
}
export async function collectInvoice(invoice) {
const {webln} = window as {webln?: any}
if (webln) {
await webln.enable()
try {
webln.sendPayment(invoice)
} catch (e) {
warn(e)
}
}
}