aboutsummaryrefslogtreecommitdiffstats
path: root/lib/invoices.js
blob: 4a09f44b47644cab3c5f8053d9d5dbfa4dc57c2c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import store from "$lib/store";
import { l } from "$lib/logging";
import { emit } from "$lib/sockets";
import { db, g, s } from "$lib/db";
import { bip21, fail } from "$lib/utils";
import { types } from "$lib/payments";
import { v4 } from "uuid";

import bc from "$lib/bitcoin";
import ln from "$lib/ln";

export let generate = async ({ invoice, user, sender }) => {
  let { currency, tip, amount, rate, request_id, type } = invoice;

  amount = parseInt(amount || 0);
  tip = parseInt(tip || 0);

  if (amount < 0) fail("amount out of range");
  if (tip > 5 * amount || tip < 0) fail("tip amount out of range");

  if (!user) user = sender;
  let uid = await g(`user:${user.username}`);
  user = await g(`user:${uid}`);

  if (!user) fail("user not provided");

  if (!currency) currency = user.currency;
  if (!rate) rate = store.rates[currency];
  if (amount < 0) fail("invalid amount");

  let hash, text;
  if (type === types.lightning) {
    let amt = amount ? `${amount + tip}sat` : "any";
    let r = await ln.invoice(amt, new Date(), "", 3600);

    hash = r.payment_hash;
    text = r.bolt11;
  } else if (type === types.bitcoin) {
    hash = await bc.getNewAddress();
    text = bip21(hash, invoice);
  } else if (type === types.internal) {
    hash = v4();
  } else {
    fail("unrecognized type");
  }

  invoice = {
    ...invoice,
    amount,
    hash,
    text,
    currency,
    rate,
    tip,
    uid,
    received: 0,
    created: Date.now()
  };

  l("creating invoice", user.username, amount, tip, currency, invoice.hash);

  await s(`invoice:${hash}`, invoice);
  await db.lPush(`${uid}:invoices`, hash);

  if (request_id) {
    let request = await g(`request:${request_id}`);
    let { invoice_id: prev } = request;
    request.invoice_id = invoice.id;
    await s(`request:${request_id}`, request);

    if (!prev) emit(request.requester.username, "invoice", invoice);
  }

  return invoice;
};