Learning

Introduction

This is one of those frustrations post where I just spent hours working on something and I finally managed to have a working solution. I learned quite a bit but I feel like it should not have taken me that much time…

Anyway, the goal was to generate a PDF from HTML, then send it back to the browser so the user could download it. I tried a lot of different things, and it’s more than likely my solution is not the most elegant, or fast, but fuck it, it works.

I consider this post to be a place where I can store this solution, juste in case I forget it in the future. I’ll know where to look. Let’s jump into the actual solution.

The solution!

Front-end

Let’s start with the front-end.

const downloadPDF = () => {
        fetch('/api/invoices/create-pdf', {
            data: {
                invoiceDetails,
                invoiceSettings,
                itemsDetails,
                organisationInfos,
                otherDetails,
                clientDetails
            },
            method: 'POST'
        }).then(res => {
            return res
                .arrayBuffer()
                .then(res => {
                    const blob = new Blob([res], { type: 'application/pdf' })
                    saveAs(blob, 'invoice.pdf')
                })
                .catch(e => alert(e))
        })
    }

This is the function that does everything. We are generating an invoice in my case.

1) A fetch with the POST method. This is the part where we generate our PDF with the proper data and generate our PDF on the server. (server code will follow)

3) The response we get needs to be converted into an arraybuffer.

4) We create a Blob ( Binary Large Objects ) with the new Blob() constructor. The Blob takes a iterable as the first argument. Notice how our response turned arraybuffer is surrounded by square braquets( [res] ). To create a blob that can be read as a PDF, the data needs to be an iterable into a binary form ( I think…). Also, notice the type application/pdf.

5) Finally, I’m using the saveAs function from the file-saver package to create the file on the front end!

Back-end

Here is the back-end things. There is a whole express application and everything. I juste show you the controller where the two methods reside for this PDF problem.

module.exports = {
    createPDF: async function(req, res, next) {
        const content = fs.readFileSync(
            path.resolve(__dirname, '../invoices/templates/basic-template.html'),
            'utf-8'
        )
        const browser = await puppeteer.launch({ headless: true })
        const page = await browser.newPage()
        await page.setContent(content)
        const buffer = await page.pdf({
            format: 'A4',
            printBackground: true,
            margin: {
                left: '0px',
                top: '0px',
                right: '0px',
                bottom: '0px'
            }
        })
        res.end(buffer)
    }
}

1) I am using puppeteer to create a PDF from the HTML content. The HTML content is read from an HTML file I simply fetch with readFileSync

2) We store the buffer data returned by page.pdf() and we return it to the front-end. This is the response converted to an arraybuffer later.

Done

Well, looking at the code, it really looks easier now that it actually did when I tried to solve this problem. It took me close to 10 hours to find a proper answer. 10 FREAKING HOURS!!!!

Note to self: if you get frustrated, walk away from the computer, get some fresh air, and come back later…

Happy Coding <3

Read more

Introduction

I have this book, called Beginning Ruby, written by Peter Cooper. It’s one of the first book I’ve bought about programming. I’ve read… 20 pages probably… For some reason, I barely started it. The book is getting old, in programming terms, but I feel like learning a little bit of Ruby, and I feel like it will get the job done to teach me the basics. I never used Ruby before, so I’m starting from scratch here.

Continue reading Learning Ruby: Playing with irb

Read more

Introduction

Solidity is a high-level language used to implement smart contracts. This is an object oriented language designed to target the Ethereum Virtual Machine. Let’s explore it!

Let’s go!!!

Let’s create a file called Contract.sol
First, you must define the version you are using. This is an information the compiler needs.

pragma solidity ^0.4.22;

All code in Ethereum belongs to a Contract. Let’s create a contract and define a few variables inside it.

pragma solidity ^0.4.22;

contract DeveloperFactory {
    // Let's create a Developer!
    uint dnaDigits = 16;
    uint ageDigits = 2;
}

Solidity is a typed language. uint stand for Unsigned Integer ( non negative integers ). These variables are state variables. They will be permanently stored in the contract storage ( in the Ethereum Blockchain ). Our Developer has a dna of 16 digits and an age of 2 digits.

Let’s keep going!

Struct and arrays

pragma solidity ^0.4.22;

contract DeveloperFactory {
    // Let's create a Developer!
    uint dnaDigits = 16;
    uint ageDigits = 2;

    struct Developer {
        string name;
        uint dna;
        uint age;
    }

    Developer[] public developers;
}

