diff options
| author | Adam Soltys <[email protected]> | 2023-01-19 16:00:38 -0800 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2023-01-19 16:00:38 -0800 |
| commit | 5264f702a2217fe8815cb5275aca14a672f6d4bb (patch) | |
| tree | 1c92a5258cfb92749c4250923f73797284c5d9c7 /routes | |
| parent | ef3679051214a9b3047b68f236eac656edcf8d38 (diff) | |
| download | coinos-server-5264f702a2217fe8815cb5275aca14a672f6d4bb.tar.gz coinos-server-5264f702a2217fe8815cb5275aca14a672f6d4bb.zip | |
refactor payment types
Diffstat (limited to 'routes')
| -rw-r--r-- | routes/invoices.js | 16 | ||||
| -rw-r--r-- | routes/payments.js | 220 |
2 files changed, 28 insertions, 208 deletions
diff --git a/routes/invoices.js b/routes/invoices.js index 1287de88..62106f3a 100644 --- a/routes/invoices.js +++ b/routes/invoices.js @@ -3,6 +3,8 @@ import { l } from "$lib/logging"; import { emit } from "$lib/sockets"; import { db, g, s } from "$lib/db"; import { bip21, fail } from "$lib/utils"; +import { types } from "$lib/payments"; + import bc from "$lib/bitcoin"; import ln from "$lib/ln"; @@ -31,13 +33,13 @@ export default { if (amount < 0) fail("invalid amount"); let hash, text; - if (type === "lightning") { + if (type === types.lightning) { let amt = amount ? `${amount + tip}sat` : "any"; let r = await ln.invoice(amt, new Date(), "", 3600); hash = r.payment_hash; text = r.bolt11; - } else if (type === "bitcoin") { + } else if (type === types.bitcoin) { hash = await bc.getNewAddress(); text = bip21(hash, invoice); } else { @@ -57,15 +59,7 @@ export default { created: Date.now() }; - - l( - "creating invoice", - user.username, - amount, - tip, - currency, - invoice.hash - ); + l("creating invoice", user.username, amount, tip, currency, invoice.hash); await s(`invoice:${hash}`, invoice); await db.lPush(`${uid}:invoices`, hash); diff --git a/routes/payments.js b/routes/payments.js index fc506685..d044f1e8 100644 --- a/routes/payments.js +++ b/routes/payments.js @@ -2,97 +2,19 @@ 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, warn } from "$lib/logging"; -import { fail } from "$lib/utils"; -import ln from "$lib/ln"; +import { l, err } from "$lib/logging"; +import { fail, sats } from "$lib/utils"; import { requirePin } from "$lib/auth"; -import { callWebhook } from "$lib/webhooks"; - -const { HOSTNAME: hostname } = process.env; - -let debit = async (user, amount, memo, to) => { - let { id: uid, currency, username } = user; - to = to && to.id; - - amount = parseInt(amount); - - 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 fee = 0; - - let hash = v4(); - - let p = { - hash, - amount: -amount, - memo, - uid, - rate: store.rates[currency], - currency, - type: "internal", - to, - created: Date.now() - }; - - if (!to) delete p.to; - - await s(`payment:${hash}`, p); - await db.lPush(`${uid}:payments`, hash); - - l("sent internal", user.username, amount); - emit(user.id, "payment", p); +import { debit, credit, confirm, types } from "$lib/payments"; - return p; -}; - -let credit = async (hash, amount, memo, from) => { - let invoice = await g(`invoice:${hash}`); - let user = await g(`user:${invoice.uid}`); - - let { id: uid, currency, username } = user; - from = from.id; - - let p = { - hash, - amount, - uid, - rate: store.rates[currency], - currency, - memo, - type: memo === "pot" ? "pot" : "internal", - from, - created: Date.now() - }; - - let { tip } = invoice; - if (tip) { - p.tip = tip; - p.amount -= tip; - } - - invoice.received += amount; - await s(`invoice:${hash}`, invoice); - await s(`payment:${hash}`, p); - await db.lPush(`${uid}:payments`, hash); - - l("received internal", username, amount); - emit(username, "payment", p); - notify(user, `Received ${amount} sats`); - callWebhook(invoice, p); +import bc from "$lib/bitcoin"; +import ln from "$lib/ln"; - return p; -}; +const { HOSTNAME: hostname } = process.env; export default { - async send({ body, user }, res) { + async create({ body, user }, res) { let { amount, hash, name, memo, tip } = body; await requirePin({ body, user }); @@ -101,7 +23,7 @@ export default { let p = await debit(user, amount, memo, recipient); if (hash) { - await credit(hash, amount, memo, user); + await credit(hash, amount, memo, user.id); } else { let pot = name || v4(); await db.incrBy(`pot:${pot}`, amount); @@ -126,116 +48,11 @@ export default { res.send({ payments, total: payments.length }); }, - async voucher(req, res) { - try { - const { redeemcode } = req.params; - let payment = await g(`voucher:${id}`); - - payment = payment.get({ plain: true }); - payment.redeemer = payment["with"]; - - if (!payment) fail("invalid code"); - - res.send(payment); - } catch (e) { - res.code(500).send(e.message); - } - }, - async get({ params: { hash } }, res) { res.send(await g(`payment:${hash}`)); }, - async redeem({ body: { redeemcode } }, res) { - try { - await db.transaction(async transaction => { - if (!redeemcode) fail("no code provided"); - - let { user } = req; - - const source = await db.Payment.findOne({ - where: { - redeemcode: req.body.redeemcode - }, - include: { - model: db.Account, - as: "account" - }, - lock: transaction.LOCK.UPDATE, - transaction - }); - - l("redeeming", redeemcode); - - if (!source) fail("Invalid code"); - if (source.redeemed) fail("Voucher has already been redeemed"); - let { amount } = source; - amount = -amount; - - if (!user) { - const ip = - req.headers["x-forwarded-for"] || req.connection.remoteAddress; - - user = await register( - { - username: redeemcode.substr(0, 8), - password: "" - }, - ip, - false - ); - - let payload = { username: user.username }; - let token = jwt.sign(payload, config.jwt); - res.cookie("token", token, { - expires: new Date(Date.now() + 432000000) - }); - - return res.send({ user }); - } - - let account = await getAccount(source.account.asset, user, transaction); - let { hash, memo, confirmed, fee, network } = source; - - source.redeemed = true; - (source.with_id = user.id), await source.save({ transaction }); - - let payment = await db.Payment.create( - { - amount, - account_id: account.id, - user_id: user.id, - hash: "Voucher " + redeemcode, - memo, - rate: store.rates[user.currency], - currency: user.currency, - confirmed, - network, - received: true, - fee, - with_id: source.user_id - }, - { transaction } - ); - - await account.increment({ balance: amount }, { transaction }); - await account.reload({ transaction }); - - payment = payment.get({ plain: true }); - payment.account = account.get({ plain: true }); - emit(user.username, "payment", payment); - emit(user.username, "account", account); - - res.send({ payment }); - }); - } catch (e) { - console.log(e); - err("problem redeeming", e.message); - return res.code(500).send("There was a problem redeeming the voucher"); - } - }, - - async sendLightning({ body: { payreq } }, res) { + async query({ body: { payreq } }, res) { let hour = 1000 * 60 * 60; let { last } = store.nodes; let { nodes } = store; @@ -264,7 +81,7 @@ export default { res.send({ amount, payments }); }, - async withdraw({ body: { name, amount }, user }, res) { + async take({ body: { name, amount }, user }, res) { amount = parseInt(amount); await t(`pot:${name}`, async balance => { await new Promise(r => setTimeout(r, 100)); @@ -278,14 +95,23 @@ export default { received: 0 }); - let payment = await credit(hash, amount, "pot", { id: name }); - await db.lPush(`pot:${name}:payments`, hash); + let payment = await credit(hash, amount, "", name, types.pot); + await db.lPush(`${name}:payments`, hash); res.send({ payment }); }, - async bitcoin({ body }, res) { - console.log(body); + async bitcoin({ body: { txid, wallet } }, res) { + if (wallet === config.bitcoin.wallet) { + let { confirmations, details } = await bc.getTransaction(txid); + for (let { address, amount, vout } of details) { + if (confirmations > 0) { + await confirm(address, txid, vout); + } else { + await credit(address, sats(amount), "", `${txid}:${vout}`, types.bitcoin); + } + } + } res.send({}); } }; |
