diff options
| author | Adam Soltys <[email protected]> | 2022-09-30 15:07:30 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2022-09-30 15:07:30 -0700 |
| commit | 4ee46fee0cbf23f51228c7c4895ee1e0565b074f (patch) | |
| tree | 803dc7399926ff508114f6e7e315b72ada399b87 /routes | |
| parent | a8aaef0abb75cf00e28cd3bd5f747246cf83049a (diff) | |
| download | coinos-server-4ee46fee0cbf23f51228c7c4895ee1e0565b074f.tar.gz coinos-server-4ee46fee0cbf23f51228c7c4895ee1e0565b074f.zip | |
derive address/payreq server side
Diffstat (limited to 'routes')
| -rw-r--r-- | routes/invoices.js | 86 | ||||
| -rw-r--r-- | routes/payments.js | 1 | ||||
| -rw-r--r-- | routes/users.js | 108 |
3 files changed, 55 insertions, 140 deletions
diff --git a/routes/invoices.js b/routes/invoices.js index b5926fec..9f93180d 100644 --- a/routes/invoices.js +++ b/routes/invoices.js @@ -5,6 +5,9 @@ import { optionalAuth } from "$lib/passport"; import { Op } from "@sequelize/core"; import axios from "axios"; import { err, l } from "$lib/logging"; +import bc from "$lib/bitcoin"; +import lq from "$lib/liquid"; +import { SATS, bip21, deriveAddress, derivePayRequest } from "$lib/utils"; app.get("/invoice", async (req, res, next) => { try { @@ -27,15 +30,12 @@ app.get("/invoice", async (req, res, next) => { app.post("/invoice", optionalAuth, async (req, res, next) => { try { - let { liquidAddress, id, invoice, user, tx } = req.body; - let { blindkey } = invoice; + let { type = "bech32", liquidAddress, id, invoice, user, tx } = req.body; + let { blindkey, currency, tip, amount, rate, network } = invoice; + let address, unconfidential, text; - if (invoice.amount < 0) throw new Error("amount out of range"); - if ( - invoice.tip > invoice.amount || - invoice.tip > 1000000 || - invoice.tip < 0 - ) + if (amount < 0) throw new Error("amount out of range"); + if (tip > amount || tip > 1000000 || tip < 0) throw new Error("tip amount out of range"); if (liquidAddress) { @@ -48,18 +48,56 @@ app.post("/invoice", optionalAuth, async (req, res, next) => { user = await db.User.findOne({ where: { username: user.username + }, + include: { + model: db.Account, + as: "account" } }); } if (!user) throw new Error("user not provided"); - if (!invoice.currency) invoice.currency = user.currency; - if (!invoice.rate) invoice.rate = store.rates[invoice.currency]; - if (invoice.tip > invoice.amount || invoice.tip > 1000000) - throw new Error("tip is too large"); - if (invoice.tip < 0 || invoice.amount < 0) - throw new Error("invalid amount"); - invoice.user_id = user.id; - invoice.account_id = user.account_id; + if (!currency) currency = user.currency; + if (!rate) rate = store.rates[currency]; + if (tip > amount || tip > 1000000) throw new Error("tip is too large"); + if (tip < 0 || amount < 0) throw new Error("invalid amount"); + + if (user.account.pubkey) { + let { address, confidentialAddress } = await deriveAddress( + user.account, + type + ); + if (confidentialAddress) { + address = confidentialAddress; + unconfidential = address; + } else { + address = address; + } + } else if (network !== "lightning") { + console.log(network, { bitcoin: bc, liquid: lq }[network]) + address = await { bitcoin: bc, liquid: lq }[network].getNewAddress(); + if (network === "liquid") + ({ unconfidential } = await lq.getAddressInfo(address)); + } + + invoice = { + ...invoice, + account_id: user.account.id, + address, + amount, + currency, + rate, + tip, + unconfidential, + user_id: user.id + }; + + if (network === "lightning") { + invoice.text = await derivePayRequest(invoice); + } else { + invoice.text = bip21(invoice, user.account); + } + + console.log("TEXT", invoice.text) l( "creating invoice", @@ -73,21 +111,7 @@ app.post("/invoice", optionalAuth, async (req, res, next) => { if (!invoice.tip) invoice.tip = 0; - const exists = - invoice.text && - (await db.Invoice.findOne({ - where: { - [Op.or]: { - address: invoice.address || "", - unconfidential: invoice.unconfidential || "", - text: invoice.text - } - } - })); - - invoice = exists - ? await exists.update(invoice) - : await db.Invoice.create(invoice); + invoice = await db.Invoice.create(invoice); store.addresses[invoice.address] = user.username; if (invoice.unconfidential) { store.addresses[invoice.unconfidential] = user.username; diff --git a/routes/payments.js b/routes/payments.js index 298309e0..8b91d9fb 100644 --- a/routes/payments.js +++ b/routes/payments.js @@ -58,7 +58,6 @@ app.get("/except", adminAuth, (req, res) => { }); app.post("/lightning/channel", lnRoutes.channel); -app.post("/lightning/invoice", lnRoutes.invoice); app.post("/lightning/query", auth, lnRoutes.query); app.post("/lightning/send", auth, lnRoutes.send); diff --git a/routes/users.js b/routes/users.js index 61d5d33a..3063758d 100644 --- a/routes/users.js +++ b/routes/users.js @@ -360,114 +360,6 @@ app.post("/logout", optionalAuth, async (req, res) => { res.send({}); }); -app.get("/address", async (req, res) => { - let { network, type } = req.query; - let address, confidentialAddress; - - let paymentType = { - bech32: "p2wpkh", - "p2sh-segwit": "p2sh", - legacy: "p2pkh", - }[type]; - if (!paymentType) paymentType = "p2wpkh"; - - let hd, i, p, n; - const mutex = new Mutex(); - const release = await mutex.acquire(); - try { - if (network === "bitcoin") { - if (!config.bitcoin) return res.code(500).send("Bitcoin not configured"); - - address = await bc.getNewAddress("", type); - store.bcAddressIndex = i + 1; - return res.send({ address }); - - p = bitcoin.payments; - n = prod ? bitcoin.networks["bitcoin"] : bitcoin.networks["regtest"]; - - i = parseInt(store.bcAddressIndex); - hd = fromBase58(config.bitcoin.masterkey, n).derivePath(`m/0'/0'/${i}'`); - - // async request to node to bump its internal index but don't use result - bc.getNewAddress().catch(console.error); - res.send({ address, confidentialAddress }); - - store.bcAddressIndex = i + 1; - } else if (network === "liquid") { - p = liquid.payments; - n = - liquid.networks[ - config.liquid.network === "mainnet" ? "liquid" : config.liquid.network - ]; - paymentType = "p2sh"; - - // async request to node to bump its internal index but don't use result - lq.getNewAddress().catch((e) => - warn("Problem bumping liquid address index", e.message) - ); - - i = parseInt(store.lqAddressIndex); - - if (!i) { - const { hdkeypath } = await lq.getAddressInfo(await lq.getNewAddress()); - const parts = hdkeypath.split("/"); - i = parseInt(parts[parts.length - 1].slice(0, -1)); - } - - l("liquid address index", i); - if (!i) throw new Error("Problem generating address"); - - hd = fromBase58(config.liquid.masterkey, n).derivePath(`m/0'/0'/${i}'`); - store.lqAddressIndex = i + 1; - } else { - throw new Error("Unsupported network"); - } - } finally { - release(); - } - - if (paymentType !== "p2sh") { - ({ address } = p[paymentType]({ - pubkey: hd.publicKey, - network: n, - })); - } else { - if (network === "liquid") { - const p2wpkh = p.p2wpkh({ - pubkey: hd.publicKey, - network: n, - }); - - const blindkey = fromPrivateKey( - Buffer.from(config.liquid.blindkey, "hex"), - hd.chainCode, - n - ); - - ({ address, confidentialAddress } = p[paymentType]({ - redeem: p2wpkh, - network: n, - blindkey: blindkey.publicKey, - })); - - lq.importBlindingKey( - confidentialAddress, - blindkey.privateKey.toString("hex") - ); - } else { - ({ address } = p[paymentType]({ - redeem: p.p2wpkh({ - pubkey: hd.publicKey, - network: n, - }), - network: n, - })); - } - } - - res.send({ address, confidentialAddress }); -}); - app.post("/account", auth, async (req, res) => { const { user } = req; const { |
