aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbun.lockbbin206855 -> 206864 bytes
-rw-r--r--index.ts21
-rw-r--r--lib/nostr.ts145
-rw-r--r--package.json6
-rw-r--r--routes/nostr.ts40
-rw-r--r--tsconfig.json3
6 files changed, 122 insertions, 93 deletions
diff --git a/bun.lockb b/bun.lockb
index d09fd8a7..4e312275 100755
--- a/bun.lockb
+++ b/bun.lockb
Binary files differ
diff --git a/index.ts b/index.ts
index 8ebcb1d0..ce0723b0 100644
--- a/index.ts
+++ b/index.ts
@@ -6,20 +6,23 @@ import { getLocations } from "$lib/locations";
import { catchUp } from "$lib/payments";
import { getFx } from "$lib/rates";
import { sendHeartbeat } from "$lib/sockets";
+import { fillPool } from "$lib/nostr";
import ecash from "$routes/ecash";
import email from "$routes/email";
import info from "$routes/info";
-import locations from "$routes/locations";
-import lnurl from "$routes/lnurl";
-import rates from "$routes/rates";
import invoices from "$routes/invoices";
import items from "$routes/items";
-import users from "$routes/users";
+import lnurl from "$routes/lnurl";
+import locations from "$routes/locations";
+import nostr from "$routes/nostr";
import payments from "$routes/payments";
+import rates from "$routes/rates";
import shopify from "$routes/shopify";
+import users from "$routes/users";
try {
+ fillPool();
getLocations();
getFx();
catchUp();
@@ -41,6 +44,14 @@ app.get("/locations", locations.list);
app.get("/invoice/:id", invoices.get);
app.post("/invoice", optional, invoices.create);
+app.get("/nostr.json", nostr.identities);
+app.get("/:pubkey/followers", nostr.followers);
+app.get("/:pubkey/follows", nostr.follows);
+app.get("/:pubkey/notes", nostr.notes);
+app.get("/:pubkey/:since/messages", nostr.messages);
+app.get("/event/:id", nostr.event);
+app.post("/event", nostr.broadcast);
+
app.get("/info", payments.info);
app.post("/payments", auth, payments.create);
app.get("/payments", auth, payments.list);
@@ -101,7 +112,7 @@ app.post("/shopify/:id", shopify);
app.post("/hidepay", admin, users.hidepay);
app.post("/unlimit", admin, users.unlimit);
-app.get("/cash/:id", ecash.get);
+app.get("/cash/:id/:version", ecash.get);
app.post("/cash", ecash.save);
app.post("/claim", auth, ecash.claim);
app.post("/mint", auth, ecash.mint);
diff --git a/lib/nostr.ts b/lib/nostr.ts
index ccfb4e54..172e3ce0 100644
--- a/lib/nostr.ts
+++ b/lib/nostr.ts
@@ -1,11 +1,10 @@
import config from "$config";
import { l } from "$lib/logging";
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 { fail, nada, wait } from "$lib/utils";
+import { fail, wait } from "$lib/utils";
import { nip19 } from "nostr-tools";
+import { emit } from "$lib/sockets";
export const COINOS_PUBKEY = getPublicKey(nip19.decode(config.nostrKey).data);
export let coinos;
@@ -13,91 +12,91 @@ export let pool;
export let fillPool = () => {
try {
- pool = RelayPool(config.relays);
- pool.on("open", (relay) => {
- if (relay.url.includes(config.nostr)) coinos = relay;
- relay.subscribe("live", { limit: 1 });
- });
+ pool = RelayPool(config.relays);
+ pool.on("open", (relay) => {
+ if (relay.url.includes(config.nostr)) coinos = relay;
+ // relay.subscribe("live", { limit: 1 });
+ });
- pool.on("event", async (relay, sub, ev) => {
- if (!coinos) return;
- if (timeouts[sub]) timeouts[sub].extend(ev);
- try {
- let content;
+ pool.on("event", async (_, sub, ev) => {
+ if (!coinos && coinos.ws.readyState !== WebSocket.OPEN) return;
+ if (timeouts[sub]) timeouts[sub].extend(ev);
try {
- content = JSON.parse(ev.content);
- } catch (e) {
- content = ev.content;
- }
+ let content;
+ try {
+ content = JSON.parse(ev.content);
+ } catch (e) {
+ content = ev.content;
+ }
- if (sub === "live") {
- let { pubkey } = ev;
+ if (sub === "live") {
+ let { pubkey } = ev;
- if (Math.abs(Math.floor(Date.now() / 1000) - ev.created_at) > 7200)
- return;
+ if (Math.abs(Math.floor(Date.now() / 1000) - ev.created_at) > 7200)
+ return;
- if (seen.includes(ev.id)) return;
- seen.push(ev.id);
- seen.length > 1000 && seen.shift();
+ if (seen.includes(ev.id)) return;
+ seen.push(ev.id);
+ seen.length > 1000 && seen.shift();
- if (coinos && ev.kind < 5) {
- // coinos.send(["EVENT", ev]);
- ev.user = await getUser(pubkey);
- // broadcast("event", ev);
+ if (coinos && ev.kind < 5) {
+ // coinos.send(["EVENT", ev]);
+ ev.user = await getUser(pubkey);
+ // broadcast("event", ev);
- if (ev.kind === 4) {
- let uid = await g(`user:${ev.tags[0][1]}`);
- if (uid) ev.recipient = await g(`user:${uid}`);
- ev.author = ev.user;
- emit(uid, "event", ev);
+ if (ev.kind === 4) {
+ let uid = await g(`user:${ev.tags[0][1]}`);
+ if (uid) ev.recipient = await g(`user:${uid}`);
+ ev.author = ev.user;
+ emit(uid, "event", ev);
+ }
}
- }
- } else if (sub.includes("profile")) {
- let { pubkey } = ev;
- let user = await getUser(pubkey);
+ } else if (sub.includes("profile")) {
+ let { pubkey } = ev;
+ let user = await getUser(pubkey);
- if (user.updated > ev.created_at) return;
+ if (user.updated > ev.created_at) return;
- if (content.name && user.username === pubkey.substr(0, 6))
- user.username = content.name;
+ if (content.name && user.username === pubkey.substr(0, 6))
+ user.username = content.name;
- delete content.name;
+ delete content.name;
- user = {
- ...user,
- ...content,
- updated: ev.created_at,
- };
+ user = {
+ ...user,
+ ...content,
+ updated: ev.created_at,
+ };
- await s(`user:${pubkey}`, JSON.stringify(user));
- } else if (sub.includes("messages")) {
- let pubkey = sub.split(":")[0];
- await db.sAdd(`${pubkey}:messages`, ev.id);
- await s(`ev:${ev.id}`, ev);
- } else if (sub.includes("follows")) {
- let pubkey = sub.split(":")[0];
- await s(`${pubkey}:follows`, ev.tags);
- for (let f of ev.tags) {
- let [_, followPubkey] = f;
- await db.sAdd(`${followPubkey}:followers`, pubkey);
+ await s(`user:${pubkey}`, JSON.stringify(user));
+ } else if (sub.includes("messages")) {
+ let pubkey = sub.split(":")[0];
+ await db.sAdd(`${pubkey}:messages`, ev.id);
+ await s(`ev:${ev.id}`, ev);
+ } else if (sub.includes("follows")) {
+ let pubkey = sub.split(":")[0];
+ await s(`${pubkey}:follows`, ev.tags);
+ for (let f of ev.tags) {
+ let [_, followPubkey] = f;
+ await db.sAdd(`${followPubkey}:followers`, pubkey);
+ }
+ coinos.send(ev);
+ } else if (sub.includes("followers")) {
+ let followed = sub.split(":")[0];
+ let { pubkey } = ev;
+ await db.sAdd(`${followed}:followers`, pubkey);
+ coinos.send(ev);
+ } else if (sub.includes("notes")) {
+ let pubkey = sub.split(":")[0];
+ await db.sAdd(pubkey, ev.id);
+ await s(`ev:${ev.id}`, ev);
}
- coinos.send(ev);
- } else if (sub.includes("followers")) {
- let followed = sub.split(":")[0];
- let { pubkey } = ev;
- await db.sAdd(`${followed}:followers`, pubkey);
- coinos.send(ev);
- } else if (sub.includes("notes")) {
- let pubkey = sub.split(":")[0];
- await db.sAdd(pubkey, ev.id);
- await s(`ev:${ev.id}`, ev);
+ } catch (e) {
+ console.log(e);
}
- } catch (e) {
- console.log(e);
- }
- });
- } catch(e) {
- console.log("POOL", e)
+ });
+ } catch (e) {
+ console.log("POOL", e);
}
};
diff --git a/package.json b/package.json
index bd54dc30..b12e5fbc 100644
--- a/package.json
+++ b/package.json
@@ -3,13 +3,13 @@
"version": "0.0.1",
"private": true,
"scripts": {
- "start": "node index.js",
- "dev": "bun --stack-size=4096 --hot index.ts",
+ "start": "bun index.js",
+ "dev": "nodemon --exec bun index.ts",
"format": "biome format *.js **/*.js --write"
},
"dependencies": {
"@aws-sdk/client-ses": "^3.449.0",
- "@cashu/cashu-ts": "^1.0.1",
+ "@cashu/cashu-ts": "github:cashubtc/cashu-ts#development",
"@fastify/cors": "^8.3.0",
"@fastify/http-proxy": "^9.5.0",
"@fastify/multipart": "^8.0.0",
diff --git a/routes/nostr.ts b/routes/nostr.ts
index fdfa2613..51b4e1ea 100644
--- a/routes/nostr.ts
+++ b/routes/nostr.ts
@@ -1,10 +1,12 @@
import { bail, nada, getUser, uniq } from "$lib/utils";
-import config from "$config";
-import { g, s, db } from "$lib/db";
-import { pool, q } from "$lib/nostr";
+import { g, db } from "$lib/db";
+import { pool, q, COINOS_PUBKEY } from "$lib/nostr";
export default {
- async event({ params: { id } }, res) {
+ async event(req, res) {
+ let {
+ params: { id },
+ } = req;
let event = await g(`ev:${id}`);
if (!event) return bail(res, "event not found");
@@ -21,7 +23,10 @@ export default {
res.send(event);
},
- async notes({ params: { pubkey } }, res) {
+ async notes(req, res) {
+ let {
+ params: { pubkey },
+ } = req;
let uid = await g(`user:${pubkey}`);
let user = await g(`user:${uid}`);
@@ -51,7 +56,10 @@ export default {
res.send(events.map((e) => ({ ...e, user })));
},
- async messages({ params: { pubkey, since = 0 } }, res) {
+ async messages(req, res) {
+ let {
+ params: { pubkey, since = 0 },
+ } = req;
let params = {
kinds: [4],
authors: [pubkey],
@@ -93,7 +101,11 @@ export default {
res.send(event);
},
- async follows({ params: { pubkey }, query: { tagsonly } }, res) {
+ async follows(req, res) {
+ let {
+ params: { pubkey },
+ query: { tagsonly },
+ } = req;
try {
let sub = `${pubkey}:follows`,
params = {
@@ -142,7 +154,10 @@ export default {
}
},
- async followers({ params: { pubkey } }, res) {
+ async followers(req, res) {
+ let {
+ params: { pubkey },
+ } = req;
try {
let pubkeys = [
...new Set([...(await db.sMembers(`${pubkey}:followers`))]),
@@ -192,7 +207,10 @@ export default {
}
},
- async identities({ query: { name } }, res) {
+ async identities(req, res) {
+ let {
+ query: { name },
+ } = req;
let names = {};
if (name) {
names = { [name]: (await getUser(name)).pubkey };
@@ -207,7 +225,7 @@ export default {
res.send({ names });
},
- async info(req, res) {
+ async info(_, res) {
res.send({ pubkey: COINOS_PUBKEY });
- }
+ },
};
diff --git a/tsconfig.json b/tsconfig.json
index 60a23477..330e2915 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -23,7 +23,8 @@
"paths": {
"$lib/*": ["./lib/*.ts"],
"$routes/*": ["./routes/*.ts"],
- "$config": ["./config.ts"]
+ "$config": ["./config.ts"],
+ "@cashu/cashu-ts": ["node_modules/@cashu/cashu-ts/dist/lib/es6/index.js"]
}
}
}