diff options
| author | Adam Soltys <[email protected]> | 2025-01-16 14:57:14 -0800 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2025-01-16 14:57:14 -0800 |
| commit | ef71c296071be3081b3ac0d742283a261135ae6d (patch) | |
| tree | ad74616c3e32c306ad5c1ded6b1ecf4da85f0591 | |
| parent | 127806d1b703eb3d144e302f20268a7555f9b016 (diff) | |
| download | coinos-server-ef71c296071be3081b3ac0d742283a261135ae6d.tar.gz coinos-server-ef71c296071be3081b3ac0d742283a261135ae6d.zip | |
zap endpoints
| -rw-r--r-- | index.ts | 3 | ||||
| -rw-r--r-- | lib/nostr.ts | 41 | ||||
| -rw-r--r-- | routes/nostr.ts | 95 |
3 files changed, 102 insertions, 37 deletions
@@ -55,6 +55,9 @@ app.get("/:pubkey/followers", nostr.followers); app.get("/:pubkey/follows", nostr.follows); app.get("/event/:id", nostr.event); app.post("/event", auth, nostr.publish); +app.get("/zaps/:id", nostr.zaps); +app.post("/zap", auth, nostr.zap); +app.post("/zapRequest", auth, nostr.zapRequest); app.get("/info", payments.info); app.post("/payments", auth, payments.create); diff --git a/lib/nostr.ts b/lib/nostr.ts index 5ef8af3d..f5d85ea0 100644 --- a/lib/nostr.ts +++ b/lib/nostr.ts @@ -1,7 +1,7 @@ import config from "$config"; -import { g, s } from "$lib/db"; +import { db, g, s } from "$lib/db"; import { l } from "$lib/logging"; -import { count, scan } from "$lib/strfry"; +import { count, scan, sync } from "$lib/strfry"; import { fail } from "$lib/utils"; import { finalizeEvent, getPublicKey, nip19 } from "nostr-tools"; import { AbstractSimplePool } from "nostr-tools/abstract-pool"; @@ -125,36 +125,21 @@ export const getRelays = async (pubkey): Promise<any> => { return { read, write }; }; -export const getProfile = async (pubkey, relays = [config.nostr]) => { - let profile = await g(`${pubkey}:profile`); +export const getProfile = async (pubkey) => { + let profile = await g(`profile:${pubkey}`); + if (profile) return profile; - if (!profile) { - const pubkeys = [pubkey]; - let filter: any = { authors: pubkeys, kinds: [0] }; + const filter = { authors: [pubkey], kinds: [0] }; + const events = await scan(filter); - let ev = await pool.get(relays, filter, opts); - - if (!ev) { - ({ write: relays } = await getRelays(pubkey)); - ev = await pool.get(relays, filter, opts); - } - - if (!ev) { - filter = { cache: ["user_infos", { pubkeys }] }; - ev = (await pool.querySync([config.cache], filter, opts)).find( - (e) => e.kind === 0, - ); - } - - if (ev) { - send(ev); - profile = JSON.parse(ev.content); - } else { - profile = anon(pubkey); - } + if (events.length) { + profile = JSON.parse(events[0].content); + } else { + profile = anon(pubkey); } - await s(`${pubkey}:profile`, profile); + await db.set(`profile:${pubkey}`, JSON.stringify(profile), { EX: 300 }); + return profile; }; diff --git a/routes/nostr.ts b/routes/nostr.ts index f43f3517..21f85aea 100644 --- a/routes/nostr.ts +++ b/routes/nostr.ts @@ -1,5 +1,6 @@ import config from "$config"; import { db, g } from "$lib/db"; +import ln from "$lib/ln"; import { anon, getCount, @@ -8,24 +9,69 @@ import { send, serverPubkey, } from "$lib/nostr"; -import { scan } from "$lib/strfry"; +import { scan, sync } from "$lib/strfry"; import { bail, fail, fields, getUser } from "$lib/utils"; +import got from "got"; import { decode } from "nostr-tools/nip19"; import type { ProfilePointer } from "nostr-tools/nip19"; +import { getZapEndpoint, makeZapRequest } from "nostr-tools/nip57"; export default { async event(req, res) { - const { - params: { id }, - } = req; - const event = await g(`ev:${id}`); - if (!event) return bail(res, "event not found"); + let { id } = req.params; + if (id.startsWith("nevent")) id = decode(id).data.id; + if (id.startsWith("note")) id = decode(id).data; + const filter = { ids: [id] }; + let events = await scan(filter); + if (!events.length) { + await sync("wss://relay.primal.net", filter); + events = await scan(filter); + } + if (!events.length) return bail(res, "event not found"); + res.send(events[0]); + }, - const { pubkey } = event; + async zaps(req, res) { + try { + let { id } = req.params; + if (id.startsWith("nevent")) id = decode(id).data.id; + if (id.startsWith("note")) id = decode(id).data; + const filter = { kinds: [9735], "#e": [id] }; + let events = await scan(filter); + if (!events.length) { + await sync("wss://relay.primal.net", filter); + events = await scan(filter); + } + if (!events.length) return bail(res, "event not found"); - event.user = (await g(`user:${pubkey}`)) || anon(pubkey); + const zaps = []; + for (const { tags } of events) { + const bolt11 = tags.find((t) => t[0] === "bolt11")?.[1]; + const description = tags.find((t) => t[0] === "description")?.[1]; + const { pubkey } = JSON.parse(description); + let amount = 0; + try { + const { amount_msat } = await ln.decode(bolt11); + if (amount_msat) amount = Math.round(amount_msat / 1000); + } catch (e) {} - res.send(event); + let user; + if (pubkey) { + try { + user = await getUser(pubkey, fields); + if (!user) user = await getProfile(pubkey); + user.pubkey = pubkey; + } catch (e) {} + } + + zaps.push({ amount, user }); + } + + res.send(zaps.filter((z) => z.amount > 0)); + } catch (e) { + console.log(e); + bail(res, e.message); + } }, async publish(req, res) { @@ -180,4 +226,35 @@ export default { recipient.relays = relays; res.send(recipient); }, + + async zapRequest(req, res) { + try { + const { amount, pubkey, id } = req.body; + const event = await makeZapRequest({ + profile: pubkey, + event: id, + amount, + relays: [config.nostr], + comment: "", + }); + + res.send(event); + } catch (e) { + console.log(e); + } + }, + + async zap(req, res) { + const { event } = req.body; + const amount = event.tags.find((t) => t[0] === "amount")[1]; + const pubkey = event.tags.find((t) => t[0] === "p")[1]; + const content = JSON.stringify(await getProfile(pubkey)); + const callback = await getZapEndpoint({ content }); + const url = new URL(callback); + url.searchParams.set("amount", amount * 1000); + url.searchParams.set("nostr", encodeURIComponent(JSON.stringify(event))); + const json = await got(url.toString()).json(); + + res.send(json); + }, }; |
