aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2025-01-21 23:28:00 -0800
committerAdam Soltys <[email protected]>2025-01-21 23:28:00 -0800
commit9662c2754834599a1074d12565279674c20af467 (patch)
tree1d77aaedf19b035378236305af582c903e025467 /lib
parenteb4e16b5599e67a65962db2a07629dfdcdda57dc (diff)
downloadcoinos-server-9662c2754834599a1074d12565279674c20af467.tar.gz
coinos-server-9662c2754834599a1074d12565279674c20af467.zip
notes and stuff
Diffstat (limited to 'lib')
-rw-r--r--lib/lightning.ts12
-rw-r--r--lib/nostr.ts38
-rw-r--r--lib/nwc.ts2
-rw-r--r--lib/payments.ts2
-rw-r--r--lib/strfry.ts39
5 files changed, 74 insertions, 19 deletions
diff --git a/lib/lightning.ts b/lib/lightning.ts
index 19f6949d..3888a405 100644
--- a/lib/lightning.ts
+++ b/lib/lightning.ts
@@ -3,7 +3,7 @@ import ln from "$lib/ln";
import { err, warn } from "$lib/logging";
import { handleZap } from "$lib/nostr";
import { credit, types } from "$lib/payments";
-import { getPayment } from "$lib/utils";
+import { getPayment, getUser } from "$lib/utils";
export async function listenForLightning() {
const inv = await ln.waitanyinvoice((await g("pay_index")) || 0);
@@ -35,7 +35,10 @@ export async function listenForLightning() {
if (invoice?.memo) {
try {
- if (JSON.parse(description).kind === 9734) handleZap(inv);
+ if (JSON.parse(description).kind === 9734) {
+ const { pubkey } = await getUser(invoice.uid);
+ handleZap(inv, pubkey);
+ }
} catch (e) {
if (!e.message.includes("Unexpected"))
warn("failed to handle zap", e.message);
@@ -81,7 +84,10 @@ export async function replay(index) {
if (invoice?.memo) {
try {
- if (JSON.parse(description).kind === 9734) handleZap(inv);
+ if (JSON.parse(description).kind === 9734) {
+ const { pubkey } = await getUser(invoice.uid);
+ handleZap(inv, pubkey);
+ }
} catch (e) {
if (!e.message.includes("Unexpected"))
warn("failed to handle zap", e.message);
diff --git a/lib/nostr.ts b/lib/nostr.ts
index 190873e2..21c254e3 100644
--- a/lib/nostr.ts
+++ b/lib/nostr.ts
@@ -33,7 +33,7 @@ export async function send(ev, url = config.nostr) {
r.close();
}
-export async function handleZap(invoice) {
+export async function handleZap(invoice, sender = undefined) {
try {
const pubkey = serverPubkey;
const sk = nip19.decode(config.nostrKey).data as Uint8Array;
@@ -59,6 +59,10 @@ export async function handleZap(invoice) {
fail("Expected none or 1 e tags");
}
+ const atags = zapreq.tags.filter(
+ (t) => t?.length && t.length >= 2 && t[0] === "a",
+ );
+
const relays_tag = zapreq.tags.find(
(t) => t?.length && t.length >= 2 && t[0] === "relays",
);
@@ -69,6 +73,7 @@ export async function handleZap(invoice) {
const relays = relays_tag.slice(1).filter((r) => r?.startsWith("ws"));
const etag = etags.length > 0 && etags[0];
+ const atag = atags.length > 0 && atags[0];
const ptag = ptags[0];
const kind = 9735;
@@ -77,6 +82,8 @@ export async function handleZap(invoice) {
const tags = [ptag];
if (etag) tags.push(etag);
+ if (atag) tags.push(atag);
+ if (sender) tags.push(["P", sender]);
tags.push(["bolt11", invoice.bolt11]);
tags.push(["description", invoice.description]);
@@ -129,11 +136,10 @@ export const getProfile = async (pubkey) => {
let profile = await g(`profile:${pubkey}`);
if (profile) return profile;
- const filter = { authors: [pubkey], kinds: [0] };
- const events = await scan(filter);
+ const event = await get({ authors: [pubkey], kinds: [0] });
- if (events.length) {
- profile = JSON.parse(events[0].content);
+ if (event) {
+ profile = JSON.parse(event.content);
} else {
profile = anon(pubkey);
}
@@ -191,3 +197,25 @@ export const getNostrUser = async (key) => {
return pick(user, fields);
};
+
+export const q = async (f) => {
+ const events = await scan(f);
+ const k = JSON.stringify(f).replace(/[^a-zA-Z0-9]/g, "");
+ const since = await g(`${k}:since}`);
+ if (since) f.since = since;
+
+ const p = sync("wss://relay.primal.net", f).then(async () => {
+ const r = await scan(f);
+ if (r.length) await s(`${k}:since`, r[r.length - 1].created_at);
+ return r;
+ });
+
+ if (events.length > 0) return events;
+ return p;
+};
+
+export const get = async (f) => {
+ f.limit = 1;
+ const events = await q(f);
+ return events[0];
+};
diff --git a/lib/nwc.ts b/lib/nwc.ts
index 82c9870d..434e0774 100644
--- a/lib/nwc.ts
+++ b/lib/nwc.ts
@@ -113,7 +113,7 @@ const handle = (method, params, user, ev) =>
inv.payment_preimage = preimage;
inv.paid_at = Math.floor(Date.now() / 1000);
try {
- await handleZap(inv);
+ await handleZap(inv, pubkey);
} catch (e) {
console.log("zap receipt failed", e);
}
diff --git a/lib/payments.ts b/lib/payments.ts
index 5f818ae4..1468a198 100644
--- a/lib/payments.ts
+++ b/lib/payments.ts
@@ -567,7 +567,7 @@ export const sendInternal = async ({
const inv = invoices[0];
inv.payment_preimage = p.id;
inv.paid_at = Math.floor(Date.now() / 1000);
- handleZap(inv).catch(console.log);
+ handleZap(inv, sender.pubkey).catch(console.log);
}
return p;
diff --git a/lib/strfry.ts b/lib/strfry.ts
index 231e3533..926ca429 100644
--- a/lib/strfry.ts
+++ b/lib/strfry.ts
@@ -1,9 +1,10 @@
import { randomUUID } from "crypto";
import { connect, createServer } from "net";
+import type { Event } from "nostr-tools";
-const exec = async (cmd) =>
+const exec = async (cmd: string, data = ""): Promise<Event[]> =>
new Promise((resolve, reject) => {
- const c = `/app/strfry ${cmd} 2>/dev/null`;
+ const c = `${cmd} 2>/dev/null`;
const id = randomUUID();
const resultSocketPath = `/sockets/result_${id}`;
@@ -11,8 +12,8 @@ const exec = async (cmd) =>
let resultBuffer = "";
const results = [];
- socket.on("data", (data) => {
- resultBuffer += data.toString();
+ socket.on("data", (chunk) => {
+ resultBuffer += chunk.toString();
const parts = resultBuffer.split("\n");
for (let i = 0; i < parts.length - 1; i++) {
@@ -20,7 +21,7 @@ const exec = async (cmd) =>
const parsedObject = JSON.parse(parts[i]);
results.push(parsedObject);
} catch (e) {
- console.error(parts[i]);
+ console.error("Failed to parse:", parts[i]);
}
}
@@ -38,7 +39,8 @@ const exec = async (cmd) =>
resultServer.listen(resultSocketPath, () => {
const controlClient = connect("/sockets/ctrl", () => {
- const message = `${resultSocketPath} ${c}\n`;
+ // Send the command and data payload
+ const message = `${resultSocketPath} ${c}\n${data}\n`;
controlClient.write(message);
controlClient.end();
});
@@ -53,7 +55,26 @@ const exec = async (cmd) =>
});
});
-export const count = (f) => exec(`scan --count '${JSON.stringify(f)}'\n`);
-export const scan = (f) => exec(`scan '${JSON.stringify(f)}'\n`);
+// const filter2params = (f) => {
+// let r = "";
+//
+// const { limit, since, until } = f;
+//
+// if (limit) r += `-l ${limit} `;
+// if (since) r += `-s ${since} `;
+// if (until) r += `-u ${until} `;
+//
+// for (const k of f.kinds || []) r += `-k ${k} `;
+// for (const a of f.authors || []) r += `-a ${a} `;
+// for (const e of f["#e"] || []) r += `-e ${e} `;
+// for (const p of f["#p"] || []) r += `-p ${p} `;
+//
+// return r;
+// };
+
+export const load = (data) => exec(`echo '${data}' | /app/strfry import --no-verify\n`);
+export const count = (f) =>
+ exec(`/app/strfry scan --count '${JSON.stringify(f)}'\n`);
+export const scan = (f) => exec(`/app/strfry scan '${JSON.stringify(f)}'\n`);
export const sync = (r, f) =>
- exec(`sync ${r} --dir down --filter '${JSON.stringify(f)}'\n`);
+ exec(`/app/strfry sync ${r} --dir down --filter '${JSON.stringify(f)}'\n`);