1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
import config from "$config";
import { db } from "$lib/db";
import { l } from "$lib/logging";
import { fail } from "$lib/utils";
import { nip19, finalizeEvent, getPublicKey } from "nostr-tools";
import { Relay } from "nostr-tools/relay";
import { AbstractSimplePool } from "nostr-tools/abstract-pool";
export const serverPubkey = getPublicKey(
nip19.decode(config.nostrKey).data as Uint8Array,
);
let alwaysTrue: any = (t: Event) => { t[Symbol("verified")] = true; return true; };
export let pool = new AbstractSimplePool({ verifyEvent: alwaysTrue });
export async function send(ev, url = config.nostr) {
if (!(ev && ev.id)) return;
try {
let r = await Relay.connect(url);
await r.publish(ev);
r.close();
} catch (e) {
console.log("nostr send error", e);
}
}
export async function handleZap(invoice) {
let pubkey = serverPubkey;
let sk = nip19.decode(config.nostrKey).data as Uint8Array;
let zapreq = JSON.parse(invoice.description);
if (!zapreq.tags || zapreq.tags.length === 0) {
fail(`No tags found`);
}
let ptags = zapreq.tags.filter(
(t) => t && t.length && t.length >= 2 && t[0] === "p",
);
if (ptags.length !== 1) {
fail(`None or multiple p tags found`);
}
let etags = zapreq.tags.filter(
(t) => t && t.length && t.length >= 2 && t[0] === "e",
);
if (!(etags.length === 0 || etags.length === 1)) {
fail(`Expected none or 1 e tags`);
}
let relays_tag = zapreq.tags.find(
(t) => t && t.length && t.length >= 2 && t[0] === "relays",
);
if (!relays_tag) {
fail(`No relays tag found`);
}
let relays = relays_tag.slice(1).filter((r) => r && r.startsWith("ws"));
let etag = etags.length > 0 && etags[0];
let ptag = ptags[0];
let kind = 9735;
let created_at = invoice.paid_at;
let content = zapreq.content;
let tags = [ptag];
if (etag) tags.push(etag);
tags.push(["bolt11", invoice.bolt11]);
tags.push(["description", invoice.description]);
tags.push(["preimage", invoice.payment_preimage]);
let ev = { pubkey, kind, created_at, content, tags };
let signed = await finalizeEvent(ev, sk);
l("sending receipt");
await Promise.allSettled(
relays.map(async (url) => {
let r = await Relay.connect(url);
await r.publish(signed);
r.close();
}),
);
}
export let getRelays = async (pubkey): Promise<any> => {
let { relays } = config;
let filter = { authors: [pubkey], kinds: [10002] };
let event = await pool.get([config.nostr], filter);
let read = relays;
let write = relays;
if (event) {
read = [];
write = [];
for (let r of event.tags) {
if (!r[2] || r[2] === "write") write.push(r[1]);
if (!r[2] || r[2] === "read") read.push(r[1]);
}
} else pool.get(relays, filter).then(send);
return { read, write };
};
export let getProfile = async (pubkey) => {
if (await db.sIsMember("noprofile", pubkey)) return;
let relays = [config.nostr];
let filter = { authors: [pubkey], kinds: [0] };
let ev = await pool.get(relays, filter);
if (ev) {
return JSON.parse(ev.content);
} else
getRelays(pubkey).then(({ write: relays }) =>
pool.get(relays, filter).then(send),
);
};
|