aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2024-09-18 12:29:20 -0700
committerAdam Soltys <[email protected]>2024-09-18 12:29:20 -0700
commit0b2f9a963ed2503ac611eab3d8bd5b640ebe08f2 (patch)
treed6d41e5cedf76835dd491928ee0b58ede03a0fd6
parentc28a1b61881c34fcc1228d4600f5bb4aa0b81b53 (diff)
downloadcoinos-server-0b2f9a963ed2503ac611eab3d8bd5b640ebe08f2.tar.gz
coinos-server-0b2f9a963ed2503ac611eab3d8bd5b640ebe08f2.zip
refactor nwc
-rw-r--r--index.ts2
-rw-r--r--lib/nostr.ts107
-rw-r--r--lib/nwc.ts117
-rw-r--r--routes/lnurl.ts4
-rw-r--r--routes/nostr.ts4
5 files changed, 128 insertions, 106 deletions
diff --git a/index.ts b/index.ts
index c9a6f90c..885cbf2e 100644
--- a/index.ts
+++ b/index.ts
@@ -7,6 +7,7 @@ import { catchUp } from "$lib/payments";
import { getFx } from "$lib/rates";
import { sendHeartbeat } from "$lib/sockets";
import { fillPool } from "$lib/nostr";
+import nwc from "$lib/nwc";
import ecash from "$routes/ecash";
import email from "$routes/email";
@@ -26,6 +27,7 @@ try {
getLocations();
getFx();
catchUp();
+ nwc();
} catch (e) {
console.log(e);
}
diff --git a/lib/nostr.ts b/lib/nostr.ts
index bb47696b..f6e04b8c 100644
--- a/lib/nostr.ts
+++ b/lib/nostr.ts
@@ -1,18 +1,16 @@
import config from "$config";
-import { l, err } from "$lib/logging";
+import { l } from "$lib/logging";
import { Relay, RelayPool, calculateId, signId, getPublicKey } from "nostr";
import { g, s, db } from "$lib/db";
-import { fail, getInvoice, sleep, wait } from "$lib/utils";
-import { nip04, nip19, finalizeEvent } from "nostr-tools";
-import type { UnsignedEvent } from "nostr-tools";
+import { fail, wait } from "$lib/utils";
+import { nip19 } from "nostr-tools";
import { emit } from "$lib/sockets";
-import { sendInternal, sendLightning } from "$lib/payments";
-import ln from "$lib/ln";
import { hex } from "@scure/base";
-export const COINOS_PUBKEY = hex.encode(
+export const serverPubkey = hex.encode(
getPublicKey(nip19.decode(config.nostrKey).data),
);
+
export let coinos;
export let pool;
@@ -274,98 +272,3 @@ export async function handleZap(invoice) {
await Promise.allSettled(relays.map((r) => send(ev, r)));
}
-
-let r = new Relay("ws://strfry:7777");
-r.on("open", (_) => {
- r.subscribe("nwc", { kinds: [23194], "#p": [COINOS_PUBKEY] });
-});
-
-r.on("event", async (sub, ev) => {
- try {
- if (sub !== "nwc") return;
- let { content, pubkey } = ev;
- let sk = nip19.decode(config.nostrKey).data as Uint8Array;
- let { params, method } = JSON.parse(
- await nip04.decrypt(sk, pubkey, content),
- );
-
- let uid = await g(pubkey);
- let user = await g(`user:${uid}`);
-
- let ret = { result_type: method, result: undefined, error: undefined };
-
- if (method === "pay_invoice") {
- let { invoice: pr } = params;
- let { amount_msat, payee } = await ln.decode(pr);
- let { id } = await ln.getinfo();
- let amount = Math.round(amount_msat / 1000);
-
- if (payee === id) {
- let invoice = await getInvoice(pr);
- let recipient = await g(`user:${invoice.uid}`);
-
- await sendInternal({
- amount,
- invoice,
- recipient,
- sender: user,
- });
-
- ret.result = { preimage: recipient.id};
- } else {
- await sendLightning({
- amount,
- user,
- pr,
- maxfee: 50,
- });
-
- for (let i = 0; i < 10; i++) {
- let { pays } = await ln.listpays(pr);
- let p = pays.find((p) => p.status === "complete");
- if (p) {
- let { preimage } = p;
- ret.result = { preimage };
- break;
- }
- await sleep(2000);
- }
-
- if (!ret.result)
- ret.error = { code: "INTERNAL", message: "Payment timed out" };
- }
- } else if (method === "get_info") {
- let { alias, blockheight, color } = await ln.getinfo();
- ret.result = {
- alias,
- color,
- pubkey: COINOS_PUBKEY,
- network: "mainnet",
- block_height: blockheight,
- methods: ["pay_invoice", "get_balance", "get_info"],
- };
- } else if (method === "get_balance") {
- ret.result = {
- balance: await g(`balance:${uid}`),
- };
- }
-
- content = await nip04.encrypt(sk, pubkey, JSON.stringify(ret));
-
- let response: UnsignedEvent = {
- created_at: Math.floor(Date.now() / 1000),
- kind: 23195,
- pubkey: COINOS_PUBKEY,
- tags: [
- ["p", pubkey],
- ["e", ev.id],
- ],
- content,
- };
-
- response = await finalizeEvent(response, sk);
- r.send(["EVENT", response]);
- } catch (e) {
- err("problem with nwc", e.message);
- }
-});
diff --git a/lib/nwc.ts b/lib/nwc.ts
new file mode 100644
index 00000000..d8323495
--- /dev/null
+++ b/lib/nwc.ts
@@ -0,0 +1,117 @@
+import config from "$config";
+import { err } from "$lib/logging";
+import { g } from "$lib/db";
+import { Relay } from "nostr";
+import { getInvoice, sleep } from "$lib/utils";
+import { sendInternal, sendLightning } from "$lib/payments";
+import { serverPubkey } from "$lib/nostr";
+import { nip04, nip19, finalizeEvent } from "nostr-tools";
+import type { UnsignedEvent } from "nostr-tools";
+import ln from "$lib/ln";
+
+let result = (result) => ({ result });
+let error = (error) => ({ error });
+
+export default () => {
+ let r = new Relay("ws://strfry:7777");
+
+ r.on("open", (_) => {
+ r.subscribe("nwc", { kinds: [23194], "#p": [serverPubkey] });
+ });
+
+ r.on("event", async (sub, ev) => {
+ try {
+ if (sub !== "nwc") return;
+ let { content, pubkey } = ev;
+ let sk = nip19.decode(config.nostrKey).data as Uint8Array;
+ let { params, method } = JSON.parse(
+ await nip04.decrypt(sk, pubkey, content),
+ );
+
+ let uid = await g(pubkey);
+ let user = await g(`user:${uid}`);
+
+ let result = await handle(method, params, user);
+ let payload = JSON.stringify({ result_type: method, result });
+ content = await nip04.encrypt(sk, pubkey, payload);
+
+ let response: UnsignedEvent = {
+ created_at: Math.floor(Date.now() / 1000),
+ kind: 23195,
+ pubkey: serverPubkey,
+ tags: [
+ ["p", pubkey],
+ ["e", ev.id],
+ ],
+ content,
+ };
+
+ response = await finalizeEvent(response, sk);
+ r.send(["EVENT", response]);
+ } catch (e) {
+ err("problem with nwc", e.message);
+ }
+ });
+};
+
+let handle = (method, params, user) =>
+ ({
+ async pay_invoice() {
+ let { invoice: pr } = params;
+ let { amount_msat, payee } = await ln.decode(pr);
+ let { id } = await ln.getinfo();
+ let amount = Math.round(amount_msat / 1000);
+
+ if (payee === id) {
+ let invoice = await getInvoice(pr);
+ let recipient = await g(`user:${invoice.uid}`);
+
+ let { id: preimage } = await sendInternal({
+ amount,
+ invoice,
+ recipient,
+ sender: user,
+ });
+
+ return result({ preimage });
+ } else {
+ await sendLightning({
+ amount,
+ user,
+ pr,
+ maxfee: 50,
+ });
+
+ for (let i = 0; i < 10; i++) {
+ let { pays } = await ln.listpays(pr);
+ let p = pays.find((p) => p.status === "complete");
+ if (p) {
+ let { preimage } = p;
+ return result({ preimage });
+ }
+ await sleep(2000);
+ }
+
+ return error({ code: "INTERNAL", message: "Payment timed out" });
+ }
+ },
+
+ async get_info() {
+ let { alias, blockheight, color } = await ln.getinfo();
+ return {
+ result: {
+ alias,
+ color,
+ pubkey: serverPubkey,
+ network: "mainnet",
+ block_height: blockheight,
+ methods: ["pay_invoice", "get_balance", "get_info"],
+ },
+ };
+ },
+
+ async get_balance() {
+ let balance = await g(`balance:${user.id}`);
+ return result({ balance });
+ },
+ })[method](params);
diff --git a/routes/lnurl.ts b/routes/lnurl.ts
index 5a9c0990..59fc6ba1 100644
--- a/routes/lnurl.ts
+++ b/routes/lnurl.ts
@@ -6,7 +6,7 @@ import got from "got";
import { generate } from "$lib/invoices";
import { bech32 } from "bech32";
import { types } from "$lib/payments";
-import { COINOS_PUBKEY } from "$lib/nostr";
+import { serverPubkey } from "$lib/nostr";
let { URL } = process.env;
let host = URL.split("/").at(-1);
@@ -68,7 +68,7 @@ export default {
minSendable,
maxSendable,
metadata,
- nostrPubkey: COINOS_PUBKEY,
+ nostrPubkey: serverPubkey,
callback: `${URL}/api/lnurl/${id}`,
tag: "payRequest",
});
diff --git a/routes/nostr.ts b/routes/nostr.ts
index 51b4e1ea..9bbff33d 100644
--- a/routes/nostr.ts
+++ b/routes/nostr.ts
@@ -1,6 +1,6 @@
import { bail, nada, getUser, uniq } from "$lib/utils";
import { g, db } from "$lib/db";
-import { pool, q, COINOS_PUBKEY } from "$lib/nostr";
+import { pool, q, serverPubkey } from "$lib/nostr";
export default {
async event(req, res) {
@@ -226,6 +226,6 @@ export default {
},
async info(_, res) {
- res.send({ pubkey: COINOS_PUBKEY });
+ res.send({ pubkey: serverPubkey });
},
};