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 /lib | |
| parent | a8aaef0abb75cf00e28cd3bd5f747246cf83049a (diff) | |
| download | coinos-server-4ee46fee0cbf23f51228c7c4895ee1e0565b074f.tar.gz coinos-server-4ee46fee0cbf23f51228c7c4895ee1e0565b074f.zip | |
derive address/payreq server side
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/send.js | 32 | ||||
| -rw-r--r-- | lib/utils.js | 84 |
2 files changed, 97 insertions, 19 deletions
diff --git a/lib/send.js b/lib/send.js index f20185e5..e7255219 100644 --- a/lib/send.js +++ b/lib/send.js @@ -66,10 +66,11 @@ export default async (amount, memo, hash, user) => { }); conversionFeeDeduction = Math.min(account.lightning_credits, conversionFee); + total = amount + conversionFee - conversionFeeDeduction; if ( !account || - account.balance < amount + conversionFee - conversionFeeDeduction + account.balance < total ) { warn( "user attempting to send more than they have", @@ -81,12 +82,12 @@ export default async (amount, memo, hash, user) => { } await account.decrement( - { balance: amount, lightning_credits: conversionFeeDeduction }, + { balance: total, lightning_credits: conversionFeeDeduction }, { transaction } ); await account.reload({ transaction }); - l("debited account", account.id); + l("debited account", account.id, total); let tokens; if (!payreq.satoshis) tokens = amount; @@ -100,26 +101,22 @@ export default async (amount, memo, hash, user) => { if (!m) throw new Error(`lightning payment failed ${amount} ${hash}`); if (m.payment_error) throw new Error(m.payment_error); - ({ fee, secret: preimage, tokens: total } = m); + ({ fee, secret, tokens: total } = m); + preimage = secret.toString("hex"); } else { - m = await ln.pay(hash, tokens ? `${tokens}sats` : undefined); - let sent; - ({ - msatoshi: total, - msatoshi_sent: sent, - payment_preimage: preimage - } = m); - - fee = parseInt((sent - total) / 1000); - total = parseInt(total / 1000); + let { msatoshi, msatoshi_sent, payment_preimage } = await ln.pay(hash, tokens ? `${tokens}sats` : undefined); + preimage = payment_preimage; + fee = parseInt((msatoshi_sent - msatoshi) / 1000); + total = parseInt(msatoshi / 1000); } - preimage = preimage.toString("hex"); - if (store.seen.includes(preimage)) { warn("duplicate payment detected", preimage); throw new Error("Duplicate payment detected"); } + + store.seen.push(preimage); + store.seen.push(hash); }); await db.transaction(async transaction => { @@ -226,9 +223,6 @@ export default async (amount, memo, hash, user) => { emit(user.username, "account", payment.account); emit(user.username, "payment", payment); - store.seen.push(preimage); - store.seen.push(hash); - l("sent lightning", user.username, total - fee, fee); }); diff --git a/lib/utils.js b/lib/utils.js index 1ff24c67..036ccd6d 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,5 +1,13 @@ +import config from "$config"; import db from "$db"; import sequelize from "@sequelize/core"; +import { fromBase58 } from "bip32"; +import { payments as bcPayments, networks as bcNetworks } from "bitcoinjs-lib"; +import { payments as lqPayments, networks as lqNetworks } from "liquidjs-lib"; +import { createInvoice } from "lightning"; +import lnd from "$lib/lnd"; +import ln from "$lib/ln"; + const { Op } = sequelize; export const getUser = async (username, transaction) => { @@ -90,3 +98,79 @@ export const getBlockHeight = message => { readUInt32(); return readUInt32(); }; + +export const deriveAddress = async (account, type) => { + let { index, pubkey, path, network } = account; + let n = { bitcoin: bcNetworks, liquid: lqNetworks }[network][ + prod ? "bitcoin" : "regtest" + ]; + let p = { bitcoin: bcPayments, liquid: lqPayments }[network]; + let root = fromBase58(pubkey, n); + let parts = path.split("/"); + let hd = root.derive(parseInt(parts[parts.length - 1])); + + type = { + bech32: "p2wpkh", + "p2sh-segwit": "p2sh", + legacy: "p2pkh" + }[type]; + + console.log("TYPE", type); + + let r; + if (type !== "p2sh") { + r = p[type]({ + pubkey: hd.publicKey, + network: n + }); + } else { + r = p[type]({ + redeem: p.p2wpkh({ + pubkey: hd.publicKey, + network: n + }), + network: n + }); + } + + index++; + account.index = index; + account.address = r.address; + await account.save(); + + return r; +}; + +export const bip21 = ({ address, amount, memo, tip, network }, { asset }) => { + if (network === "liquid") network = "liquidnetwork"; + + let url = amount || memo ? `${network}:${address}?` : address; + if (amount) + url += `amount=${((amount + tip) / SATS).toFixed(8)}${memo ? "&" : ""}`; + if (memo) url += `message=${memo}`; + + if (network === "liquidnetwork" && amount) { + url += `&asset=${asset}`; + } + + return url; +}; + +export const derivePayRequest = async ({ amount, memo, tip }) => { + if (!tip) tip = 0; + let value = amount + tip; + + if (config.lna.clightning) { + if (!memo) memo = "coinos"; + return (await ln.invoice(value ? `${value}sat` : "any", new Date(), memo, 360)) + .bolt11; + } else { + return ( + await createInvoice({ + lnd, + tokens: value, + description: memo + }) + ).request; + } +}; |
