aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2024-09-24 12:30:51 -0700
committerAdam Soltys <[email protected]>2024-09-24 12:30:51 -0700
commit80365c227c5a774ad65f5dad8b989e1966630160 (patch)
treea9d6cd130e48e815fb60b91263c5d9b5a83b8808 /lib
parent8c8c71d54d23960ffc4caa94619bae7c6a69514b (diff)
downloadcoinos-server-80365c227c5a774ad65f5dad8b989e1966630160.tar.gz
coinos-server-80365c227c5a774ad65f5dad8b989e1966630160.zip
reconcile onchain balance
Diffstat (limited to 'lib')
-rw-r--r--lib/invoices.ts5
-rw-r--r--lib/payments.ts72
-rw-r--r--lib/register.ts20
3 files changed, 83 insertions, 14 deletions
diff --git a/lib/invoices.ts b/lib/invoices.ts
index 60bcba0f..d7f09de5 100644
--- a/lib/invoices.ts
+++ b/lib/invoices.ts
@@ -51,13 +51,15 @@ export let generate = async ({ invoice, user }) => {
let id = v4();
- let hash, text;
+ let hash, text, path;
if (account.seed) {
type = "bitcoin";
let node = rpc({ ...config[type], wallet: aid });
hash = await node.getNewAddress();
text = bip21(hash, invoice);
+
+ ({ hdkeypath: path } = await node.getAddressInfo(hash));
} else if (type === types.lightning) {
let r;
if (bolt11) {
@@ -107,6 +109,7 @@ export let generate = async ({ invoice, user }) => {
received: 0,
request_id,
memoPrompt,
+ path,
prompt,
secret,
text,
diff --git a/lib/payments.ts b/lib/payments.ts
index 6d83b28f..9d2d9b79 100644
--- a/lib/payments.ts
+++ b/lib/payments.ts
@@ -11,6 +11,7 @@ import {
fail,
fiat,
getInvoice,
+ getUser,
sleep,
SATS,
sats,
@@ -154,7 +155,7 @@ export let credit = async ({
return;
}
- let { tip } = inv;
+ let { path, tip } = inv;
tip = parseInt(tip) || 0;
if (!memo) ({ memo } = inv);
@@ -162,7 +163,7 @@ export let credit = async ({
if (amount < 0 || tip < 0) fail("Invalid amount");
if (type === types.internal) amount += tip;
- let user = await g(`user:${inv.uid}`);
+ let user = await getUser(inv.uid);
let { id: uid, currency, username } = user;
let rates = await g("rates");
@@ -186,6 +187,7 @@ export let credit = async ({
iid: inv.id,
hash,
amount: amount - tip,
+ path,
uid,
rate,
currency,
@@ -319,7 +321,7 @@ export let completePayment = async (p, user) => {
};
let pay = async ({ aid = undefined, amount, to, user }) => {
- if (!aid) aid = user.id;
+ if (!aid) aid = user.id;
amount = parseInt(amount) || 0;
let lnurl, pr;
if (to.includes("@") && to.includes(".")) {
@@ -440,6 +442,7 @@ export let sendOnchain = async (params) => {
let amount = total - change;
+ console.log("debiting", aid, amount);
let p = await debit({
aid,
hash: txid,
@@ -613,7 +616,6 @@ export let sendInternal = async ({
invoice = await generate({
invoice: { amount, type: "lightning" },
user: recipient,
- sender,
});
let { hash } = invoice;
@@ -718,11 +720,16 @@ export let build = async ({
let { vin } = await node.decodeRawTransaction(tx.hex);
for (let { txid, vout } of vin) {
- let nonWitnessUtxo = await node.getRawTransaction(txid);
- let tx = await node.decodeRawTransaction(nonWitnessUtxo);
- let { address } = tx.vout[vout].scriptPubKey;
+ let rawTx = await node.getRawTransaction(txid);
+ let tx = await node.decodeRawTransaction(rawTx);
+ let prevOutput = tx.vout[vout];
+ let { address } = prevOutput.scriptPubKey;
let { hdkeypath: path } = await node.getAddressInfo(address);
- inputs.push({ nonWitnessUtxo, path });
+ let witnessUtxo = {
+ amount: Math.round(prevOutput.value * SATS),
+ script: prevOutput.scriptPubKey.hex,
+ };
+ inputs.push({ witnessUtxo, path });
}
return { feeRate, ourfee, fee, fees, hex: tx.hex, inputs };
@@ -760,3 +767,52 @@ export let catchUp = async () => {
setTimeout(catchUp, 10000);
};
+
+export let reconcile = async (account) => {
+ let { descriptors, id, uid, type } = account;
+ let user = await getUser(uid);
+ let node = rpc({ ...config[type], wallet: id });
+ let { total_amount } = await node.scanTxOutSet("start", descriptors);
+ let total = Math.round(total_amount * SATS);
+ let { balanceAdjustment: memo } = t(user);
+
+ let balance = await g(`balance:${id}`);
+
+ let inflight = 0;
+ for (let pid of await db.sMembers(`inflight:${id}`)) {
+ let p = await g(`payment:${pid}`);
+ inflight += Math.abs(p.amount) + p.fee;
+ }
+
+ balance += inflight;
+
+ let amount = Math.abs(total - balance);
+ let hash = v4();
+
+ if (total > balance) {
+ let inv = {
+ memo,
+ type: types.reconcile,
+ hash,
+ amount,
+ uid,
+ aid: id,
+ };
+ await s(`invoice:${hash}`, inv);
+ await credit({
+ hash,
+ amount,
+ type: types.reconcile,
+ aid: id,
+ });
+ } else if (total < balance) {
+ await debit({
+ aid: id,
+ amount,
+ hash: v4(),
+ memo,
+ user,
+ type: types.reconcile,
+ });
+ }
+};
diff --git a/lib/register.ts b/lib/register.ts
index eb20ae23..f2e97fed 100644
--- a/lib/register.ts
+++ b/lib/register.ts
@@ -4,7 +4,7 @@ import { v4 } from "uuid";
import config from "$config";
import countries from "$lib/countries";
-import { s } from "$lib/db";
+import { db } from "$lib/db";
import { l, warn } from "$lib/logging";
import { fail, getUser } from "$lib/utils";
@@ -52,10 +52,20 @@ export default async (user, ip) => {
user.migrated = true;
user.locktime = 300;
- await s(`user:${id}`, user);
- await s(`user:${username}`, id);
- await s(`user:${pubkey}`, id);
- await s(`balance:${id}`, 0);
+ let account = JSON.stringify({
+ id,
+ type: "ecash",
+ name: "Spending",
+ });
+
+ db.multi()
+ .set(`user:${id}`, JSON.stringify(user))
+ .set(`user:${username}`, id)
+ .set(`user:${pubkey}`, id)
+ .set(`balance:${id}`, 0)
+ .set(`account:${id}`, account)
+ .lPush(`${id}:accounts`, id)
+ .exec();
l("new user", username);