diff options
| author | Adam Soltys <[email protected]> | 2021-08-09 20:55:17 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2021-08-09 20:55:17 -0700 |
| commit | 56559c7b9749fe62fe2fe0ba90725391d83b8bf7 (patch) | |
| tree | 48d6a0630d05d6787b4410708a5efceff472636b /routes | |
| parent | 803ecab2b5c3a00d107372ea6757cd6ce0f8224d (diff) | |
| parent | 8d6f65079868ae6134f593752e3380180591623d (diff) | |
| download | coinos-server-56559c7b9749fe62fe2fe0ba90725391d83b8bf7.tar.gz coinos-server-56559c7b9749fe62fe2fe0ba90725391d83b8bf7.zip | |
Merge branch 'v1.0.0'
Diffstat (limited to 'routes')
| -rw-r--r-- | routes/admin.js | 224 | ||||
| -rw-r--r-- | routes/bitcoin/receive.js | 48 | ||||
| -rw-r--r-- | routes/bitcoin/send.js | 55 | ||||
| -rw-r--r-- | routes/invoices.js | 4 | ||||
| -rw-r--r-- | routes/lightning/receive.js | 53 | ||||
| -rw-r--r-- | routes/liquid/fee.js | 9 | ||||
| -rw-r--r-- | routes/liquid/receive.js | 71 | ||||
| -rw-r--r-- | routes/liquid/send.js | 34 | ||||
| -rw-r--r-- | routes/lnurl.js | 10 | ||||
| -rw-r--r-- | routes/payments.js | 1 | ||||
| -rw-r--r-- | routes/referrals.js | 7 | ||||
| -rw-r--r-- | routes/send.js | 2 | ||||
| -rw-r--r-- | routes/users.js | 25 |
13 files changed, 222 insertions, 321 deletions
diff --git a/routes/admin.js b/routes/admin.js index c401c724..c7b7578d 100644 --- a/routes/admin.js +++ b/routes/admin.js @@ -35,20 +35,12 @@ router.get( .select('username', 'email', 'phone', 'verified', knex.raw('LEFT(createdAt,10) as created_at')) .from('users') - if (starts_with) { - search = search + '%' - } else if (contains) { - search = '%' + search + '%' - } + var timeCondition = parseInput.addTimeSearch(req.query, 'users.createdAt') + var userCondition = parseInput.addUserSearch(req.query) - if (search) { - users = users - .where(function() { - this.where('username', 'like', search) - this.orWhere('email', 'like', search) - }) - } - debug('search ? ' + search) + if (timeCondition) users = users.whereRaw(timeCondition) + if (userCondition) users = users.whereRaw(userCondition) + // Alternative Sequelize query syntax // await db.User.findAll({ // attributes: ['username', 'email', 'phone', 'verified', 'createdAt'] @@ -101,6 +93,11 @@ router.get( // ] // }) + var timeCondition = parseInput.addTimeSearch(req.query, 'referrals.updatedAt') + var userCondition = parseInput.addUserSearch(req.query, 'sponsor') + + if (timeCondition) referrals = referrals.whereRaw(timeCondition) + if (userCondition) referrals = referrals.whereRaw(userCondition) debug('Referrals: ' + JSON.stringify(referrals)) return res.send({referrals: referrals}) @@ -141,20 +138,12 @@ router.get( .leftJoin('users', 'users.email', 'waiting_list.email') .where('waiting_list.id', '>', 0) - if (starts_with) { - search = search + '%' - } else if (contains) { - search = '%' + search + '%' - } + var timeCondition = parseInput.addTimeSearch(req.query, 'waiting_list.updated_at') + var userCondition = parseInput.addUserSearch(req.query) + + if (timeCondition) queue = queue.whereRaw(timeCondition) + if (userCondition) queue = queue.whereRaw(userCondition) - if (search) { - queue = queue - .where(function() { - this.where('waiting_list.email', 'like', search) - this.orWhere('users.username', 'like', search) - }) - } - debug('search ? ' + search) const found = await queue debug('Waiting list: ' + JSON.stringify(found)) @@ -195,19 +184,12 @@ router.get( .where('balance', '>', 0) } - if (starts_with) { - search = search + '%' - } else if (contains) { - search = '%' + search + '%' - } + var timeCondition = parseInput.addTimeSearch(req.query, 'accounts.updatedAt') + var userCondition = parseInput.addUserSearch(req.query) + + if (timeCondition) accounts = accounts.whereRaw(timeCondition) + if (userCondition) accounts = accounts.whereRaw(userCondition) - if (search) { - accounts = accounts - .where(function() { - this.where('users.email', 'like', search) - this.orWhere('users.username', 'like', search) - }) - } debug('search ? ' + search) const found = await accounts @@ -270,21 +252,11 @@ router.get( debug(types[i] + ' since ' + since) } } + if (since) transactions = transactions.havingRaw('invoices + payments + deposits + orders > ?', [0]) - if (starts_with) { - search = search + '%' - } else if (contains) { - search = '%' + search + '%' - } - - if (search) { - transactions = transactions - .where(function() { - this.where('users.email', 'like', search) - this.orWhere('users.username', 'like', search) - }) - } + var userCondition = parseInput.addUserSearch(req.query) + if (userCondition) transactions = transactions.whereRaw(userCondition) transactions = transactions .groupBy('users.id') @@ -338,27 +310,16 @@ router.get( .leftJoin('users as u1', 'a1.user_id', 'u1.id') .leftJoin('users as u2', 'a2.user_id', 'u2.id') - if (since) { - orders = orders - .where('orders.updatedAt', '>=', since) - } + var timeCondition = parseInput.addTimeSearch(req.query, 'orders.updatedAt') + if (timeCondition) orders = orders.whereRaw(timeCondition) - if (starts_with) { - search = search + '%' - } else if (contains) { - search = '%' + search + '%' - } - - if (search) { - orders = orders - .where( function () { - this.where('u1.email', 'like', search) - this.orWhere('u1.username', 'like', search) - this.orWhere('u2.username', 'like', search) - this.orWhere('u2.email', 'like', search) - }) - } - debug('orders since ' + since) + var userCondition1 = parseInput.addUserSearch(req.query, 'u1') + var userCondition2 = parseInput.addUserSearch(req.query, 'u2') + + if (userCondition1) orders = orders.where( function () { + this.whereRaw(userCondition1) + this.orWhere(knex.raw(userCondition2)) + }) var found = await orders debug('orders: ' + JSON.stringify(found)) @@ -403,26 +364,11 @@ router.get( .leftJoin('accounts', 'invoices.account_id', 'accounts.id') .leftJoin('users', 'accounts.user_id', 'users.id') - if (since) { - invoices = invoices - .where('invoices.updatedAt', '>=', since) - } - - debug('invoices since ' + since) - - if (starts_with) { - search = search + '%' - } else if (contains) { - search = '%' + search + '%' - } + var timeCondition = parseInput.addTimeSearch(req.query, 'invoices.updatedAt') + var userCondition = parseInput.addUserSearch(req.query) - if (search) { - invoices = invoices - .where(function() { - this.where('users.email', 'like', search) - this.orWhere('users.username', 'like', search) - }) - } + if (timeCondition) invoices = invoices.whereRaw(timeCondition) + if (userCondition) invoices = invoices.whereRaw(userCondition) var found = await invoices debug('invoices: ' + JSON.stringify(found)) @@ -468,26 +414,11 @@ router.get( debug('dtype: ' + deposits.constructor + ' : ' + typeof(deposits)) - if (since) { - deposits = deposits - .where('deposits.updatedAt', '>=', since) - } - - debug('deposits since ' + since) - - if (starts_with) { - search = search + '%' - } else if (contains) { - search = '%' + search + '%' - } + var timeCondition = parseInput.addTimeSearch(req.query, 'deposits.updatedAt') + var userCondition = parseInput.addUserSearch(req.query) - if (search) { - deposits = deposits - .where(function() { - this.where('users.email', 'like', search) - this.orWhere('users.username', 'like', search) - }) - } + if (timeCondition) deposits = deposits.whereRaw(timeCondition) + if (userCondition) deposits = deposits.whereRaw(userCondition) var found = await deposits debug('deposits: ' + JSON.stringify(found)) @@ -530,27 +461,11 @@ router.get( .from('withdrawals') .leftJoin('users', 'withdrawals.user_id', 'users.id') - if (since) { - withdrawals = withdrawals - .where('withdrawals.updatedAt', '>=', since) - } - - debug('withdrawals since ' + since) - - - if (starts_with) { - search = search + '%' - } else if (contains) { - search = '%' + search + '%' - } + var timeCondition = parseInput.addTimeSearch(req.query, 'withdrawals.updatedAt') + var userCondition = parseInput.addUserSearch(req.query) - if (search) { - withdrawals = withdrawals - .where(function() { - this.where('users.email', 'like', search) - this.orWhere('users.username', 'like', search) - }) - } + if (timeCondition) withdrawals = withdrawals.whereRaw(timeCondition) + if (userCondition) withdrawals = withdrawals.whereRaw(userCondition) var found = await withdrawals debug('withdrawals: ' + JSON.stringify(found)) @@ -595,27 +510,12 @@ router.get( .leftJoin('accounts', 'payments.account_id', 'accounts.id') .leftJoin('users', 'accounts.user_id', 'users.id') - if (since) { - payments = payments - .where('payments.updatedAt', '>=', since) - } - - debug('payments since ' + since) - + var timeCondition = parseInput.addTimeSearch(req.query, 'payments.updatedAt') + var userCondition = parseInput.addUserSearch(req.query) - if (starts_with) { - search = search + '%' - } else if (contains) { - search = '%' + search + '%' - } + if (timeCondition) payments = payments.whereRaw(timeCondition) + if (userCondition) payments = payments.whereRaw(userCondition) - if (search) { - payments = payments - .where(function() { - this.where('users.email', 'like', search) - this.orWhere('users.username', 'like', search) - }) - } var found = await payments debug('payments: ' + JSON.stringify(found)) return res.send({payments: found}) @@ -658,7 +558,9 @@ router.get( // 'payments.network', // knex.raw('LEFT(hash,20) as hash'), // knex.raw('Left(payments.updatedAt,16) as transferred') - ) + // knex.raw( parseInput.readableDate('Max(payments.updatedAt)', 'last_changed') ) + knex.raw( 'DATE_FORMAT(Max(payments.updatedAt), ?) AS last_changed', "%M %d, %Y" ) + ) .from('payments') .leftJoin('accounts', 'payments.account_id', 'accounts.id') .leftJoin('users', 'payments.user_id', 'users.id') // should really point to accounts @@ -666,30 +568,16 @@ router.get( // .groupBy('payments.currency') // .groupBy('payments.network') - if (since) { - kyc = kyc - .where('payments.updatedAt', '>=', since) - } - - debug('payments since ' + since) + var timeCondition = parseInput.addTimeSearch(req.query, 'payments.updatedAt') + var userCondition = parseInput.addUserSearch(req.query) - if (starts_with) { - search = search + '%' - } else if (contains) { - search = '%' + search + '%' - } + if (timeCondition) kyc = kyc.whereRaw(timeCondition) + if (userCondition) kyc = kyc.whereRaw(userCondition) - if (search) { - kyc = kyc - .where(function() { - this.where('users.email', 'like', search) - this.orWhere('users.username', 'like', search) - }) - } var found = await kyc.having('max', '>=', threshold) debug('payments: ' + JSON.stringify(found)) - return res.send({kyc_transactions: found}) + return res.send({found: found}) }) ); diff --git a/routes/bitcoin/receive.js b/routes/bitcoin/receive.js index 67ccdb45..603db47b 100644 --- a/routes/bitcoin/receive.js +++ b/routes/bitcoin/receive.js @@ -18,6 +18,8 @@ const network = config.bitcoin.network === "mainnet" ? "bitcoin" : config.bitcoin.network ]; +const queue = {}; + zmqRawTx.on("message", async (topic, message, sequence) => { const hex = message.toString("hex"); let tx = bitcoin.Transaction.fromHex(message); @@ -27,7 +29,7 @@ zmqRawTx.on("message", async (topic, message, sequence) => { if (payments.includes(hash)) return; Promise.all( - tx.outs.map(async o => { + tx.outs.map(async (o) => { try { const { value } = o; @@ -46,20 +48,20 @@ zmqRawTx.on("message", async (topic, message, sequence) => { let user = await db.User.findOne({ where: { - username: addresses[address] - } + username: addresses[address], + }, }); const invoice = await db.Invoice.findOne({ where: { user_id: user.id, - network: "bitcoin" + network: "bitcoin", }, order: [["id", "DESC"]], include: { model: db.Account, - as: "account" - } + as: "account", + }, }); if (!invoice) return; @@ -104,7 +106,7 @@ zmqRawTx.on("message", async (topic, message, sequence) => { confirmed, address, network: "bitcoin", - invoice_id: invoice.id + invoice_id: invoice.id, }); payment = payment.get({ plain: true }); payment.account = account.get({ plain: true }); @@ -123,19 +125,17 @@ zmqRawTx.on("message", async (topic, message, sequence) => { ); }); -let queue = {}; - zmqRawBlock.on("message", async (topic, message, sequence) => { - const payments = await db.Payment.findAll({ - where: { confirmed: false } - }); + const payments = await db.Payment.findAll({ + where: { confirmed: false }, + }); - let block = bitcoin.Block.fromHex(message.toString("hex")); - block.transactions.map(tx => { - let hash = reverse(tx.getHash()).toString("hex"); - if (payments.find(p => p.hash === hash)) queue[hash] = 1; + let block = bitcoin.Block.fromHex(message.toString("hex")); + block.transactions.map((tx) => { + let hash = reverse(tx.getHash()).toString("hex"); + if (payments.find((p) => p.hash === hash)) queue[hash] = 1; + }); }); -}); setInterval(async () => { try { @@ -144,25 +144,25 @@ setInterval(async () => { const hash = arr[i]; let account, address, user, total; - await db.transaction(async transaction => { + await db.transaction(async (transaction) => { let p = await db.Payment.findOne({ where: { hash, confirmed: 0, received: 1 }, include: [ { model: db.Account, - as: "account" + as: "account", }, { model: db.Invoice, - as: "invoice" + as: "invoice", }, { model: db.User, - as: "user" - } + as: "user", + }, ], lock: transaction.LOCK.UPDATE, - transaction + transaction, }); if (p && p.address) address = p.address; @@ -211,7 +211,7 @@ setInterval(async () => { address: c.address, amount: total - 100, user, - limit: total + limit: total, }); } } diff --git a/routes/bitcoin/send.js b/routes/bitcoin/send.js index cab79e06..470889b3 100644 --- a/routes/bitcoin/send.js +++ b/routes/bitcoin/send.js @@ -1,4 +1,3 @@ -const bitcoin = require("bitcoinjs-lib"); const btc = config.liquid.btcasset; module.exports = ah(async (req, res) => { @@ -32,10 +31,10 @@ module.exports = ah(async (req, res) => { total = total - change + fee; let amount = total - fee; - let params; + let account, params; try { await db.transaction(async transaction => { - let account = await db.Account.findOne({ + account = await db.Account.findOne({ where: { id: user.account_id }, @@ -62,38 +61,38 @@ module.exports = ah(async (req, res) => { await account.decrement({ balance: total }, { transaction }); await account.reload({ transaction }); + }); - params = { - amount: -amount, - fee, - memo, - account_id: account.id, - user_id: user.id, - rate: app.get("rates")[user.currency], - currency: user.currency, - address, - confirmed: true, - received: false, - network: "bitcoin" - }; + params = { + amount: -amount, + fee, + memo, + account_id: account.id, + user_id: user.id, + rate: app.get("rates")[user.currency], + currency: user.currency, + address, + confirmed: true, + received: false, + network: "bitcoin" + }; - if (config.bitcoin.walletpass) - await bc.walletPassphrase(config.bitcoin.walletpass, 300); + if (config.bitcoin.walletpass) + await bc.walletPassphrase(config.bitcoin.walletpass, 300); - hex = (await bc.signRawTransactionWithWallet(hex)).hex; - params.hash = await bc.sendRawTransaction(hex); + hex = (await bc.signRawTransactionWithWallet(hex)).hex; + params.hash = await bc.sendRawTransaction(hex); - let payment = await db.Payment.create(params, { transaction }); + let payment = await db.Payment.create(params); - payment = payment.get({ plain: true }); - payment.account = account.get({ plain: true }); + payment = payment.get({ plain: true }); + payment.account = account.get({ plain: true }); - emit(user.username, "payment", payment); - res.send(payment); + emit(user.username, "payment", payment); + res.send(payment); - payments.push(params.hash); - l.info("sent bitcoin", user.username, total); - }); + payments.push(params.hash); + l.info("sent bitcoin", user.username, total); } catch (e) { l.error("error sending bitcoin", e.message); return res.status(500).send(e.message); diff --git a/routes/invoices.js b/routes/invoices.js index c188811e..51906b8c 100644 --- a/routes/invoices.js +++ b/routes/invoices.js @@ -27,6 +27,10 @@ app.post( let { liquidAddress, invoice, user, tx } = req.body; let { blindkey } = invoice; + if (invoice.amount < 0) throw new Error("amount out of range"); + if (invoice.tip > invoice.amount || invoice.tip > 1000000 || invoice.tip < 0) + throw new Error("tip amount out of range"); + if (liquidAddress) { l.info("conversion request for", liquidAddress, invoice.text); convert[invoice.text] = { address: liquidAddress, tx }; diff --git a/routes/lightning/receive.js b/routes/lightning/receive.js index 0e98cd93..d974860e 100644 --- a/routes/lightning/receive.js +++ b/routes/lightning/receive.js @@ -1,21 +1,18 @@ -const handlePayment = async msg => { +const handlePayment = async (msg) => { + if (!msg.settled) return; let account, total, user; - try { - await db.transaction(async transaction => { - if (!msg.settled) return; - const invoice = await db.Invoice.findOne({ - where: { - text: msg.payment_request - } - }); + const invoice = await db.Invoice.findOne({ + where: { + text: msg.payment_request, + }, + }); - if (!invoice) - return l.warn( - "received lightning with no invoice", - msg.payment_request - ); + if (!invoice) + return l.warn("received lightning with no invoice", msg.payment_request); + try { + await db.transaction(async (transaction) => { const { text: hash, currency, memo, rate, tip, user_id } = invoice; const amount = parseInt(msg.amt_paid_sat) - tip; if (amount > 10000000 || amount < 0) @@ -25,14 +22,14 @@ const handlePayment = async msg => { where: { user_id, asset: config.liquid.btcasset, - pubkey: null + pubkey: null, }, include: { model: db.User, - as: "user" + as: "user", }, lock: transaction.LOCK.UPDATE, - transaction + transaction, }); ({ user } = account); @@ -52,7 +49,8 @@ const handlePayment = async msg => { received: true, confirmed: true, network: "lightning", - tip + tip, + invoice_id: invoice.id, }, { transaction } ); @@ -85,7 +83,12 @@ const handlePayment = async msg => { let c = convert[msg.payment_request]; if (msg.payment_request && c) { - l.info("lightning detected for conversion request", msg.payment_request, c.address, user.username); + l.info( + "lightning detected for conversion request", + msg.payment_request, + c.address, + user.username + ); user.account = account; @@ -94,7 +97,7 @@ const handlePayment = async msg => { address: c.address, amount: total - 100, user, - limit: total + limit: total, }); } catch (e) { l.error("problem sending liquid payment", e.message, e.stack); @@ -106,14 +109,14 @@ const handlePayment = async msg => { }; if (config.lna.clightning) { - const poll = async ln => { - const wait = async i => { + const poll = async (ln) => { + const wait = async (i) => { const { bolt11: payment_request, pay_index, status, msatoshi_received, - payment_preimage: r_preimage + payment_preimage: r_preimage, } = await ln.waitanyinvoice(i); let settled = status === "paid"; @@ -123,13 +126,13 @@ if (config.lna.clightning) { payment_request, settled, amt_paid_sat, - r_preimage + r_preimage, }); wait(pay_index); }; const { invoices } = await ln.listinvoices(); - wait(Math.max(...invoices.map(i => i.pay_index).filter(n => n))); + wait(Math.max(...invoices.map((i) => i.pay_index).filter((n) => n))); }; poll(lna); diff --git a/routes/liquid/fee.js b/routes/liquid/fee.js index 2070873a..fad69f13 100644 --- a/routes/liquid/fee.js +++ b/routes/liquid/fee.js @@ -3,11 +3,6 @@ const buildTx = require("../../lib/buildliquidtx"); liquidTx = async ({ address, asset, amount, feeRate, replaceable, user }) => { let tx, fee; let node = lq; - /* - if (asset === config.liquid.btcasset) { - node = rare; - } - */ if (user.account.pubkey) { let psbt = await buildTx({ @@ -64,6 +59,8 @@ liquidTx = async ({ address, asset, amount, feeRate, replaceable, user }) => { } ); + l.info("funding tx for fee estimate", tx); + tx = await node.fundRawTransaction(tx, params); let blinded = await node.blindRawTransaction(tx.hex); @@ -81,7 +78,7 @@ module.exports = ah(async (req, res) => { let tx = await liquidTx({ ...req.body, user: req.user }) res.send(tx); } catch (e) { - l.error("error estimating liquid fee", e.message, e.stack); + l.error("error estimating liquid fee", e.message); return res.status(500).send(e.message); } }); diff --git a/routes/liquid/receive.js b/routes/liquid/receive.js index 3a6aab10..2396755f 100644 --- a/routes/liquid/receive.js +++ b/routes/liquid/receive.js @@ -15,7 +15,7 @@ const getAccount = async (params, transaction) => { let account = await db.Account.findOne({ where: params, lock: transaction.LOCK.UPDATE, - transaction + transaction, }); if (account) { @@ -37,12 +37,12 @@ const getAccount = async (params, transaction) => { const existing = await db.Account.findOne({ where: { asset, - pubkey + pubkey, }, order: [["id", "ASC"]], limit: 1, lock: transaction.LOCK.UPDATE, - transaction + transaction, }); if (existing) { @@ -65,6 +65,8 @@ const zmqRawTx = zmq.socket("sub"); zmqRawTx.connect(config.liquid.zmqrawtx); zmqRawTx.subscribe("rawtx"); +const queue = {}; + zmqRawTx.on("message", async (topic, message, sequence) => { const hex = message.toString("hex"); @@ -80,7 +82,7 @@ zmqRawTx.on("message", async (topic, message, sequence) => { if (payments.includes(blinded.txid)) return; Promise.all( - tx.vout.map(async o => { + tx.vout.map(async (o) => { try { if (!(o.scriptPubKey && o.scriptPubKey.addresses)) return; @@ -92,14 +94,14 @@ zmqRawTx.on("message", async (topic, message, sequence) => { Object.keys(addresses).includes(address) && !change.includes(address) ) { - await db.transaction(async transaction => { + await db.transaction(async (transaction) => { let user = await getUser(addresses[address], transaction); let invoice = await db.Invoice.findOne({ where: { unconfidential: address, user_id: user.id, - network: "liquid" + network: "liquid", }, order: [["id", "DESC"]], }); @@ -110,10 +112,10 @@ zmqRawTx.on("message", async (topic, message, sequence) => { let account = await db.Account.findOne({ where: { - id: invoice.account_id + id: invoice.account_id, }, lock: transaction.LOCK.UPDATE, - transaction + transaction, }); if ( @@ -131,7 +133,7 @@ zmqRawTx.on("message", async (topic, message, sequence) => { asset, pubkey: account.pubkey, pending: value, - index: 0 + index: 0, }, transaction ); @@ -162,7 +164,8 @@ zmqRawTx.on("message", async (topic, message, sequence) => { tip, confirmed, address, - network: "liquid" + network: "liquid", + invoice_id: invoice.id, }, { transaction } ); @@ -185,12 +188,10 @@ zmqRawTx.on("message", async (topic, message, sequence) => { ); }); -let queue = {}; - zmqRawBlock.on("message", async (topic, message, sequence) => { try { const payments = await db.Payment.findAll({ - where: { confirmed: 0 } + where: { confirmed: 0 }, }); const block = Block.fromHex(message.toString("hex"), true); @@ -200,9 +201,9 @@ zmqRawBlock.on("message", async (topic, message, sequence) => { hash = await lq.getBlockHash(block.height); json = await lq.getBlock(hash, 2); - json.tx.map(async tx => { + json.tx.map(async (tx) => { if (issuances[tx.txid]) { - await db.transaction(async transaction => { + await db.transaction(async (transaction) => { const { user_id, asset, @@ -210,7 +211,7 @@ zmqRawBlock.on("message", async (topic, message, sequence) => { asset_payment_id, token, token_amount, - token_payment_id + token_payment_id, } = issuances[tx.txid]; const user = await getUserById(user_id); @@ -218,7 +219,7 @@ zmqRawBlock.on("message", async (topic, message, sequence) => { let account = await db.Account.findOne({ where: { user_id, asset }, lock: transaction.LOCK.UPDATE, - transaction + transaction, }); account.balance = asset_amount * SATS; account.pending = 0; @@ -228,10 +229,10 @@ zmqRawBlock.on("message", async (topic, message, sequence) => { where: { id: asset_payment_id }, include: { model: db.Account, - as: "account" + as: "account", }, lock: transaction.LOCK.UPDATE, - transaction + transaction, }); payment.confirmed = true; @@ -246,7 +247,7 @@ zmqRawBlock.on("message", async (topic, message, sequence) => { account = await db.Account.findOne({ where: { user_id, asset: token }, lock: transaction.LOCK.UPDATE, - transaction + transaction, }); account.balance = token_amount * SATS; account.pending = 0; @@ -256,10 +257,10 @@ zmqRawBlock.on("message", async (topic, message, sequence) => { where: { id: token_payment_id }, include: { model: db.Account, - as: "account" + as: "account", }, lock: transaction.LOCK.UPDATE, - transaction + transaction, }); payment.confirmed = true; @@ -272,7 +273,7 @@ zmqRawBlock.on("message", async (topic, message, sequence) => { emit(user.username, "payment", payment); } }); - } else if (payments.find(p => p.hash === tx.txid)) queue[tx.txid] = 1; + } else if (payments.find((p) => p.hash === tx.txid)) queue[tx.txid] = 1; }); } catch (e) { return console.log(e); @@ -286,26 +287,26 @@ 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({ + let account, address, user, total, p; + await db.transaction(async (transaction) => { + p = await db.Payment.findOne({ where: { hash, confirmed: 0, received: 1 }, include: [ { model: db.Account, - as: "account" + as: "account", }, { model: db.Invoice, - as: "invoice" + as: "invoice", }, { model: db.User, - as: "user" - } + as: "user", + }, ], lock: transaction.LOCK.UPDATE, - transaction + transaction, }); ({ account, address, user } = p); @@ -338,7 +339,7 @@ setInterval(async () => { ); notify(user, `${total} SAT payment confirmed`); - await callWebhook(p.invoice, p); + callWebhook(p.invoice, p); } else { l.warn("couldn't find liquid payment", hash); } @@ -347,7 +348,7 @@ setInterval(async () => { }); let c = convert[address]; - if (address && c) { + if (address && c && p.account.asset === network.assetHash) { l.info( "liquid detected for conversion request", address, @@ -361,11 +362,11 @@ setInterval(async () => { address: c.address, amount: total - 100, user, - limit: total + limit: total, }); } } } catch (e) { l.error("problem processing queued liquid transaction", e.message, e.stack); } -}, 1000); +}); diff --git a/routes/liquid/send.js b/routes/liquid/send.js index 19b7344f..5abc692f 100644 --- a/routes/liquid/send.js +++ b/routes/liquid/send.js @@ -1,5 +1,6 @@ const btc = config.liquid.btcasset; const lcad = config.liquid.cadasset; +const { Transaction } = require("@asoltys/liquidjs-lib"); sendLiquid = async ({ asset, amount, user, address, memo, tx, limit }) => { if (amount > 10000000) throw new Error("Amount too large"); @@ -48,7 +49,8 @@ sendLiquid = async ({ asset, amount, user, address, memo, tx, limit }) => { const assets = Object.keys(totals); const payments = []; - return db.transaction(async transaction => { + let main, signed; + await db.transaction(async transaction => { for (let i = 0; i < assets.length; i++) { let asset = assets[i]; let amount = totals[asset]; @@ -75,12 +77,12 @@ sendLiquid = async ({ asset, amount, user, address, memo, tx, limit }) => { await faucet.reload({ transaction }); await faucet.save({ transaction }); } - - total += fee - covered; } + + total += fee - covered; } - if (limit && total > limit) + if (limit && total > limit + fee) throw new Error("Tx amount exceeds authorized amount"); if (asset !== btc || total) { @@ -132,16 +134,11 @@ sendLiquid = async ({ asset, amount, user, address, memo, tx, limit }) => { } } - if (config.liquid.walletpass) - await lq.walletPassphrase(config.liquid.walletpass, 300); - - let blinded = await lq.blindRawTransaction(tx.hex); - let signed = await lq.signRawTransactionWithWallet(blinded); - let txid = await lq.sendRawTransaction(signed.hex); - - l.info("sent liquid tx", txid, address); + signed = await lq.signRawTransactionWithWallet( + await lq.blindRawTransaction(tx.hex) + ); + let txid = Transaction.fromHex(signed.hex).getId(); - let main; for (let i = 0; i < assets.length; i++) { p = payments[i]; if (p) { @@ -157,15 +154,22 @@ sendLiquid = async ({ asset, amount, user, address, memo, tx, limit }) => { emit(user.username, "account", main.account); emit(user.username, "payment", main); - return main; }); + + if (config.liquid.walletpass) + await lq.walletPassphrase(config.liquid.walletpass, 300); + + let txid = await lq.sendRawTransaction(signed.hex); + l.info("sent liquid tx", txid, address); + + return main; }; module.exports = ah(async (req, res) => { let { user } = req; try { - res.send(await sendLiquid({...req.body, user })); + res.send(await sendLiquid({ ...req.body, user })); } catch (e) { l.error("problem sending liquid", user.username, e.message); return res.status(500).send(e); diff --git a/routes/lnurl.js b/routes/lnurl.js index adf4df7c..67f581d1 100644 --- a/routes/lnurl.js +++ b/routes/lnurl.js @@ -129,16 +129,6 @@ app.get( maxSendable = maxSendable || 1000000000; if (parseInt(amount)) minSendable = maxSendable = amount * 1000; - let invoices = await db.Invoice.findAll({ - where: { - amount - }, - order: [["id", "DESC"]], - limit: 1 - }); - - if (invoices.length) await invoices[0].destroy(); - try { const result = await lnurlServer.generateNewUrl("payRequest", { minSendable, diff --git a/routes/payments.js b/routes/payments.js index 70b711da..efb01079 100644 --- a/routes/payments.js +++ b/routes/payments.js @@ -96,6 +96,7 @@ ah(async () => { if (config.lna.clightning) { lna = require("clightning-client")(config.lna.dir); } else { + lnd = require("../lib/lnd"); lna = lnd.default; lnp = [ "addInvoice", diff --git a/routes/referrals.js b/routes/referrals.js index 3bcce5b2..11cf8590 100644 --- a/routes/referrals.js +++ b/routes/referrals.js @@ -244,6 +244,7 @@ router.post( debug('email: ' + email) debug('phone: ' + phone) + debug('user_id: ' + user_id) await knex.table('waiting_list') .insert({ @@ -259,15 +260,17 @@ router.post( router.get( "/joinQueue", ah(async (req, res) => { - const {email, phone} = req.query; + const {email, phone, user_id} = req.query; debug('email: ' + email) debug('phone: ' + phone) + debug('user: ' + user_id) await knex('waiting_list') .insert({ email: email, - phone: phone + phone: phone, + user_id: user_id }) res.send({success: true, message: 'Added ' + email + ' to waiting list ' + phone}) diff --git a/routes/send.js b/routes/send.js index 579e70b4..3aec9fb6 100644 --- a/routes/send.js +++ b/routes/send.js @@ -45,7 +45,7 @@ module.exports = ah(async (req, res, next) => { }; if (!username) { - return res.status(500).send("Vouchers temporarily disabled"); + throw new Error("Vouchers temporarily disabled"); l.info("creating redeemable payment"); params.redeemcode = uuidv4(); params.hash = `${req.get("origin")}/redeem/${params.redeemcode}`; diff --git a/routes/users.js b/routes/users.js index 71f4b89a..23f016c7 100644 --- a/routes/users.js +++ b/routes/users.js @@ -148,7 +148,8 @@ app.post( return res.status(500).send("Username taken"); } else { sockets[username] = sockets[user.username]; - if (user.username !== 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); @@ -323,10 +324,7 @@ app.post( (user.password && !(await bcrypt.compare(req.body.password, user.password))) ) { - l.warn( - "invalid username or password attempt", - req.body.username - ); + l.warn("invalid username or password attempt", req.body.username); return res.status(401).end(); } @@ -426,11 +424,24 @@ app.get( : config.liquid.network ]; type = "p2sh"; - + // async request to node to bump its internal index but don't use result - lq.getNewAddress().catch(console.error); + lq.getNewAddress().catch(e => + l.warn("Problem bumping liquid address index", e.message) + ); i = parseInt(app.get("lqAddressIndex")); + + if (!i) { + const { hdkeypath } = await lq.getAddressInfo( + await lq.getNewAddress() + ); + const parts = hdkeypath.split("/"); + i = parts[parts.length - 1].slice(0, -1); + } + + if (!i) throw new Error("Problem generating address"); + hd = fromBase58(config.liquid.masterkey, n).derivePath(`m/0'/0'/${i}'`); app.set("lqAddressIndex", i + 1); } else { |