The struct variable allows us to define more complex data structures. Here the Developer struc takes a string called name, a uint called dna and a uint called age.

Solidity also has arrays. You can create dynamic or fixed arrays. Here, our Developer array is dynamic because we do not specify a length. So we can keep adding Developers to our army without any limitations.

Developer[5] public developers is a fixed array that can contain 5 Developer struct.

Functions

A function would look something like this:

pragma solidity ^0.4.22;

contract DeveloperFactory {
    // Let's create a Developer!
    uint maxAge = 100;
    uint minAge = 5;

    struct Developer {
        string name;
        uint id;
        uint age;
    }

    Developer[] public developers;

    function _createDeveloper( string _name, uint _id, uint _age ) private{
        developers.push( Developer( _name, _id, _age ) );
    }

    function _generateRandomId( string _str ) private pure returns (uint){
        uint rand = uint(keccak256(_str));
        return rand;
    }

    function createRandomDeveloper( string _name, uint _age ) public view {
        require(_age > minAge);
        require(_age < maxAge);
        uint randId = _generateRandomId( _name );
        _createDeveloper(_name, randId, _age );
    }
}

We create functions with the function keyword. Functions can take parameters. By default, functions are public. I added the private keyword to make this function private. I also chose to add an underscore before a private function or variable to distinguish them from public variables. You don’t have to do this, I just find it easier to read.

Ethereum has the hash function keccak256 built in. This is a version of SHA3. Pass it any string and you get a 256-bit hexadecimal number.

As you can see, we are typecasting the keccak256 value into a uint value and we return it.

Aside from the private keyword, there are several things you can add to a function:

  • The function returns something: Use the returns keyword and specify the type the function returns. Here, it will return a uint type.

  • The view keyword means that our function needs to look at some of our contract’s variables, but not modify them. Our function createRandomDeveloper needs to look at minAge and maxAge variables.

  • The pure keyword means that the function is not accessing any data in the app. It only returns something depending on its parameters. Our _generateRandomId is pure.

We have three functions. _generateRandomId generates a random Id for our developer by using the keccak256 built in function. _createDeveloper creates and pushes a new Developer struct into our developers array. createRandomDeveloper is the only public function. It checks if the age provided is correct. The require statements will throw errors if it is not the case ( age greater than 100 and lower than 5 in our case ). So, this last function is the one that can be called from outside our contract.

Events

You can also create events so you can communicate what happens on the blockchain to your front-end app. Your app would then listen to those events and react accordingly.

pragma solidity ^0.4.22;

contract DeveloperFactory {
    // Let's create a Developer!

    event NewDeveloper(uint devId, string name, uint age);

    uint maxAge = 100;
    uint minAge = 5;

    struct Developer {
        string name;
        uint id;
        uint age;
    }

    Developer[] public developers;

    function _createDeveloper( string _name, uint _id, uint _age ) private{
        uint id = developers.push( Developer( _name, _id, _age ) ) - 1;
        newDeveloper(id, _name, _age);
    }

    function _generateRandomId( string _str ) private pure returns (uint){
        uint rand = uint(keccak256(_str));
        return rand;
    }

    function createRandomDeveloper( string _name, uint _age ) public view {
        require(_age > minAge);
        require(_age < maxAge);
        uint randId = _generateRandomId( _name );
        _createDeveloper(_name, randId, _age );
    }
}

We create an event with the event keyword. In our contract, the event will have three parameters, the devId, the name and the age. We will fire our event in our _createDeveloper function. It works like a function. The id is retrieved thanks to the push method on the developers array. It will return the new length of the array. Because the array start at index 0, we subtract 1 to get the developer id.

Note: This series is inspired by the CryptoZombies tutorial. Don’t hesitate to check it out, it’s amazing!

Note bis: You can use the Remix IDE in your browser if you want to play around in Solidity

Conclusion

We have explored some concepts of Solidity. In the next article, we will go in more depth into what Solidity allows you to do. Stay tuned!

Read more

Introduction

In my previous article, I tried to described the concept of a blockchain with code. This time, I’ll try to describe the structure of a single block. I will use the Bitcoin blockchain to explain blocks, but keep in mind that the concepts will remain more or less the same. It could be useful to read my last article to understand a few things first.
Continue reading Blockchain: what is inside a block?

Read more