From 89519c0cd1cafeea9939110b99bcf865ffe617a0 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Wed, 12 May 2021 00:15:50 -0400 Subject: kyc notification --- routes/funding.js | 177 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 104 insertions(+), 73 deletions(-) diff --git a/routes/funding.js b/routes/funding.js index d9af4da7..8d94344e 100644 --- a/routes/funding.js +++ b/routes/funding.js @@ -1,3 +1,4 @@ +const mailgun = require("mailgun-js")(config.mailgun); const multer = require("multer"); const storage = multer.diskStorage({ @@ -6,8 +7,8 @@ const storage = multer.diskStorage({ }, filename: (req, file, cb) => { const parts = file.originalname.split("."); - const ext = parts.length > 1 ? parts[parts.length - 1] : 'bin'; - cb(null, `${req.user.username}-${file.fieldname}.${ext}`) + const ext = parts.length > 1 ? parts[parts.length - 1] : "bin"; + cb(null, `${req.user.username}-${file.fieldname}.${ext}`); } }); @@ -21,80 +22,110 @@ const upload = multer({ } }); -app.post("/id", auth, upload.single("id"), ah(async (req, res) => { - const { user } = req; - if (user.verified === 'proof') user.verified = 'pending'; - else user.verified = 'id'; - await user.save(); - emit(user.username, "user", user); - - res.end(); -})); - -app.post("/proof", auth, upload.single("proof"), ah(async (req, res) => { - const { user } = req; - if (user.verified === 'id') user.verified = 'pending'; - else user.verified = 'proof'; - await user.save(); - emit(user.username, "user", user); - - res.end(); -})); - -app.post("/funding", auth, ah(async (req, res) => { - try { - let { id, amount, code } = req.body; - - if (!code) { - code = ''; - let d = 'ABCDEFGHIJKLMNPQRSTUVWXYZ23456789'; - let l = d.length; - for (let i = 0; i < 8; i++) { - code += d.charAt(Math.floor(Math.random() * l)); - } - } +app.post( + "/id", + auth, + upload.single("id"), + ah(async (req, res) => { + const { user } = req; + if (user.verified === "proof") user.verified = "pending"; + else user.verified = "id"; + await user.save(); + emit(user.username, "user", user); - let params = { - user_id: req.user.id, - amount, - code, + let data = { + ...config.mail, + subject: "KYC Documents", + text: `ID uploaded for ${user.username}`, + from: "adam@coinos.io", + to: "kyc@coinos.io" }; - let deposit; - if (id) { - if (!parseFloat(amount) || parseFloat(amount) < 0) throw new Error("Invalid amount"); - deposit = await db.Deposit.findOne({ where: { id } }) - deposit.update(params); - await deposit.save(); - } else { - deposit = await db.Deposit.create(params); - } + mailgun.messages().send(data); + + res.end(); + }) +); - res.send(deposit); - } catch(e) { - l.error("funding error", e.message); - res.status(500).send("Funding request failed"); - } -})); - -app.post("/withdrawal", auth, ah(async (req, res) => { - try { - const { account, amount, email, institution, transit, notes } = req.body; - if (!parseFloat(amount) || parseFloat(amount) < 0) throw new Error("Invalid amount"); - - await db.Withdrawal.create({ - user_id: req.user.id, - account, - amount, - email, - institution, - transit, - notes, - }); +app.post( + "/proof", + auth, + upload.single("proof"), + ah(async (req, res) => { + const { user } = req; + if (user.verified === "id") user.verified = "pending"; + else user.verified = "proof"; + await user.save(); + emit(user.username, "user", user); res.end(); - } catch(e) { - l.error("withdrawal error", e.message); - res.status(500).send("Withdrawal request failed"); - } -})); + }) +); + +app.post( + "/funding", + auth, + ah(async (req, res) => { + try { + let { id, amount, code } = req.body; + + if (!code) { + code = ""; + let d = "ABCDEFGHIJKLMNPQRSTUVWXYZ23456789"; + let l = d.length; + for (let i = 0; i < 8; i++) { + code += d.charAt(Math.floor(Math.random() * l)); + } + } + + let params = { + user_id: req.user.id, + amount, + code + }; + + let deposit; + if (id) { + if (!parseFloat(amount) || parseFloat(amount) < 0) + throw new Error("Invalid amount"); + deposit = await db.Deposit.findOne({ where: { id } }); + deposit.update(params); + await deposit.save(); + } else { + deposit = await db.Deposit.create(params); + } + + res.send(deposit); + } catch (e) { + l.error("funding error", e.message); + res.status(500).send("Funding request failed"); + } + }) +); + +app.post( + "/withdrawal", + auth, + ah(async (req, res) => { + try { + const { account, amount, email, institution, transit, notes } = req.body; + if (!parseFloat(amount) || parseFloat(amount) < 0) + throw new Error("Invalid amount"); + + await db.Withdrawal.create({ + user_id: req.user.id, + account, + amount, + email, + institution, + transit, + notes + }); + + res.end(); + } catch (e) { + l.error("withdrawal error", e.message); + res.status(500).send("Withdrawal request failed"); + } + }) +); -- cgit v1.2.3 From d1d31eee11da20859a315ea4b8af0324b78d9d00 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Wed, 12 May 2021 00:17:30 -0400 Subject: kyc logs --- routes/funding.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/routes/funding.js b/routes/funding.js index 8d94344e..b398d341 100644 --- a/routes/funding.js +++ b/routes/funding.js @@ -42,6 +42,7 @@ app.post( }; mailgun.messages().send(data); + l.info("id uploaded", user.username); res.end(); }) @@ -57,6 +58,7 @@ app.post( else user.verified = "proof"; await user.save(); emit(user.username, "user", user); + l.info("id proof uploaded", user.username); res.end(); }) -- cgit v1.2.3 From 6be7b95a73ce0a666f7cda1425f13ddf741ca172 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Wed, 12 May 2021 23:19:12 -0400 Subject: log username changes --- routes/users.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/routes/users.js b/routes/users.js index b02e10af..d2cf6f2a 100644 --- a/routes/users.js +++ b/routes/users.js @@ -161,6 +161,7 @@ app.post( return res.status(500).send("Username taken"); } else { sockets[username] = sockets[user.username]; + l.info("changing username", user.username, username); user.username = username; token = jwt.sign({ username }, config.jwt); @@ -614,6 +615,7 @@ app.post( "/redeem", optionalAuth, ah(async function(req, res) { + return res.status(500).send("Vouchers temporarily disabled"); const { redeemcode } = req.body; if (!redeemcode) fail("no code provided"); -- cgit v1.2.3 From 7d6d6ca74f1f271427c271382fff49446aaa1895 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Wed, 12 May 2021 23:19:24 -0400 Subject: rates endpoint --- lib/rates.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/rates.js b/lib/rates.js index fdb7f5ac..b9e889fb 100644 --- a/lib/rates.js +++ b/lib/rates.js @@ -44,6 +44,11 @@ let fetchRates; setTimeout(fetchRates, 7200000); })(); +app.get('/rates', + ah(async (req, res, next) => { + res.send(app.get("rates")); + })); + setInterval(() => { broadcast("rate", app.get("last")); }, 1000); -- cgit v1.2.3 From 4d2379b801ed0a95e8538a64873a0be503e74672 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Thu, 13 May 2021 02:24:05 -0400 Subject: confidential to non-confidential liquid conversion --- lib/rates.js | 10 +++++++--- lib/sockets.js | 3 +-- routes/invoices.js | 1 + routes/lightning/receive.js | 1 + routes/liquid/receive.js | 18 +++++++++++++++++- routes/liquid/send.js | 2 +- routes/users.js | 2 +- 7 files changed, 29 insertions(+), 8 deletions(-) diff --git a/lib/rates.js b/lib/rates.js index b9e889fb..80c22bf0 100644 --- a/lib/rates.js +++ b/lib/rates.js @@ -27,7 +27,9 @@ let fetchRates; try { let { data: { rates: fx } - } = await axios.get(`http://data.fixer.io/api/latest?access_key=${config.fixer}`); + } = await axios.get( + `http://data.fixer.io/api/latest?access_key=${config.fixer}` + ); let USD = fx["USD"]; Object.keys(fx).map(k => { fx[k] = parseFloat((fx[k] / fx["USD"]).toFixed(6)); @@ -44,10 +46,12 @@ let fetchRates; setTimeout(fetchRates, 7200000); })(); -app.get('/rates', +app.get( + "/rates", ah(async (req, res, next) => { res.send(app.get("rates")); - })); + }) +); setInterval(() => { broadcast("rate", app.get("last")); diff --git a/lib/sockets.js b/lib/sockets.js index b6a806ff..931a9d23 100644 --- a/lib/sockets.js +++ b/lib/sockets.js @@ -92,10 +92,9 @@ wss.on("connection", function(ws, req) { case "login": let token = data; - if (differenceInSeconds(new Date(), subSeconds(lastSeen[token], 5)) < 2) return; + if (differenceInSeconds(new Date(), lastSeen[token]) < 5) return; lastSeen[token] = new Date(); - try { if (!token || token === "null") return ws.close(); const username = jwt.decode(token).username; diff --git a/routes/invoices.js b/routes/invoices.js index cdf8ca91..a1928287 100644 --- a/routes/invoices.js +++ b/routes/invoices.js @@ -40,6 +40,7 @@ app.post( if (!user) throw new Error("user not provided"); if (!invoice.currency) invoice.currency = user.currency; if (!invoice.rate) invoice.rate = app.get("rates")[invoice.currency]; + if (invoice.tip > invoice.amount || invoice.tip > 1000000) throw new Error("tip is too large") invoice.user_id = user.id; invoice.account_id = user.account_id; diff --git a/routes/lightning/receive.js b/routes/lightning/receive.js index 8778bb22..325f7092 100644 --- a/routes/lightning/receive.js +++ b/routes/lightning/receive.js @@ -18,6 +18,7 @@ const handlePayment = async msg => { const { text: hash, currency, memo, rate, tip, user_id } = invoice; const amount = parseInt(msg.amt_paid_sat) - tip; + if (amount > 10000000 || amount < 0) throw new Error("amount out of range"); account = await db.Account.findOne({ where: { diff --git a/routes/liquid/receive.js b/routes/liquid/receive.js index 3ce6ca9a..f6a78cfa 100644 --- a/routes/liquid/receive.js +++ b/routes/liquid/receive.js @@ -287,6 +287,7 @@ setInterval(async () => { for (let i = 0; i < arr.length; i++) { const hash = arr[i]; + let account, address, user, total; await db.transaction(async transaction => { let p = await db.Payment.findOne({ where: { hash, confirmed: 0, received: 1 }, @@ -304,7 +305,7 @@ setInterval(async () => { transaction }); - const { user } = p; + ({ account, address, user } = p); if (p && p.account) { let total = p.amount + p.tip; @@ -340,6 +341,21 @@ setInterval(async () => { delete queue[hash]; }); + + let c = convert[address]; + if (c) { + let { tx } = c; + user.account = account; + + delete queue[hash]; + + await sendLiquid({ + address, + user, + tx, + limit: total + }); + } } } catch (e) { l.error("problem processing queued liquid transaction", e.message); diff --git a/routes/liquid/send.js b/routes/liquid/send.js index 0729370c..b80471b0 100644 --- a/routes/liquid/send.js +++ b/routes/liquid/send.js @@ -158,6 +158,6 @@ module.exports = ah(async (req, res) => { res.send(await sendLiquid({ user, address, memo, tx })); } catch (e) { l.error("problem sending liquid", user.username, e.message); - return res.status(500).send(e.message); + return res.status(500).send(e); } }); diff --git a/routes/users.js b/routes/users.js index d2cf6f2a..44478c0a 100644 --- a/routes/users.js +++ b/routes/users.js @@ -161,7 +161,7 @@ app.post( return res.status(500).send("Username taken"); } else { sockets[username] = sockets[user.username]; - l.info("changing username", user.username, username); + if (user.username !== username) l.info("changing username", user.username, username); user.username = username; token = jwt.sign({ username }, config.jwt); -- cgit v1.2.3