diff options
| author | Adam Soltys <[email protected]> | 2023-02-06 16:48:13 -0800 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2023-02-06 16:48:13 -0800 |
| commit | 9c667055c6367e1b2e239686e72f52995679a47e (patch) | |
| tree | 0b1d4aee51ec2d4e92d08a9d1404ba4e2ecd462a /lib/payments.js | |
| parent | 15294844dbc8e73b4d1e92008a7eebc6b86b9ec5 (diff) | |
| parent | 6f5602d112b68adb7452abf3047f20c32e7725b6 (diff) | |
| download | coinos-server-9c667055c6367e1b2e239686e72f52995679a47e.tar.gz coinos-server-9c667055c6367e1b2e239686e72f52995679a47e.zip | |
Merge branch 'master' into test
Diffstat (limited to 'lib/payments.js')
| -rw-r--r-- | lib/payments.js | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/lib/payments.js b/lib/payments.js new file mode 100644 index 00000000..6fd595d4 --- /dev/null +++ b/lib/payments.js @@ -0,0 +1,155 @@ +import config from "$config"; +import store from "$lib/store"; +import { emit } from "$lib/sockets"; +import { v4 } from "uuid"; +import { notify } from "$lib/notifications"; +import { db, g, s, t } from "$lib/db"; +import { l, err } from "$lib/logging"; +import { fail } from "$lib/utils"; +import { callWebhook } from "$lib/webhooks"; + +export const types = { + internal: "internal", + bitcoin: "bitcoin", + lightning: "lightning", + pot: "pot", + classic: "classic" +}; + +export let debit = async ( + hash, + amount, + fee = 0, + memo, + user, + type = types.internal, + id = v4() +) => { + let ref; + let invoice = await g(`invoice:${hash}`); + if (invoice) ref = invoice.uid; + + let { id: uid, currency, username } = user; + + amount = parseInt(amount); + + if (!amount || amount < 0) fail("Amount must be greater than zero"); + + let ourfee = [types.bitcoin, types.lightning].includes(type) + ? Math.round(amount * config.fee) + : 0; + + 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, + rate: store.rates[currency], + currency, + type, + ref, + created: Date.now() + }; + + await s(`payment:${id}`, p); + await db.lPush(`${uid}:payments`, id); + + l("sent", type, user.username, amount); + emit(user.id, "payment", p); + + return p; +}; + +export let credit = async (hash, amount, memo, ref, type = types.internal) => { + amount = parseInt(amount); + let invoice = await g(`invoice:${hash}`); + if (!invoice) return; + if (!memo) ({ memo } = invoice); + + let user = await g(`user:${invoice.uid}`); + + let { id: uid, currency, username } = user; + + let p = { + hash, + amount, + uid, + rate: store.rates[currency], + currency, + memo, + ref, + type, + confirmed: true, + created: Date.now() + }; + + let { tip } = invoice; + if (tip) { + p.tip = tip; + p.amount -= tip; + } + + invoice.received += amount; + + let balance = "balance"; + if (type === types.bitcoin) { + let [txid, vout] = ref.split(":").slice(-2); + p.id = `${txid}:${vout}`; + p.confirmed = false; + balance = "pending"; + } else { + p.id = hash; + } + + 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) + .exec(); + + l("received", type, username, amount); + emit(uid, "payment", p); + notify(user, `Received ${amount} sats`); + callWebhook(invoice, p); + + return p; +}; + +export let confirm = async (address, txid, vout) => { + let id = `payment:${txid}:${vout}`; + let p = await g(id); + p.confirmed = true; + + await db + .multi() + .set(id, JSON.stringify(p)) + .decrBy(`pending:${p.uid}`, p.amount) + .incrBy(`balance:${p.uid}`, p.amount) + .exec(); +}; |
