aboutsummaryrefslogtreecommitdiffstats
path: root/lib/nostr.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2023-11-30 15:34:45 -0800
committerAdam Soltys <[email protected]>2023-11-30 15:34:45 -0800
commita7322928c45848cfb9984454bf8ece6e3439c673 (patch)
tree9b1031c31ee1f8160306ac66749afe0802f8aa54 /lib/nostr.js
parentacb93f29e83b35c0917d88ebbc62812e2dff989f (diff)
downloadcoinos-server-a7322928c45848cfb9984454bf8ece6e3439c673.tar.gz
coinos-server-a7322928c45848cfb9984454bf8ece6e3439c673.zip
zaps and emails
Diffstat (limited to 'lib/nostr.js')
-rw-r--r--lib/nostr.js88
1 files changed, 86 insertions, 2 deletions
diff --git a/lib/nostr.js b/lib/nostr.js
index 604d207d..3a370aec 100644
--- a/lib/nostr.js
+++ b/lib/nostr.js
@@ -1,9 +1,10 @@
import config from "$config";
-import { Relay, RelayPool } from "nostr";
+import { Relay, RelayPool, calculateId, signId, getPublicKey } from "nostr";
import { broadcast, emit } from "$lib/sockets";
import store from "$lib/store";
import { g, s, db } from "$lib/db";
-import { nada, wait } from "$lib/utils";
+import { fail, nada, wait } from "$lib/utils";
+import { nip19 } from "nostr-tools";
export let coinos;
export let pool;
@@ -178,3 +179,86 @@ let getUser = async pubkey => {
}
);
};
+
+function send(ev, url, opts) {
+ let timeout = (opts && opts.timeout != null && opts.timeout) || 1000;
+
+ return new Promise((resolve, reject) => {
+ let relay = Relay(url);
+
+ function timeout_reached() {
+ relay.close();
+ reject(new Error("Request timeout"));
+ }
+
+ let timer = setTimeout(timeout_reached, timeout);
+
+ relay.on("open", () => {
+ clearTimeout(timer);
+ timer = setTimeout(timeout_reached, timeout);
+ relay.send(["EVENT", ev]);
+ });
+
+ relay.on("ok", (evid, ok, msg) => {
+ clearTimeout(timer);
+ relay.close();
+ resolve({ evid, ok, msg });
+ });
+ });
+}
+
+export async function handleZap(invoice) {
+ let { nostrKey: privkey } = config;
+ let pubkey = getPublicKey(privkey);
+ let keypair = { privkey, pubkey };
+ 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 };
+ ev.id = await calculateId(ev);
+ ev.sig = await signId(privkey, ev.id);
+
+ await Promise.all(relays.map(r => send(ev, r)));
+}