aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2023-01-26 11:26:05 -0800
committerAdam Soltys <[email protected]>2023-01-26 11:26:09 -0800
commitf0543b6d94081f43a265bb9f754a654df9c4268a (patch)
treec2fee79d8e410a2b6914f2dd53d7abef19497e39
parent143490db49b6d67e9ddb2c59ea92ae923d08911c (diff)
downloadcoinos-server-f0543b6d94081f43a265bb9f754a654df9c4268a.tar.gz
coinos-server-f0543b6d94081f43a265bb9f754a654df9c4268a.zip
sample notify script
-rw-r--r--lib/db.js12
-rw-r--r--lib/payments.js31
-rw-r--r--lib/upload.js20
-rw-r--r--lib/whitelist.js1
-rw-r--r--routes/payments.js12
-rw-r--r--sampledata/bitcoin/bitcoin.conf1
-rwxr-xr-xsampledata/bitcoin/transaction.sh2
7 files changed, 47 insertions, 32 deletions
diff --git a/lib/db.js b/lib/db.js
index acc4bff1..516db236 100644
--- a/lib/db.js
+++ b/lib/db.js
@@ -11,16 +11,9 @@ export let s = (k, v) => db.set(k, JSON.stringify(v));
let retries = {};
export let t = async (k, f) => {
- let result;
try {
- result = await db.executeIsolated(async db => {
- await db.watch(k);
- let v = await db.get(k);
- await db
- .multi()
- .set(k, await f(v))
- .exec();
- });
+ await db.watch(k);
+ await f(await db.get(k), db);
} catch (err) {
if (!err.message.includes("watch")) throw err;
@@ -37,5 +30,4 @@ export let t = async (k, f) => {
}
delete retries[k];
- return result;
};
diff --git a/lib/payments.js b/lib/payments.js
index 386d84d8..d0593447 100644
--- a/lib/payments.js
+++ b/lib/payments.js
@@ -34,16 +34,30 @@ export let debit = async (
if (!amount || amount < 0) fail("Amount must be greater than zero");
- await t(`balance:${uid}`, async balance => {
- await new Promise(r => setTimeout(r, 100));
- if (balance < amount) fail("Insufficient funds");
- return balance - amount;
+ let ourfee = Math.round(amount * config.fee);
+ await t(`balance:${uid}`, async (balance, db) => {
+ await t(`credit:${type}:${uid}`, async (credit, db) => {
+ let covered = Math.min(credit, ourfee) || 0;
+ ourfee -= covered;
+
+ if (balance < amount + ourfee) fail("Insufficient funds");
+ await db
+ .multi()
+ .decrBy(`credit:${type}:${uid}`, covered)
+ .exec();
+ });
+
+ await db
+ .multi()
+ .decrBy(`balance:${uid}`, amount + (ourfee - credit))
+ .exec();
});
let p = {
id,
amount: -amount,
fee,
+ ourfee,
memo,
uid,
confirmed: true,
@@ -103,9 +117,12 @@ export let credit = async (hash, amount, memo, ref, type = types.internal) => {
p.id = hash;
}
- await db
- .multi()
- .set(`invoice:${hash}`, JSON.stringify(invoice))
+ let m = await db.multi();
+
+ if ([types.bitcoin, types.lightning].includes(type))
+ m.incrBy(`credit:${type}:${uid}`, Math.round(amount * config.fee));
+
+ m.set(`invoice:${hash}`, JSON.stringify(invoice))
.set(`payment:${p.id}`, JSON.stringify(p))
.lPush(`${uid}:payments`, p.id)
.incrBy(`${balance}:${uid}`, amount)
diff --git a/lib/upload.js b/lib/upload.js
index fbf9ce20..5f5aebed 100644
--- a/lib/upload.js
+++ b/lib/upload.js
@@ -5,12 +5,16 @@ import fs from "fs";
import path from "path";
import sharp from "sharp";
import { pipeline } from "stream";
-import { g, s } from "$lib/db";
+import { g, s, db } from "$lib/db";
-export default async ({ params: { type }, file, user }, res) => {
+export default async (req, res) => {
+ let {
+ params: { type },
+ user
+ } = req;
if (!["banner", "profile"].includes(type)) throw new Error("invalid upload");
- let data = await file();
+ let data = await req.file();
let s1 = new Clone(data.file);
let s2 = new Clone(data.file);
@@ -30,14 +34,8 @@ export default async ({ params: { type }, file, user }, res) => {
await new Promise(r => pipeline(s2, t, fs.createWriteStream(path), r));
- let r = async () => {
- await db.watch(`user:${user.id}`);
- user = await g(`user:${user.id}`);
- user[type] = true;
- let m = await db.multi();
- await s(`user:${user.id}`, user);
- };
- await r();
+ user[type] = true;
+ await s(`user:${user.id}`, user);
res.send(name);
};
diff --git a/lib/whitelist.js b/lib/whitelist.js
index 77243855..850dffc0 100644
--- a/lib/whitelist.js
+++ b/lib/whitelist.js
@@ -14,6 +14,7 @@ export default [
"haspin",
"id",
"index",
+ "linked",
"keys",
"locktime",
"payments",
diff --git a/routes/payments.js b/routes/payments.js
index a060d90a..ca32e969 100644
--- a/routes/payments.js
+++ b/routes/payments.js
@@ -111,9 +111,12 @@ export default {
async take({ body: { name, amount }, user }, res) {
amount = parseInt(amount);
- await t(`pot:${name}`, async balance => {
+ await t(`pot:${name}`, async (balance, db) => {
if (balance < amount) fail("Insufficient funds");
- return balance - amount;
+ await db
+ .multi()
+ .decrBy(`pot:${name}`, amount)
+ .exec();
});
let hash = v4();
@@ -211,10 +214,11 @@ export default {
total = total - change + fee;
let amount = total - fee;
+ if (change && !amount) fail("Cannot send to unregistered coinos address");
+
await debit(txid, amount, fee, null, user, types.bitcoin, txid);
await bc.sendRawTransaction(hex);
res.send({ txid });
- },
-
+ }
};
diff --git a/sampledata/bitcoin/bitcoin.conf b/sampledata/bitcoin/bitcoin.conf
index 5da37e5a..3aa44186 100644
--- a/sampledata/bitcoin/bitcoin.conf
+++ b/sampledata/bitcoin/bitcoin.conf
@@ -16,6 +16,7 @@ rpcwallet=coinos
wallet=coinos
wallet=external
+walletnotify=/home/bitcoin/.bitcoin/transaction.sh %s %w
zmqpubrawblock=tcp://0.0.0.0:18506
zmqpubrawtx=tcp://0.0.0.0:18507
diff --git a/sampledata/bitcoin/transaction.sh b/sampledata/bitcoin/transaction.sh
new file mode 100755
index 00000000..e44789d1
--- /dev/null
+++ b/sampledata/bitcoin/transaction.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+wget -O- --post-data='{"txid": "'$1'", "wallet": "'$2'"}' --header='Content-Type:application/json' 'http://app:3119/bitcoin'