Programming Challenges & Improvements - Discussion

challenge 4
this is my style for main page
excuse me for finish I have a small question but I don’t know if this is the correct discussion. Can I do something like this with react using other tools or anything else ?

h1=message
p This is a payment solution for lightning Network

style.
  body {
    background: #1C6EA4;
    background: -moz-radial-gradient(center, #1C6EA4 0%, #2388CB 55%, #144E75 100%);
    background: -webkit-radial-gradient(center, #1C6EA4 0%, #2388CB 55%, #144E75 100%);
    background: radial-gradient(ellipse at center, #1C6EA4 0%, #2388CB 55%, #144E75 100%);
    text-shadow: 1px 2px 2px #CE5937;
    text-align: center;
    ont-family: Georgia, serif;
    font-size: 16px;
    letter-spacing: 2px;
    word-spacing: 2px;
    color: #000000;
    font-weight: 700;
    text-decoration: none solid rgb(68, 68, 68);
    font-style: normal;
    font-variant: small-caps;
    text-transform: capitalize;
  
  }
    h2 {
      color: red; 
    }
    #button {
      color: rgb(255, 255, 255); font-size: 16px; line-height: 16px; padding: 6px; border-radius: 10px; font-family: Georgia, serif; font-weight: normal; text-decoration: none; font-style: normal; font-variant: normal; text-transform: none; background-image: linear-gradient(to right, rgb(28, 110, 164) 0%, rgb(35, 136, 203) 50%, rgb(20, 78, 117) 100%); box-shadow: rgb(0, 0, 0) 5px 5px 15px 5px; border: 2px solid rgb(28, 110, 164); display: inline-block;}
      .button:hover {
      background: #1C6EA4; }
      .button:active {
      background: #144E75; }
    }

1 Like

Sure you can! :smiley: You can use any web framework you want. Jade has been used here because some users might not have done the react course and would have trouble finishing the course without it. So it was easier. :slight_smile:

2 Likes

Thanks @Alko89 for your support I finished all bitcoin courses, another step for my career. I understand better now . I need to try to put all together and continue.

1 Like

:zap: LAPP improvements :hammer_and_wrench:

Just some proof of work for challenge 1

Nothing fancy for lack of time but it definitely works :+1:

Landing page with required radio button selection and a reset button:
lapp_product_choice_2021-03-19

index.jade and some invoice terminal output in VSCodium:
lapp_indexjade_2021-03-19

Invoice with a dark theme and default language set to German:
lapp_invoice_2021-03-19

invoice.js for creation and verification of the invoice:
lapp_invoicejs_2021-03-19

Already looking forward to hacking the rest together!

Hey great job! :raised_hands: the design is kind of like mine when I did it. Its fine! :sweat_smile:

:zap: LAPP improvements II :hammer_and_wrench:

Here comes challenge 2:

lapp_invoice_backend_2021-03-20 lapp_invoicejs_terminal_2021-03-20 lapp_product_customer_2021-03-20

1 Like

oh man that took me longer than i care to admit!
anyway i just did basically what filip said in the solution video (before watching it): used a radio button basically like so in the jade file

input(type="radio", name='amount', value='5') <!-- three times for three different products, value changing by cost of product-->

and the following in the router.post portion of the invoice.js file

  var dollarAmt;
  typeof req.body.amount == "string" ? dollarAmt = parseFloat(req.body.amount) : dollarAmt = req.body.amount ;

1 Like

i’m flummoxed by this error from the browser after i click submit: no context as to which file has the problem except that acorn is parsing javascript, so it’s likely invoice.js, but that position is the in the middle of a variable, i.e. makes no sense (and i’ve gotten this error when the line itself was commented out, so it seems not to be in the invoice.js file, but here’s the line i thought it was just for reference:

var buyer = {name: req.body.name, email: req.body.email, phone: req.body.phone, address1: req.body.addy1, address2: req.body.addy2};

, position 54 is the m of ‘req.body.email’)

Unexpected token (59:54)
SyntaxError: Unexpected token (59:54)
    at Parser.pp.raise (/Users/weakuser 1/Documents/crypto training/Lightning Network App programming/lightning-app-boilerplate/node_modules/acorn/dist/acorn.js:943:13)
    at Parser.pp.unexpected (/Users/weakuser 1/Documents/crypto training/Lightning Network App programming/lightning-app-boilerplate/node_modules/acorn/dist/acorn.js:1503:8)
    at Parser.pp.parseExprAtom (/Users/weakuser 1/Documents/crypto training/Lightning Network App programming/lightning-app-boilerplate/node_modules/acorn/dist/acorn.js:327:12)
    at Parser.pp.parseExprSubscripts (/Users/weakuser 1/Documents/crypto training/Lightning Network App programming/lightning-app-boilerplate/node_modules/acorn/dist/acorn.js:216:19)
    at Parser.pp.parseMaybeUnary (/Users/weakuser 1/Documents/crypto training/Lightning Network App programming/lightning-app-boilerplate/node_modules/acorn/dist/acorn.js:197:19)
    at Parser.pp.parseExprOps (/Users/weakuser 1/Documents/crypto training/Lightning Network App programming/lightning-app-boilerplate/node_modules/acorn/dist/acorn.js:151:19)
    at Parser.pp.parseMaybeConditional (/Users/weakuser 1/Documents/crypto training/Lightning Network App programming/lightning-app-boilerplate/node_modules/acorn/dist/acorn.js:133:19)
    at Parser.pp.parseMaybeAssign (/Users/weakuser 1/Documents/crypto training/Lightning Network App programming/lightning-app-boilerplate/node_modules/acorn/dist/acorn.js:110:19)
    at Parser.pp.parseMaybeAssign (/Users/weakuser 1/Documents/crypto training/Lightning Network App programming/lightning-app-boilerplate/node_modules/acorn/dist/acorn.js:120:23)
    at Parser.pp.parseExpression (/Users/weakuser 1/Documents/crypto training/Lightning Network App programming/lightning-app-boilerplate/node_modules/acorn/dist/acorn.js:86:19)
    at Parser.pp.parseParenExpression (/Users/weakuser 1/Documents/crypto training/Lightning Network App programming/lightning-app-boilerplate/node_modules/acorn/dist/acorn.js:341:18)
    at Parser.pp.parseParenAndDistinguishExpression (/Users/weakuser 1/Documents/crypto training/Lightning Network App programming/lightning-app-boilerplate/node_modules/acorn/dist/acorn.js:399:16)
    at Parser.pp.parseExprAtom (/Users/weakuser 1/Documents/crypto training/Lightning Network App programming/lightning-app-boilerplate/node_modules/acorn/dist/acorn.js:297:19)
    at Parser.pp.parseExprSubscripts (/Users/weakuser 1/Documents/crypto training/Lightning Network App programming/lightning-app-boilerplate/node_modules/acorn/dist/acorn.js:216:19)
    at Parser.pp.parseMaybeUnary (/Users/weakuser 1/Documents/crypto training/Lightning Network App programming/lightning-app-boilerplate/node_modules/acorn/dist/acorn.js:197:19)
    at Parser.pp.parseExprOps (/Users/weakuser 1/Documents/crypto training/Lightning Network App programming/lightning-app-boilerplate/node_modules/acorn/dist/acorn.js:151:19)
    at Parser.pp.parseMaybeConditional (/Users/weakuser 1/Documents/crypto training/Lightning Network App programming/lightning-app-boilerplate/node_modules/acorn/dist/acorn.js:133:19)
    at Parser.pp.parseMaybeAssign (/Users/weakuser 1/Documents/crypto training/Lightning Network App programming/lightning-app-boilerplate/node_modules/acorn/dist/acorn.js:110:19)
    at Parser.pp.parseExprList (/Users/weakuser 1/Documents/crypto training/Lightning Network App programming/lightning-app-boilerplate/node_modules/acorn/dist/acorn.js:651:185)
    at Parser.pp.parseSubscripts (/Users/weakuser 1/Documents/crypto training/Lightning Network App programming/lightning-app-boilerplate/node_modules/acorn/dist/acorn.js:240:29)
    at Parser.pp.parseExprSubscripts (/Users/weakuser 1/Documents/crypto training/Lightning Network App programming/lightning-app-boilerplate/node_modules/acorn/dist/acorn.js:219:15)
    at Parser.pp.parseMaybeUnary (/Users/weakuser 1/Documents/crypto training/Lightning Network App programming/lightning-app-boilerplate/node_modules/acorn/dist/acorn.js:197:19)

i’m just going to move on to the next challenge because my code looks similar enough to filip’s, but if anyone has any input on this, i’m all ears…

edit: this from the terminal just for completeness:

POST /invoice 500 809.413 ms - 4174
GET /stylesheets/style.css 304 4.674 ms - -

style.css has no line 59, just fyi
setting invoice.jade to what it was before this challenge allowed me to get to the invoice page, so it must’ve been there, but of course there’s no extra invoice info there as i’d expected…

Seems like you have a typo in invoice.jade file. Beware that jade templates are whitespace sensitive. It helps to enable this in your text editor if it supports it so you’re able to see if you’re using spaces or tabs for example.

1 Like

yeah, i’m pretty sure i had an extra tab in there somewhere … thank you!

at any rate, i’m still unable to see the details (e.g. phone, email, address, etc) on the invoice.jade page; should i not be changing that file? i.e. is it only after the invoice is paid that i should expect to see these things?
what i had that gives no errors (but doesn’t serve the additional details from the second challenge):

script(src="https://lightning.filipmartinsson.com/modal/btcpay.js") <!--//library filip wrote that will allow us to display a popup with the invoice-->
script(type="text/javascript").   <!--jade syntax right here-->
  window.onload = function () {
    var id = "#{invoiceID}";  //now 'invoiceID' (from "invoice.js": 48?) is 'id' in this front-end javascript script, which...
                              //... is TO BE SENT TO THE BACKEND when window closes and used by 'router.get' in the OTHER part of "invoice.js" !!!
    window.btcpay.showInvoice(id);
    window.btcpay.onModalWillLeave(function(){  // callback function to check if invoice is paid before serving user the next page/step, ...
      window.location.href= "invoice/" + id;    // i.e. this will redirect the user to localhost:3000/invoice/(id), ...
                                                //...which makes a get request to that URL, WHICH WE HANDLE AS 'router.get' in "invoice.js"
    });
  }

what i expected to have that would serve the extra details:

script(src="https://lightning.filipmartinsson.com/modal/btcpay.js") <!--//library filip wrote that will allow us to display a popup with the invoice-->
script(type="text/javascript").   <!--jade syntax right here-->
  window.onload = function () {
    var id = "#{invoiceID}";  //now 'invoiceID' (from "invoice.js": 48?) is 'id' in this front-end javascript script, which...
                              //... is TO BE SENT TO THE BACKEND when window closes and used by 'router.get' in the OTHER part of "invoice.js" !!!
    window.btcpay.showInvoice(id);
    /*
    var name = "#{name}";
    window.btcpay.showInvoice(name);
    var addy = "#{addy1}";
    window.btcpay.showInvoice(addy);
    var contact = "#{email}";
    window.btcpay.showInvoice(contact);
    var phone = "#{phone}";
    window.btcpay.showInvoice(phone);
    window.btcpay.onModalWillLeave(function(){  // callback function to check if invoice is paid before serving user the next page/step, ...
      window.location.href= "invoice/" + id;    // i.e. this will redirect the user to localhost:3000/invoice/(id), ...
                                                //...which makes a get request to that URL, WHICH WE HANDLE AS 'router.get' in "invoice.js"
    });
  }

am i on the right track, or is totally wasting my time?

If you want to add details to your invoice you have to set them when you are creating the invoice (client.create_invoice({price: product.price, currency: 'USD', ...})).
You can check the Btcpay docs to find out all the parameters you can add to your invoice.

this
https://www.hostinger.com/tutorials/website/how-to-link-a-stylesheet-css-file-to-your-html-file
and the “golden rules” here
https://www.tutorialspoint.com/software_engineering/software_user_interface_design.htm
were really helpful in giving me a broader based understanding of what UI/UX is supposed to be (also schneiderman/plaisant citation “designing the user interface” may help for a deeper dive)

that’s what i did. i just was wondering if they should show up on the “pay invoice” page or only after the invoice has been paid… i mean i saw no reason we couldn’t put it on the pay invoice page, i just didn’t see it when i tried adapting invoice.jade to it (i guess because there’s no way to render window.btcpay.showInvoice(input) with anything other than the invoiceID as input)

The server contains all the data you have set up. Reading the invoice with the ID will return all the data of the invoice you have setup in the first step. :slight_smile:

1 Like

Hello, :grinning:

Does anyone know where to find documentation about the Jade framework?

This URL currently returns a 404 error
http://jade-lang.com/

By the way, any thoughts about Jade itself, is it a framework worth learning?
Best,
Matt

1 Like

Apparently they have change their website to https://www.jadeworld.com/ and their SDK is not available to public, they now ask us to request access to a developer key in order to download and play around with their sdk, now the process is a little bit complex.

Also, I don’t think it’s a framework worth of learning by this times, there are new tools better than jade for LN development, check here: https://dev.lightning.community/lapps/

You can also check this project if your wondering on which other type of projects can be build on LND.
https://docs.lightning.engineering/lapps/guides/polar-lapps

The template application that they offer has App, is made with React and typescript, those 2 are being use heavily right now to build web3 apps.
https://github.com/lightninglabs/builders-guide-sample-app

So I suggest that: instead of jade, learn react + typescript, will serve you much more for other web3 projects than jade, including Lightning Network Development (build Lapps).

Carlos Z

3 Likes

Outstanding, thank you Carlos :+1:, this is very useful info!
Matt

1 Like

Hello,

I still cannot pay the invoice because I couldn’t create a channel to Filip’s node :sob: (error “You gave bad parameters: our dust limit xxx would be above their reserve xxx”)

However I’ve added the customer information to the result pages (github link here), both ‘paid’ (untested) and ‘not paid’ (tested) :

invoice.js
var express = require('express');
var router = express.Router();

const BTCPAY_PRIV_KEY = process.env.BTCPAY_PRIV_KEY;
const BTCPAY_MERCHANT_KEY = process.env.BTCPAY_MERCHANT_KEY;


// Initialize the client
const btcpay = require('btcpay')
const keypair = btcpay.crypto.load_keypair(new Buffer.from(BTCPAY_PRIV_KEY, 'hex'));
const client = new btcpay.BTCPayClient('https://lightning.filipmartinsson.com', keypair, {merchant: BTCPAY_MERCHANT_KEY})


/* get & verify invoice. */
router.get('/:id', async function(req, res, next) {
    var invoiceId = req.params.id;
    client.get_invoice(invoiceId)
        .then(invoice => {
            console.log(invoice)

            if ((invoice.status == "complete" ) || (invoice.status == "paid)")){
                res.end("<html><p>The invoice to " + invoice.buyer.name + " was paid</p><p>email: " + invoice.buyer.email + "</p><p>address: "+invoice.buyer.address1 +"</p></html>");
            }
            else
                res.end("<html><p>The invoice to " + invoice.buyer.name + " was not paid</p><p>email: " + invoice.buyer.email + "</p><p>address: "+invoice.buyer.address1 +"</p></html>");

        }).catch(error =>{console.log(error);})

});

/* Create invoice. */
router.post('/', function(req, res, next) {
    var dollarAmount = req.body.product;
    var buyerEmail = req.body.email;
    var buyerName = req.body.custname;
    var buyerAddress = req.body.address;

    client.create_invoice({price: dollarAmount, currency: "USD", buyer: {email: buyerEmail, name: buyerName, address1: buyerAddress}})
    .then(invoice => {
        res.render("invoice", {invoiceId: invoice.id});
    })
    .catch(err => {console.log(err)});
});


module.exports = router;

Hi All :smiley:

I’ve created two more jade views to handle the invoice results:

notpaid.jade
h2 Hi, the payment did not go through
p Dear 
    =buyer.name  

p The invoice for an amount of 
p=currency 
    =price 
p did not go through and you were not charged.

h2 Customer details
p Address: 
    =buyer.address1 
p Email: 
    =buyer.email


paid.jade
h1 Thanks for paying

h2 Invoice
p Amount:  
    =currency 
    =price 
p Fully paid.

h2 Customer details
p Name: 
    =buyer.name 
p Address: 
    =buyer.address1 
p Email: 
    =buyer.email


and this is the new code for invoice.js:

var express = require('express');
var router = express.Router();

const BTCPAY_PRIV_KEY = process.env.BTCPAY_PRIV_KEY;
const BTCPAY_MERCHANT_KEY = process.env.BTCPAY_MERCHANT_KEY;


// Initialize the client
const btcpay = require('btcpay')
const keypair = btcpay.crypto.load_keypair(new Buffer.from(BTCPAY_PRIV_KEY, 'hex'));
const client = new btcpay.BTCPayClient('https://lightning.filipmartinsson.com', keypair, {merchant: BTCPAY_MERCHANT_KEY})


/* get & verify invoice. */
router.get('/:id', async function(req, res, next) {
    var invoiceId = req.params.id;
    client.get_invoice(invoiceId)
        .then(invoice => {
            console.log(invoice)

            if ((invoice.status == "complete" ) || (invoice.status == "paid)")){
                res.render("paid", {price: invoice.price, currency: invoice.currency, buyer: invoice.buyer})
            }
            else
                res.render("notpaid", {price: invoice.price, currency: invoice.currency, buyer: invoice.buyer});


        }).catch(error =>{console.log(error);})

});

/* Create invoice. */
router.post('/', function(req, res, next) {
    var dollarAmount = req.body.product;
    var buyerEmail = req.body.email;
    var buyerName = req.body.custname;
    var buyerAddress = req.body.address;

    client.create_invoice({
    price: dollarAmount, currency: "USD", 
    buyer: 
        {
        email: buyerEmail, 
        name: buyerName, 
        address1: buyerAddress}})
    .then(invoice => {
        res.render("invoice", {invoiceId: invoice.id});
    })
    .catch(err => {console.log(err)});
});


module.exports = router;


Thanks, I’ll be checking those