aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2024-11-21 10:47:25 -0800
committerAdam Soltys <[email protected]>2024-11-21 10:47:25 -0800
commit3b15d16339c9209f307f8453af91fba15f3d340c (patch)
treed9f4ca8879c6a0b29ca8f6ad795c2154387626fd
parent5642b90b54084061cdbbf6f1dc70c38245b05d5f (diff)
downloadcoinos-server-3b15d16339c9209f307f8453af91fba15f3d340c.tar.gz
coinos-server-3b15d16339c9209f307f8453af91fba15f3d340c.zip
wip
-rwxr-xr-xbun.lockbbin208510 -> 208532 bytes
-rw-r--r--index.ts3
-rw-r--r--lib/ecash.ts20
-rw-r--r--lib/invoices.ts8
-rw-r--r--package.json2
-rw-r--r--routes/ecash.ts62
6 files changed, 81 insertions, 14 deletions
diff --git a/bun.lockb b/bun.lockb
index 41ec4eac..1d92db58 100755
--- a/bun.lockb
+++ b/bun.lockb
Binary files differ
diff --git a/index.ts b/index.ts
index 8c4b7b11..adb13863 100644
--- a/index.ts
+++ b/index.ts
@@ -56,7 +56,7 @@ app.post("/event", auth, nostr.publish);
app.get("/info", payments.info);
app.post("/payments", auth, payments.create);
app.get("/payments", auth, payments.list);
-app.get("/payments/:hash", auth, payments.get);
+app.get("/payments/:hash", payments.get);
app.post("/parse", auth, payments.parse);
app.get("/fund/:name", payments.fund);
app.get("/fund/:name/withdraw", payments.withdraw);
@@ -125,6 +125,7 @@ app.post("/unlimit", admin, users.unlimit);
app.get("/cash/:id/:version", ecash.get);
app.post("/cash", ecash.save);
+app.post("/cash/pay", ecash.pay);
app.post("/claim", auth, ecash.claim);
app.post("/mint", auth, ecash.mint);
app.post("/melt", auth, ecash.melt);
diff --git a/lib/ecash.ts b/lib/ecash.ts
index 9ea4ec38..05326718 100644
--- a/lib/ecash.ts
+++ b/lib/ecash.ts
@@ -91,3 +91,23 @@ export async function init(amount = 10000) {
}
}
+export async function payNostr(token) {
+ const decodedToken = getDecodedToken(token);
+ if (!decodedToken) {
+ console.error("could not decode token");
+ return;
+ }
+ const proofs = token.getProofs(decodedToken);
+ const mint = token.getMint(decodedToken);
+ const paymentPayload: PaymentRequestPayload = {
+ id: request.id,
+ mint: mint,
+ unit: request.unit || "",
+ proofs: proofs,
+ };
+ const paymentPayloadString = JSON.stringify(paymentPayload);
+ await nostrStore.sendNip17DirectMessageToNprofile(
+ transport.target,
+ paymentPayloadString,
+ );
+}
diff --git a/lib/invoices.ts b/lib/invoices.ts
index 0a94334c..30ae8402 100644
--- a/lib/invoices.ts
+++ b/lib/invoices.ts
@@ -13,6 +13,7 @@ const lq = rpc(config.liquid);
export const generate = async ({ invoice, user }) => {
let {
bolt11,
+ bolt12,
aid,
currency,
expiry,
@@ -71,6 +72,13 @@ export const generate = async ({ invoice, user }) => {
if (r.payee !== nodeid) fail("invalid invoice");
amount = Math.round(r.amount_msat / 1000);
r.bolt11 = bolt11;
+ } else if (bolt12) {
+ r = await ln.offer({
+ amount_msat: amount ? `${amount + tip}sat` : "any",
+ label: id,
+ description: memo || "",
+ absolute_expiry: expiry,
+ });
} else {
expiry ||= 60 * 60 * 24 * 30;
r = await ln.invoice({
diff --git a/package.json b/package.json
index d2cc9cae..593c2690 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,7 @@
},
"dependencies": {
"@aws-sdk/client-ses": "^3.449.0",
- "@cashu/cashu-ts": "^1.1.0",
+ "@cashu/cashu-ts": "^2.0.0-rc3",
"@coinos/rpc": "^0.0.6",
"@fastify/cors": "^8.3.0",
"@fastify/http-proxy": "^9.5.0",
diff --git a/routes/ecash.ts b/routes/ecash.ts
index cc617138..ff092374 100644
--- a/routes/ecash.ts
+++ b/routes/ecash.ts
@@ -1,13 +1,33 @@
import { db, g, s } from "$lib/db";
-import { check, claim, get, mint } from "$lib/ecash";
+import { check, claim, get, mint, request } from "$lib/ecash";
import { err, l } from "$lib/logging";
import { credit, debit, types } from "$lib/payments";
import { emit } from "$lib/sockets";
import { bail, fail } from "$lib/utils";
+import {
+ PaymentRequest,
+ PaymentRequestPayload,
+ PaymentRequestTransport,
+ PaymentRequestTransportType,
+ decodePaymentRequest,
+ getDecodedToken,
+} from "@cashu/cashu-ts";
import { v4 } from "uuid";
-
const { ecash: type } = types;
+const sendCash = async ({ amount, user }) => {
+ const id = v4();
+ const hash = v4();
+
+ const p = await debit({ hash, amount, user, type });
+ const token = await mint(amount);
+ p.memo = id;
+ await s(`payment:${p.id}`, p);
+ s(`cash:${id}`, token);
+
+ return { id, token };
+};
+
export default {
async save(req, res) {
const {
@@ -73,16 +93,7 @@ export default {
user,
} = req;
try {
- const id = v4();
- const hash = v4();
-
- const p = await debit({ hash, amount, user, type });
- const token = await mint(amount);
- p.memo = id;
- await s(`payment:${p.id}`, p);
- s(`cash:${id}`, token);
-
- res.send({ id });
+ res.send(await sendCash({ amount, user }));
} catch (e) {
err(e.message);
bail(res, e.message);
@@ -141,4 +152,31 @@ export default {
bail(res, e.message);
}
},
+
+ async pay(req, res) {
+ const { user } = req;
+ const { request } = req.body;
+ const { amount } = decodePaymentRequest(request);
+ const { id, token } = await sendCash({ amount, user });
+
+
+ const decodedToken = getDecodedToken(token);
+ if (!decodedToken) {
+ console.error("could not decode token");
+ return;
+ }
+ const proofs = token.getProofs(decodedToken);
+ const mint = token.getMint(decodedToken);
+ const paymentPayload: PaymentRequestPayload = {
+ id: request.id,
+ mint: mint,
+ unit: request.unit || "",
+ proofs: proofs,
+ };
+ const paymentPayloadString = JSON.stringify(paymentPayload);
+ try {
+ await nostrStore.sendNip17DirectMessageToNprofile(transport.target, paymentPayloadString);
+
+ res.send({ id, token });
+ },
};