Building a Lightning App (Lapp) - Discussion

Did you got any errors when doing npm install?

I use cygwin (https://www.cygwin.com/) when working on windows. You could also try using the bash shell that is installed with git, though I’m not sure how well it would work with other shell commands on windows.

You have to have the server running before you’ll be able to access the website because jade is a template engine and will not render without it.

Using the official instructions for the node is probably best. Have you decided on a client you want to use? :slight_smile:

1 Like

following fililp’s “Hello World” video, the last step (removing the 1st level --h1-- header message and replacing it with the “message” variable pointing to index.js, which requires us to restart the server) gave me an error on the webpage reload (i.e. i got through all the steps without issue, but the last check --has the webpage loaded the “message” variable?-- failed.
i figured this out already (i’d used the wrong commenting paradigm in my scripts), but the remaining question here: he said there were two ways to do this, but then he stops the video after this one way… is the other way much more complicated?

i also wanted to drop off another question (this one from the first video on improving payment verification with webhooks): at which point exactly is it that we can no longer avoid a user repeatedly using the same URL to get the product/service repeatedly?
my understanding was that we send the user to this page only when they pay or close the window (i guess they could go to the invoice page and just close it, but that’s not what he said in the video: “just use the old URL”); doesn’t the btcpay scripting use a different terminology for an invoice already paid, i.e. “complete”? if so, we could just remove that from the options in the router.get function… also how does the loading the URL itself trigger the product/service (vs. just triggering the “thank you” page, i.e. post-hoc)?

edit: this in particular is really confusing me
“when we create this invoice, we want to send it in a string”
“want to send a string that is a notification URL as a string when we create the invoice"

i guess i’m just not understanding how this vulnerability exists, like where in the code it is instantiated…
thanks for any pointers

I’m not sure I understand. When you create an invoice you get redirected to a new page with a Bitpay popup that contains the qr code for the user to be able to pay. Once the invoice gets paid it would trigger a redirect to a completed page. I don’t think we implemented a page for a failed payment and there is no practical way for the user to get to an already paid invoice.

1 Like

yeah, i think i finally realized that the webhooks idea is that you set up a whole 'nother page to listen for POST requests incoming from a server you don’t control, like a web callback or something… that helped with the confusion around filip’s quotes i listed.

as for the invoice issue (precursor video to the challenge videos), he was saying if you just take the {domain}.com/invoice/{invoiceID} and copy and paste it (i.e. before webhooks came to save the day), you somehow replicate the transaction without spending the money to get the product/service?? i was going through the code from index.js through index.jade to invoice.js to try and figure out where that vulnerability crops up exactly, but the control flow, so-to-speak, between these files was really difficult to follow for me… it doesn’t help that i have no idea how to debug in the terminal, let alone across the terminal and a served page…

so you’re saying (if i understand correctly) that when i (the user) create an invoice, i’m redirected to a bitpay popup, which (once paid) would redirect me to the completed page (which i think is the one with the {invoiceID} at the end where the vulnerability was); if so, i was scratching my head trying to figure out why the {invoiceID} is necessary to serve as part of the URL, why not just hash it or rename it somehow?

The /invoice endpoint that you use to pay is a post method, it doesn’t accept id in the url. Once you have a paid invoice it will redirect you to a get method with the invoice id. Not sure why this wouldn’t be safe, sending id as get param is pretty standard practice.
If you want to change that part you can create a new post site and redirect the finished invoice there and send the id in the body.

1 Like

when you say “/invoice endpoint you use to pay is a post method”, does that mean invoice.js setting up invoice.jade? or invoice.jade is the /invoice endpoint?
he said something about the way we initially coded it being sloppy because of its vulnerability to being copy/pasted; beyond that i hardly understand anything except what’s in front of my nose when i’m coding… anyway, i hardly understood it, so my apologies if i’m doing a bad job describing it.

If you look in the invoice.js file, you’ll see you have defined two endpoints. A get and a post endpoint. Post is used to open a Bitpay popup and get one is used to redirect the user after the payment either succeeded or failed.
These are standard HTTP methods used for web development https://www.w3schools.com/tags/ref_httpmethods.asp

1 Like

ok, i think i’m getting it as far as endpoints: essentially, the invoice.js can route post requests to the router.post endpoint (endpoint being the submit payment page in this case), and it can route anything with the invoice/{invoice id} in the http to the get method (which is the invoice.jade file).

as to filip’s point:
in this video (https://academy.moralis.io/lessons/improving-payment-verification-with-webhooks-part-1-theory) from 1:25 to 1:50, he describes this issue, which i think i understand as “[anyone can copy/paste the URL that invoice.jade puts up]”, but again, i’m not sure i understand all the moving parts; you were saying it’s standard to send id as get param, which i think means it’s safe enough to do this (all of which filip later says is unnecessary when using webhooks)

/* get & verify invoice. */ // i.e. get invoice/{invoiceID}
router.get('/:id', async function(req, res, next) { //REQuest, RESolve, NEXT (step??)
  // payment verification
  var invoiceID = req.params.id;  // 'req.params.id' is coming from the input: '/:id'

  client.get_invoice(invoiceID)
  .then(invoice => {                                                        // check if invoice is paid, ...
      if (invoice.status == "complete" || invoice.status == "paid") {
                                                                            //... if so, deliver product/service ...
        res.end("<html>Thank you!</html>"); // could also res.render a new page with more follow-up, but let's just end it here
      }
      else {                                                                //... and if no, do something about it!
        res.end("<html>Hey, we want more money!</html>")
      }
    })
    .catch(err => console.log(err))
});

does that make sense? am i misunderstanding what he’s saying in that clip, or what you’re saying about the standard practice?
my original question was basically where’s the code that allows for such a vulnerability; i figured it was within this code (if (invoice.status==“complete” || invoice.status==“paid”) or invoice.jade…

Yes one would see the invoiceId of the invoice in the URL of the get request. So the issue in this case is the /:id in the request. This would give the user the id to the invoice. But to actually exploit that one would have to gain access to btcpay server.
There are benefits to this, maybe one would want to send the id to the seller in case of support issues or someone else to show them they actually paid the invoice.

1 Like

ahhh, i see… interesting also the benefits…

so he was saying because the logic in our invoice.js takes that “/:id” input and checks if paid in order to immediately render service/product, it’s happening “too fast”, i.e. there needs to be some check on whether service has already been rendered (i.e. even if paid), not just whether the invoice has been paid… logic that would be built into the webhook page allows us to check in our own database whether that’s been satisfied or not

thanks a lot for following up on all that with me and giving me somewhere to think out loud.

1 Like

Hello i’m a novice with the terminal and working my way around the lightning APP. When i type the localhost:3000 it doesn’t connect, on the terminal i get the following error when i type ~npm start~

TypeError: Cannot read properties of null (reading ‘fromRed’)
at Point.getX (/Users/odaykamal/lightning-app-boilerplate/node_modules/elliptic/lib/elliptic/curve/short.js:416:17)
at Point._encode (/Users/odaykamal/lightning-app-boilerplate/node_modules/elliptic/lib/elliptic/curve/base.js:294:16)
at Point.encode (/Users/odaykamal/lightning-app-boilerplate/node_modules/elliptic/lib/elliptic/curve/base.js:303:28)
at Point.encodeCompressed (/Users/odaykamal/lightning-app-boilerplate/node_modules/elliptic/lib/elliptic/curve/base.js:289:15)
at Function.get_sin_from_key (/Users/odaykamal/lightning-app-boilerplate/node_modules/btcpay/dist/core/cryptography.js:16:47)
at new BTCPayClient (/Users/odaykamal/lightning-app-boilerplate/node_modules/btcpay/dist/core/client.js:13:53)
at Object. (/Users/odaykamal/lightning-app-boilerplate/routes/invoice.js:9:16)
at Module._compile (node:internal/modules/cjs/loader:1101:14)
at Object.Module._extensions…js (node:internal/modules/cjs/loader:1153:10)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Module.require (node:internal/modules/cjs/loader:1005:19)
at require (node:internal/modules/cjs/helpers:102:18)
at Object. (/Users/odaykamal/lightning-app-boilerplate/app.js:9:21)
at Module._compile (node:internal/modules/cjs/loader:1101:14)
at Object.Module._extensions…js (node:internal/modules/cjs/loader:1153:10)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Module.require (node:internal/modules/cjs/loader:1005:19)
at require (node:internal/modules/cjs/helpers:102:18)
at Object. (/Users/odaykamal/lightning-app-boilerplate/bin/www:7:11)
at Module._compile (node:internal/modules/cjs/loader:1101:14)
MacBook-Pro-2:lightning-app-boilerplate odaykamal$

1 Like

Seems like you didn’t installed all the dependencies. Did you got any error when installing them?

Hi Alko i didnt get any errors, I just followed the video. Ill try redownloading them again. Can you share the link please?

1 Like

What link do you mean? BTCpay server is on https://lightning.filipmartinsson.com/

Hello,

Can someone help me? I’m on the creating API key section and encountered the following after the git clone command (see image below). I followed and tried the directions twice.

  • David

1 Like

You have to install git.

Hi Alko89,

Thank you for helping me on this course too. How do you install git? It appears that I’m running into that issue for the BTC programming course too.

Sincerely,

David

https://git-scm.com/download/win

Hello,

I tried this section again and used the following command:
node -e “const btcpay=require(‘btcpay’); new btcpay.BTCPayClient(’<BTCPAY_URL>’, btcpay.crypto.load_keypair(Buffer.from(’<BTCPAY_KEY>’, ‘hex’))).pair_client(’<BTCPAY_PAIRCODE>’).then(console.log).catch(console.error)”

But after inserting the website (https://lightning.filipmartinsson.com/), my private key, and pairing code, this is what my screen displays.

Hmm, I’m not sure I’ve never encountered this error. Can you provide more detailed steps you made to get to this state?

I’ve updated BTCPay server, we were running a bit older version but I don’t think this was the issue, you can try again just in case.