aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/invoice.js
blob: 1212cbe3303858724a8ebeef83fb82a41d1b2556 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { auth, get, post } from '$lib/utils';
import { redirect } from '@sveltejs/kit';

export default async ({ cookies, request }) => {
	let form = await request.formData();

	let rates = await get('/rates');

	let invoice = {
		amount: parseInt(form.get('amount')),
		tip: parseInt(form.get('tip')),
		network: 'lightning',
		prompt: form.get('prompt') === 'true',
		rate: rates[form.get('currency')]
	};

	let user = { username: form.get('username') };

	let { uuid } = await post('/invoice', { invoice, user }, auth(cookies));

	throw redirect(307, `/invoice/${uuid}`);
};
tle='author Adam Soltys <[email protected]> 2021-02-19 21:46:21 -0800 committer Adam Soltys <[email protected]> 2021-02-19 21:46:21 -0800 instant lightning->liquid conversion' href='/coinos-server.git/commit/routes/lightning/receive.js?h=cashreq&id=fb2a1a9f7262c58636b62fe1eee1b95e88a481c8'>fb2a1a9f ^
2bcd5e9c ^



d3e0bb7e ^
2bcd5e9c ^
2bcd5e9c ^
d01159ce ^

2bcd5e9c ^

















d3e0bb7e ^

205b9ba8 ^
1fbae57b ^





3bdd16bb ^
d3e0bb7e ^



3ce9c73b ^

d3e0bb7e ^
d3e0bb7e ^


3ce9c73b ^
d3e0bb7e ^

2bcd5e9c ^
ea58d17b ^
2bcd5e9c ^
a22b5cd3 ^
765c6a42 ^
47aa4840 ^
fb2a1a9f ^

47aa4840 ^




fb2a1a9f ^
47aa4840 ^








fb2a1a9f ^
47aa4840 ^




fb2a1a9f ^
47aa4840 ^


47aa4840 ^


47aa4840 ^
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
                                    
                           
                           
 




                                            
 




                                                                             


                                                                         

                                               
 
                                          


                                        
                      


                         
                    

                                      
                   

         
                           
 













                                                    
                               
             



                       
                           
                                
 

                                                                   

















                                                      

                                         
                                   





                                                    
 



                             

                              
               


                      
                                                                      

       
               
                                                              
   
  
 
                            

                             




                                
                                    








                                                            
                  




                                                 
                                                                     


            


                                             
 
const handlePayment = async msg => {
  if (!msg.settled) return;
  let account, total, user;

  const invoice = await db.Invoice.findOne({
    where: {
      text: 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)
        throw new Error("amount out of range");

      account = await db.Account.findOne({
        where: {
          user_id,
          asset: config.liquid.btcasset,
          pubkey: null
        },
        include: {
          model: db.User,
          as: "user"
        },
        lock: transaction.LOCK.UPDATE,
        transaction
      });

      ({ user } = account);

      let preimage = msg.r_preimage.toString("hex");

      let payment = await db.Payment.create(
        {
          account_id: account.id,
          user_id,
          hash,
          memo,
          amount,
          currency,
          preimage,
          rate,
          received: true,
          confirmed: true,
          network: "lightning",
          tip
        },
        { transaction }
      );

      total = amount + tip;
      invoice.received += total;

      await account.increment({ balance: total }, { transaction });
      await account.reload({ transaction });
      await invoice.save({ transaction });
      await payment.save({ transaction });
      payments.push(msg.payment_request);

      payment = payment.get({ plain: true });
      payment.account = account.get({ plain: true });

      emit(user.username, "payment", payment);
      emit(user.username, "account", payment.account);
      notify(user, `Received ${total} SAT`);

      l.info(
        "lightning payment received",
        user.username,
        payment.amount,
        payment.tip
      );
    });

    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
      );

      user.account = account;

      try {
        await sendLiquid({
          address: c.address,
          amount: total - 100,
          user,
          limit: total
        });
      } catch (e) {
        l.error("problem sending liquid payment", e.message, e.stack);
      }
    }
  } catch (e) {
    l.error("problem receiving lightning payment", e.message);
  }
};

if (config.lna.clightning) {
  const poll = async ln => {
    const wait = async i => {
      const {
        bolt11: payment_request,
        pay_index,
        status,
        msatoshi_received,
        payment_preimage: r_preimage
      } = await ln.waitanyinvoice(i);

      let settled = status === "paid";
      let amt_paid_sat = parseInt(msatoshi_received / 1000);

      await handlePayment({
        payment_request,
        settled,
        amt_paid_sat,
        r_preimage
      });
      wait(pay_index);
    };

    const { invoices } = await ln.listinvoices();
    wait(Math.max(...invoices.map(i => i.pay_index).filter(n => n)));
  };

  poll(lna);
} else {
  const invoices = lna.subscribeInvoices({});
  invoices.on("data", handlePayment);
}