aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2023-12-27 23:22:27 -0800
committerAdam Soltys <[email protected]>2023-12-28 22:51:02 -0800
commit02a373b8128c1544711d14ecd6ed19e20c7e3b0b (patch)
tree51327752718eac827273ada093fe6060d7184f56 /lib
parentaaf8dd49b07066e534408a2d41d84c518a45c2b6 (diff)
downloadcoinos-server-02a373b8128c1544711d14ecd6ed19e20c7e3b0b.tar.gz
coinos-server-02a373b8128c1544711d14ecd6ed19e20c7e3b0b.zip
liquid wip
Diffstat (limited to 'lib')
-rw-r--r--lib/auth.js5
-rw-r--r--lib/db.js23
-rw-r--r--lib/invoices.js4
-rw-r--r--lib/liquid.js3
-rw-r--r--lib/migrate.js52
-rw-r--r--lib/payments.js21
-rw-r--r--lib/utils.js5
7 files changed, 87 insertions, 26 deletions
diff --git a/lib/auth.js b/lib/auth.js
index 575d826e..b17a1f2d 100644
--- a/lib/auth.js
+++ b/lib/auth.js
@@ -1,3 +1,4 @@
+import migrate from "$lib/migrate";
import fastifyPassport from "@fastify/passport";
import { g } from "$lib/db";
import config from "$config";
@@ -36,8 +37,10 @@ export const jwtStrategy = new jwt.Strategy(
async (payload, next) => {
let user;
if (payload.id) {
- user = await g(`user:${payload.id}`);
+ let { id } = payload;
+ user = await g(`user:${id}`);
if (typeof user === "string") user = await g(`user:${user}`);
+ if (!user) migrate(id);
}
next(null, user);
diff --git a/lib/db.js b/lib/db.js
index d14e4962..c44c7177 100644
--- a/lib/db.js
+++ b/lib/db.js
@@ -41,16 +41,33 @@ export let db = createClient({
},
});
-async function connectWithRetry() {
+export let archive = createClient({
+ url: config.archive,
+ socket: {
+ reconnectStrategy: (retries) => Math.min(retries * 50, 5000),
+ },
+});
+
+async function dbReconnect() {
try {
await db.connect();
} catch (err) {
console.error("Failed to connect to Redis, retrying...", err);
- setTimeout(connectWithRetry, 5000); // Retry after 5 seconds
+ setTimeout(dbReconnect, 5000); // Retry after 5 seconds
+ }
+}
+
+async function archiveReconnect() {
+ try {
+ await archive.connect();
+ } catch (err) {
+ console.error("Failed to connect to Redis, retrying...", err);
+ setTimeout(archiveReconnect, 5000); // Retry after 5 seconds
}
}
-connectWithRetry();
+dbReconnect();
+archiveReconnect();
db.on("error", (e) => {
if (e.message.startsWith("getaddr")) return;
diff --git a/lib/invoices.js b/lib/invoices.js
index 23af1aa4..b5718e23 100644
--- a/lib/invoices.js
+++ b/lib/invoices.js
@@ -6,6 +6,7 @@ import { getUser, bip21, fail, SATS } from "$lib/utils";
import { types } from "$lib/payments";
import { v4 } from "uuid";
+import lq from "$lib/liquid";
import bc from "$lib/bitcoin";
import ln from "$lib/ln";
@@ -54,6 +55,9 @@ export let generate = async ({ invoice, user, sender, memo }) => {
} else if (type === types.bitcoin) {
hash = await bc.getNewAddress();
text = bip21(hash, invoice);
+ } else if (type === types.liquid) {
+ hash = await lq.getNewAddress();
+ text = bip21(hash, invoice);
} else if (type === types.internal) {
hash = id;
} else {
diff --git a/lib/liquid.js b/lib/liquid.js
new file mode 100644
index 00000000..ec8ec7cb
--- /dev/null
+++ b/lib/liquid.js
@@ -0,0 +1,3 @@
+import config from "$config";
+import rpc from "$lib/rpc";
+export default rpc(config.liquid);
diff --git a/lib/migrate.js b/lib/migrate.js
new file mode 100644
index 00000000..e8ae5993
--- /dev/null
+++ b/lib/migrate.js
@@ -0,0 +1,52 @@
+import { archive, db, g } from "$lib/db";
+
+export default async (id) => {
+ let user = JSON.parse(await archive.get(`user:${id}`));
+
+ if (typeof user === "string") {
+ id = user;
+ user = JSON.parse(await archive.get(`user:${id}`));
+ }
+
+ if (user) {
+ let multi = await db
+ .multi()
+ .set(`user:${user.username}`, id)
+ .set(`user:${user.pubkey}`, id)
+ .set(`user:${id}`, JSON.stringify(user))
+ .set(`${id}:contacts`, await archive.get(`${id}:contacts`))
+ .set(`credit:bitcoin:${id}`, await archive.get(`credit:bitcoin:${id}`) || 0)
+ .set(
+ `credit:lightning:${id}`,
+ await archive.get(`credit:lightning:${id}`) || 0,
+ )
+ .set(`${id}:lastlen`, (await archive.get(`${id}:lastlen`)) || 0)
+ .set(`${id}:cindex`, (await archive.get(`${id}:cindex`)) || 0)
+ .set(`balance:${id}`, (await archive.get(`balance:${id}`)) || 0)
+ .set(`pending:${id}`, (await archive.get(`pending:${id}`)) || 0);
+
+ let payments = await archive.lRange(`${id}:payments`, 0, -1);
+ await Promise.all(
+ payments.map(async (pid) => {
+ let p = await archive.get(`payment:${pid}`);
+ multi = await multi
+ .lPush(`${id}:payments`, pid)
+ .set(`payment:${pid}`, p);
+ }),
+ );
+
+ let invoices = await archive.lRange(`${id}:invoices`, 0, -1);
+ await Promise.all(
+ invoices.map(async (iid) => {
+ let inv = await archive.get(`invoice:${iid}`);
+ multi = await multi
+ .lPush(`${id}:invoices`, iid)
+ .set(`invoice:${iid}`, inv);
+ }),
+ );
+
+ await multi.exec();
+
+ return user;
+ }
+};
diff --git a/lib/payments.js b/lib/payments.js
index 604a78d8..e0aff192 100644
--- a/lib/payments.js
+++ b/lib/payments.js
@@ -23,6 +23,7 @@ export const types = {
lightning: "lightning",
fund: "fund",
classic: "classic",
+ liquid: "liquid",
};
export let debit = async ({
@@ -208,26 +209,6 @@ export let credit = async (hash, amount, memo, ref, type = types.internal) => {
return p;
};
-export let confirm = async (address, txid, vout) => {
- let id = `payment:${txid}:${vout}`;
- let p = await g(id);
- if (typeof p === "string") p = await g(`payment:${p}`);
- if (!p) return db.sAdd("missed", id);
- if (p.confirmed) return;
-
- p.confirmed = true;
- emit(p.uid, "payment", p);
-
- l("confirming", txid);
-
- let r = await db
- .multi()
- .set(`payment:${p.id}`, JSON.stringify(p))
- .decrBy(`pending:${p.uid}`, p.amount)
- .incrBy(`balance:${p.uid}`, p.amount)
- .exec();
-};
-
export let payLightning = async (user, payreq, amount, maxfee, memo) => {
let p;
let hash = payreq;
diff --git a/lib/utils.js b/lib/utils.js
index 1e12214b..0c382a0c 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -27,8 +27,9 @@ export const uniq = (a, k) => [...new Map(a.map((x) => [k(x), x])).values()];
export const pick = (O, K) =>
K.reduce((o, k) => (typeof O[k] !== "undefined" && (o[k] = O[k]), o), {});
-export const bip21 = (address, { amount, memo, tip }) => {
- let url = amount || memo ? `bitcoin:${address}?` : address;
+export const bip21 = (address, { amount, memo, tip, type }) => {
+ let network = { liquid: "liquidnetwork", bitcoin: "bitcoin" }[type];
+ let url = amount || memo ? `${network}:${address}?` : address;
if (amount)
url += `amount=${((amount + tip) / SATS).toFixed(8)}${memo ? "&" : ""}`;
if (memo) url += `message=${memo}`;