From 2b20a6661a52e14c2b8fc43080f5636fbb211097 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Sat, 8 Oct 2022 07:06:46 +0000 Subject: fix lightning conversions --- routes/invoices.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'routes') diff --git a/routes/invoices.js b/routes/invoices.js index bdb889a2..512679db 100644 --- a/routes/invoices.js +++ b/routes/invoices.js @@ -121,8 +121,8 @@ app.post("/invoice", optionalAuth, async (req, res, next) => { } if (liquidAddress) { - l("conversion request for", liquidAddress, text); - store.convert[text] = { address: liquidAddress, tx }; + l("conversion request for", liquidAddress, invoice.text); + store.convert[invoice.text] = { address: liquidAddress, tx }; } l( -- cgit v1.2.3 From 4c596cfdcd04ee81ffc9be2e1ce2e5ee68154036 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Mon, 10 Oct 2022 18:47:11 +0000 Subject: fix liquid send --- routes/invoices.js | 32 ++++++++++++++++++++------------ routes/liquid/send.js | 8 ++++---- 2 files changed, 24 insertions(+), 16 deletions(-) (limited to 'routes') diff --git a/routes/invoices.js b/routes/invoices.js index 512679db..3a7f16b5 100644 --- a/routes/invoices.js +++ b/routes/invoices.js @@ -13,13 +13,13 @@ app.get("/invoice", async (req, res, next) => { try { const invoice = await db.Invoice.findOne({ where: { - uuid: req.query.uuid + uuid: req.query.uuid, }, include: { model: db.User, as: "user", - attributes: ["username", "currency"] - } + attributes: ["username", "currency"], + }, }); res.send(invoice); @@ -38,7 +38,7 @@ app.get("/invoice/:text", async (req, res, next) => { : text.startsWith("ln") ? { text } : { - [Op.or]: [{ unconfidential: text }, { address: text }] + [Op.or]: [{ unconfidential: text }, { address: text }], }; const invoice = await db.Invoice.findOne({ @@ -46,8 +46,8 @@ app.get("/invoice/:text", async (req, res, next) => { include: { model: db.User, as: "user", - attributes: ["username", "currency"] - } + attributes: ["username", "currency"], + }, }); res.send(invoice); @@ -71,12 +71,12 @@ app.post("/invoice", optionalAuth, async (req, res, next) => { else { user = await db.User.findOne({ where: { - username: user.username + username: user.username, }, include: { model: db.Account, - as: "account" - } + as: "account", + }, }); } if (!user) throw new Error("user not provided"); @@ -111,7 +111,7 @@ app.post("/invoice", optionalAuth, async (req, res, next) => { rate, tip, unconfidential, - user_id: user.id + user_id: user.id, }; if (network === "lightning") { @@ -121,8 +121,16 @@ app.post("/invoice", optionalAuth, async (req, res, next) => { } if (liquidAddress) { - l("conversion request for", liquidAddress, invoice.text); - store.convert[invoice.text] = { address: liquidAddress, tx }; + if (network === "lightning") { + l("conversion request for", liquidAddress, invoice.text); + store.convert[invoice.text] = { address: liquidAddress, tx }; + } else if (network === "liquid") { + l("conversion request for", liquidAddress, invoice.unconfidential); + store.convert[invoice.unconfidential] = { address: liquidAddress, tx }; + } else { + l("conversion request for", liquidAddress, invoice.address); + store.convert[invoice.address] = { address: liquidAddress, tx }; + } } l( diff --git a/routes/liquid/send.js b/routes/liquid/send.js index 2fa7a22a..d7a7c7b4 100644 --- a/routes/liquid/send.js +++ b/routes/liquid/send.js @@ -44,16 +44,16 @@ export const sendLiquid = async ({ asset, amount, user, address, memo, tx, limit let { asset, value, - scriptPubKey: { type, addresses } + scriptPubKey } = vout[i]; - if (type === "fee") fee = toSats(value); + if (scriptPubKey.type === "fee") fee = toSats(value); else { if (!totals[asset]) totals[asset] = change[asset] = 0; totals[asset] += toSats(value); - if (addresses) { - if (await isChange(addresses[0])) { + if (scriptPubKey.address) { + if (await isChange(scriptPubKey.address)) { change[asset] += toSats(value); } } -- cgit v1.2.3 From 95507964eaa529412c0cc2f8153aa9f35636d4bc Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Wed, 12 Oct 2022 21:45:57 +0000 Subject: rm pw confirmation --- routes/users.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'routes') diff --git a/routes/users.js b/routes/users.js index c270902c..5ecc387a 100644 --- a/routes/users.js +++ b/routes/users.js @@ -177,7 +177,7 @@ app.post("/user", auth, async (req, res) => { user.email = email; user.address = address; - if (password && password === confirm) { + if (password) { user.password = await bcrypt.hash(password, 1); } -- cgit v1.2.3 From d97b2543f6b9b5a969e2f9fa93f6064b543a58c5 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Thu, 13 Oct 2022 15:07:18 -0700 Subject: only return hosted balances --- routes/info.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'routes') diff --git a/routes/info.js b/routes/info.js index 6c2c601d..f3de8907 100644 --- a/routes/info.js +++ b/routes/info.js @@ -38,12 +38,14 @@ app.get("/info", async (req, res, next) => { app.get("/balances", async (req, res, next) => { try { const accounts = await db.Account.findAll({ + where: { + pubkey: null + }, attributes: [ "asset", - "pubkey", [sequelize.fn("sum", sequelize.col("balance")), "total"] ], - group: ["asset", "pubkey"] + group: ["asset"] }); let lnchannel; -- cgit v1.2.3 From a4cccc51652405d6c3d2b6edd2dba5627c3535ba Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Thu, 13 Oct 2022 18:05:49 -0700 Subject: tickets --- index.js | 2 ++ lib/redis.js | 11 +++++++++ package.json | 1 + pnpm-lock.yaml | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ routes/tickets.js | 19 +++++++++++++++ 5 files changed, 105 insertions(+) create mode 100644 lib/redis.js create mode 100644 routes/tickets.js (limited to 'routes') diff --git a/index.js b/index.js index 06338fbc..c0db543c 100644 --- a/index.js +++ b/index.js @@ -6,6 +6,7 @@ import { l, err } from "./lib/logging"; import { optionalAuth } from "$lib/passport"; import "./db"; +import "./lib/redis"; import "./lib/sockets"; import "./lib/webhooks"; import "./lib/passport"; @@ -21,6 +22,7 @@ import "./routes/users"; import "./routes/invoices"; import "./routes/payments"; import "./routes/lnurl"; +import "./routes/tickets"; if (config.bitcoin) store.networks.push("bitcoin"); if (config.liquid) store.networks.push("liquid"); diff --git a/lib/redis.js b/lib/redis.js new file mode 100644 index 00000000..98a71856 --- /dev/null +++ b/lib/redis.js @@ -0,0 +1,11 @@ +import { createClient } from "redis"; + +const redis = createClient({ + url: "redis://redis", +}); + +redis.on("error", (err) => console.log("redis error", err)); + +await redis.connect(); + +export default redis; diff --git a/package.json b/package.json index 033cb60f..93810935 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "pump": "^3.0.0", "query-string": "^6.13.1", "readable-stream-clone": "^0.0.7", + "redis": "^4.3.1", "sqlite3": "^5.0.11", "tiny-secp256k1": "^2.1.2", "uuid": "8", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bf5b859b..5caf125d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -53,6 +53,7 @@ specifiers: pump: ^3.0.0 query-string: ^6.13.1 readable-stream-clone: ^0.0.7 + redis: ^4.3.1 sqlite3: ^5.0.11 tiny-secp256k1: ^2.1.2 uuid: '8' @@ -113,6 +114,7 @@ dependencies: pump: 3.0.0 query-string: 6.14.1 readable-stream-clone: 0.0.7 + redis: 4.3.1 sqlite3: 5.0.11 tiny-secp256k1: 2.1.2 uuid: 8.3.2 @@ -369,6 +371,55 @@ packages: resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} dev: false + /@redis/bloom/1.0.2_@redis+client@1.3.0: + resolution: {integrity: sha512-EBw7Ag1hPgFzdznK2PBblc1kdlj5B5Cw3XwI9/oG7tSn85/HKy3X9xHy/8tm/eNXJYHLXHJL/pkwBpFMVVefkw==} + peerDependencies: + '@redis/client': ^1.0.0 + dependencies: + '@redis/client': 1.3.0 + dev: false + + /@redis/client/1.3.0: + resolution: {integrity: sha512-XCFV60nloXAefDsPnYMjHGtvbtHR8fV5Om8cQ0JYqTNbWcQo/4AryzJ2luRj4blveWazRK/j40gES8M7Cp6cfQ==} + engines: {node: '>=14'} + dependencies: + cluster-key-slot: 1.1.0 + generic-pool: 3.8.2 + yallist: 4.0.0 + dev: false + + /@redis/graph/1.0.1_@redis+client@1.3.0: + resolution: {integrity: sha512-oDE4myMCJOCVKYMygEMWuriBgqlS5FqdWerikMoJxzmmTUErnTRRgmIDa2VcgytACZMFqpAOWDzops4DOlnkfQ==} + peerDependencies: + '@redis/client': ^1.0.0 + dependencies: + '@redis/client': 1.3.0 + dev: false + + /@redis/json/1.0.4_@redis+client@1.3.0: + resolution: {integrity: sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==} + peerDependencies: + '@redis/client': ^1.0.0 + dependencies: + '@redis/client': 1.3.0 + dev: false + + /@redis/search/1.1.0_@redis+client@1.3.0: + resolution: {integrity: sha512-NyFZEVnxIJEybpy+YskjgOJRNsfTYqaPbK/Buv6W2kmFNaRk85JiqjJZA5QkRmWvGbyQYwoO5QfDi2wHskKrQQ==} + peerDependencies: + '@redis/client': ^1.0.0 + dependencies: + '@redis/client': 1.3.0 + dev: false + + /@redis/time-series/1.0.3_@redis+client@1.3.0: + resolution: {integrity: sha512-OFp0q4SGrTH0Mruf6oFsHGea58u8vS/iI5+NpYdicaM+7BgqBZH8FFvNZ8rYYLrUO/QRqMq72NpXmxLVNcdmjA==} + peerDependencies: + '@redis/client': ^1.0.0 + dependencies: + '@redis/client': 1.3.0 + dev: false + /@sequelize/core/7.0.0-alpha.10_jza55q5z6t5fyeys4gcza62sym: resolution: {integrity: sha512-uikpWaCiIaijsgoa9cH+3jCQl8r+FaQPhoE8AOJYvPwxOx52E1JZnRPMXNnlpbFy3Xu0qekrc5LBJq7IR8UB0Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1308,6 +1359,11 @@ packages: mimic-response: 1.0.1 dev: false + /cluster-key-slot/1.1.0: + resolution: {integrity: sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==} + engines: {node: '>=0.10.0'} + dev: false + /co/4.6.0: resolution: {integrity: sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} @@ -2222,6 +2278,11 @@ packages: is-property: 1.0.2 dev: false + /generic-pool/3.8.2: + resolution: {integrity: sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg==} + engines: {node: '>= 4'} + dev: false + /get-caller-file/2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} @@ -4045,6 +4106,17 @@ packages: resolve: 1.20.0 dev: false + /redis/4.3.1: + resolution: {integrity: sha512-cM7yFU5CA6zyCF7N/+SSTcSJQSRMEKN0k0Whhu6J7n9mmXRoXugfWDBo5iOzGwABmsWKSwGPTU5J4Bxbl+0mrA==} + dependencies: + '@redis/bloom': 1.0.2_@redis+client@1.3.0 + '@redis/client': 1.3.0 + '@redis/graph': 1.0.1_@redis+client@1.3.0 + '@redis/json': 1.0.4_@redis+client@1.3.0 + '@redis/search': 1.1.0_@redis+client@1.3.0 + '@redis/time-series': 1.0.3_@redis+client@1.3.0 + dev: false + /registry-auth-token/4.2.1: resolution: {integrity: sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==} engines: {node: '>=6.0.0'} diff --git a/routes/tickets.js b/routes/tickets.js new file mode 100644 index 00000000..0334c2c6 --- /dev/null +++ b/routes/tickets.js @@ -0,0 +1,19 @@ +import app from "$app"; +import redis from "$lib/redis"; +import { auth } from "$lib/passport"; + +app.get("/ticket", async (req, res) => { + res.send({ ticket: await redis.lLen("tickets") }); +}); + +app.post("/ticket", auth, async (req, res) => { + try { + let { asset } = req.body; + if (!asset || asset.length !== 64) throw new Error("invalid asset"); + await redis.lPush("tickets", req.body.asset); + + res.send(await redis.lPush("tickets", req.body.asset)); + } catch (e) { + res.code(500).send(e.message); + } +}); -- cgit v1.2.3 From 22d2777bb6bf9e5eb61fd14c05d8ae9ae7586481 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Mon, 17 Oct 2022 21:11:08 +0000 Subject: rm hostname --- routes/lnurl.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'routes') diff --git a/routes/lnurl.js b/routes/lnurl.js index 683899b0..2a7cb772 100644 --- a/routes/lnurl.js +++ b/routes/lnurl.js @@ -207,6 +207,7 @@ app.get("/pay/:username", async (req, res, next) => { app.post("/pay", auth, async (req, res, next) => { const { user } = req; + const { amount, comment, @@ -228,7 +229,6 @@ app.post("/pay", auth, async (req, res, next) => { memo: comment, username: recipients[secret].username }, - hostname, user ); @@ -238,6 +238,7 @@ app.post("/pay", auth, async (req, res, next) => { res.send(await send(amount, "", data.pr, user)); } } catch (e) { + console.log(e); err("failed to send payment", e.message); res.code(500).send(e.message); } -- cgit v1.2.3 From 14b363bcfcfdd03f2232c2d0779ee90fc5cc27e6 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Tue, 18 Oct 2022 21:00:50 -0700 Subject: improve asset issuance to internal user --- docker-compose.yml | 5 ++ lib/sockets.js | 1 + routes/assets.js | 116 ++++++++++++++++++++++++++++---------------- routes/lightning/receive.js | 1 - routes/liquid/receive.js | 19 +++----- routes/tickets.js | 7 ++- 6 files changed, 92 insertions(+), 57 deletions(-) (limited to 'routes') diff --git a/docker-compose.yml b/docker-compose.yml index 8261d746..4d1a89d9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -179,6 +179,11 @@ services: networks: default: ipv4_address: 172.18.0.32 + redis: + container_name: redis + image: redis + volumes: + - ./config/redis:/data networks: default: name: net diff --git a/lib/sockets.js b/lib/sockets.js index a8428d2f..22072dd0 100644 --- a/lib/sockets.js +++ b/lib/sockets.js @@ -115,6 +115,7 @@ app.register(async function(app) { names[id] = username; let user = await getUser(username); + if (user.locked) throw new Error("Account is locked"); let payments = await user.getPayments({ where: { diff --git a/routes/assets.js b/routes/assets.js index ecc44d84..de539946 100644 --- a/routes/assets.js +++ b/routes/assets.js @@ -120,7 +120,7 @@ app.post("/assets", auth, async (req, res) => { l( "attempting issuance", req.user.username, - contract, + JSON.stringify(contract), "address", address, "pubkey", @@ -177,6 +177,7 @@ app.post("/assets", auth, async (req, res) => { as: "user" }, order: [["balance", "DESC"]], + lock: transaction.LOCK.UPDATE, transaction }); @@ -199,23 +200,51 @@ app.post("/assets", auth, async (req, res) => { await account.reload({ transaction }); emit(user.username, "account", account); + let invoice; + let recipient = user; + if (address) { + invoice = await db.Invoice.findOne({ + where: { address }, + include: { + model: db.User, + as: "user" + } + }); + recipient = invoice.user; + } + + if (!invoice) { + invoice = await db.Invoice.create( + { + account_id: account.id, + user_id, + amount: Math.round(params.asset_amount * SATS), + address: asset_address, + currency: user.currency, + rate: store.rates[user.currency], + network: "liquid" + }, + { transaction } + ); + } + account = await db.Account.create( { asset, contract, domain, - user_id, + user_id: invoice.user_id, ticker, precision, name, balance: 0, network: "liquid", - pending: address ? 0 : Math.round(params.asset_amount * SATS) + pending: Math.round(params.asset_amount * SATS) }, { transaction } ); - emit(user.username, "account", account); + emit(recipient.username, "account", account); l( "issued asset", user.username, @@ -225,24 +254,11 @@ app.post("/assets", auth, async (req, res) => { account.id ); - const { id: invoice_id } = await db.Invoice.create( - { - account_id: account.id, - user_id, - amount: Math.round(params.asset_amount * SATS), - address: asset_address, - currency: user.currency, - rate: store.rates[user.currency], - network: "liquid" - }, - { transaction } - ); - const asset_payment = await db.Payment.create( { account_id: account.id, - user_id, - invoice_id, + user_id: invoice.user_id, + invoice_id: invoice.id, hash: txid, amount: Math.round(params.asset_amount * SATS), received: true, @@ -252,14 +268,14 @@ app.post("/assets", auth, async (req, res) => { }, { transaction } ); - emit(user.username, "payment", asset_payment); + emit(recipient.username, "payment", asset_payment); - if (address) { + if (invoice.user_id !== user.id) { const asset_send = await db.Payment.create( { account_id: account.id, user_id, - invoice_id, + invoice_id: invoice.id, hash: txid, amount: -Math.round(params.asset_amount * SATS), received: false, @@ -269,7 +285,7 @@ app.post("/assets", auth, async (req, res) => { }, { transaction } ); - emit(user.username, "payment", asset_send); + emit(recipient.username, "payment", asset_send); } store.issuances[txid] = { @@ -280,10 +296,39 @@ app.post("/assets", auth, async (req, res) => { }; if (token_amount) { + invoice = null; + recipient = user; + + if (address) { + invoice = await db.Invoice.findOne({ + where: { address }, + include: { + model: db.User, + as: "user" + } + }); + recipient = invoice.user; + } + + if (!invoice) { + invoice = await db.Invoice.create( + { + account_id: account.id, + user_id, + amount: Math.round(params.token_amount * SATS), + address: token_address, + currency: user.currency, + rate: store.rates[user.currency], + network: "liquid" + }, + { transaction } + ); + } + account = await db.Account.create( { asset: token, - user_id, + user_id: invoice.user_id, domain, ticker: `${ticker}REISSUANCETOKEN`, precision: 8, @@ -293,24 +338,12 @@ app.post("/assets", auth, async (req, res) => { }, { transaction } ); - emit(user.username, "account", account); - - const { id: invoice_id } = await db.Invoice.create( - { - account_id: account.id, - user_id, - amount: Math.round(params.asset_amount * SATS), - address: asset_address, - currency: user.currency, - rate: store.rates[user.currency], - network: "liquid" - }, - { transaction } - ); + emit(recipient.username, "account", account); const token_payment = await db.Payment.create( { account_id: account.id, + invoice_id: invoice.id, user_id, hash: txid, amount: Math.round(token_amount * SATS), @@ -321,12 +354,13 @@ app.post("/assets", auth, async (req, res) => { }, { transaction } ); - emit(user.username, "payment", token_payment); + emit(recipient.username, "payment", token_payment); - if (address) { + if (invoice.user_id !== user.id) { const token_send = await db.Payment.create( { account_id: account.id, + invoice_id: invoice.id, user_id, hash: txid, amount: -Math.round(token_amount * SATS), @@ -337,7 +371,7 @@ app.post("/assets", auth, async (req, res) => { }, { transaction } ); - emit(user.username, "payment", token_send); + emit(recipient.username, "payment", token_send); } store.issuances[txid].token = token; diff --git a/routes/lightning/receive.js b/routes/lightning/receive.js index 97c4b47f..f4a20a59 100644 --- a/routes/lightning/receive.js +++ b/routes/lightning/receive.js @@ -143,7 +143,6 @@ if (config.lna.clightning) { msatoshi_received, payment_preimage: secret } = await ln.waitanyinvoice(i); - console.log("um"); let settled = status === "paid"; let received = parseInt(msatoshi_received / 1000); diff --git a/routes/liquid/receive.js b/routes/liquid/receive.js index 2f90af5e..718feba5 100644 --- a/routes/liquid/receive.js +++ b/routes/liquid/receive.js @@ -58,10 +58,8 @@ const getAccount = async (params, transaction) => { params.seed = nc.seed; } - const assets = assets; - - if (assets[asset]) { - ({ domain, ticker, precision, name } = assets[asset]); + if (store.assets[asset]) { + ({ domain, ticker, precision, name } = store.assets[asset]); } else { const existing = await db.Account.findOne({ where: { @@ -149,13 +147,14 @@ zmqRawTx.on("message", async (topic, message, sequence) => { let account = await db.Account.findOne({ where: { - id: invoice.account_id + id: invoice.account_id, + asset }, lock: transaction.LOCK.UPDATE, transaction }); - if (!(account && account.asset === asset)) { + if (!account) { let pubkey = account ? account.pubkey : null; account = await getAccount( @@ -371,13 +370,7 @@ setInterval(async () => { emit(user.username, "account", account); emit(user.username, "payment", p); - l( - "liquid confirmed", - user.username, - account.asset, - p.amount, - p.tip - ); + l("liquid confirmed", user.username, account.asset, p.amount, p.tip); notify(user, `${total} SAT payment confirmed`); callWebhook(p.invoice, p); diff --git a/routes/tickets.js b/routes/tickets.js index 0334c2c6..7ca56740 100644 --- a/routes/tickets.js +++ b/routes/tickets.js @@ -6,13 +6,16 @@ app.get("/ticket", async (req, res) => { res.send({ ticket: await redis.lLen("tickets") }); }); +app.get("/tickets", async (req, res) => { + res.send(await redis.lRange("tickets", 0, -1)); +}); + app.post("/ticket", auth, async (req, res) => { try { let { asset } = req.body; if (!asset || asset.length !== 64) throw new Error("invalid asset"); - await redis.lPush("tickets", req.body.asset); - res.send(await redis.lPush("tickets", req.body.asset)); + res.send(await redis.rPush("tickets", req.body.asset)); } catch (e) { res.code(500).send(e.message); } -- cgit v1.2.3