Building a Blockchain Application with JavaScript

4 months ago 2
ARTICLE AD BOX
Building a Blockchain Application with JavaScript

The post Building a Blockchain Application with JavaScript appeared first on Coinpedia Fintech News

Introduction

Blockchain technology has an impact on many of today’s game-changing innovations, from cryptocurrencies like Bitcoin to decentralized apps (DApps) in different fields. A blockchain is a shared ledger that keeps track of transactions across many computers so that the record can’t be changed after the fact. Each entry, or “block,” is connected to the one before it making a chain of blocks, which is why it’s called a “blockchain.” This setup makes sure data is open, secure, and can’t be altered, which is key for lots of uses

JavaScript in Blockchain

Javascript is a multifaceted and celebrated language especially suited for blockchain development. With its extensive ecosystem and strong community support, JavaScript simplifies blockchain development in several ways:

  • Wide Adoption: Since Javascript is the core language used for web development its very obvious to have application in the blockchain landscape with web applications.
  • Asynchronous Processing: JavaScript’s asynchronous capabilities, facilitated by Node.js, are ideal for handling multiple transactions and interactions in a blockchain environment.
  • Rich Ecosystem: Tools and libraries in the JavaScript ecosystem, such as Node.js for server-side development and Express.js for APIs, streamline blockchain application development.

Audience

This article is designed for developers who are familiar with JavaScript and wish to delve into blockchain technology. It will guide you through setting up your development environment, understanding blockchain fundamentals, building a basic blockchain application, and exposing it via a simple API.

Chapter 1: Setting Up the Development Environment

Installing Node.js

  • Download node js on your system from the official website and prefer the LTS (Long Term Support) version as it is recommended the best for all the operating systems and maintain stability.
  •  Follow the installation instructions specific to your OS. The installation includes npm (Node Package Manager), which is essential for managing project dependencies.
  • Verify the installation is done properly or not by running the following commands in the bash:
    1. node -v
    2. npm -v

    After you run the commands you should get the respective versions of the packages you installed if the setup is successful.

    Choosing an IDE

    When you opt for JavaScript as your programming language the best partner to cater all the development needs is VsCode its robust features and versatile environment is best suitable.

    • Visual Studio Code:
      1. Download VsCode from the official site
      2. Install the extensions as follows:
        1. ESLint: For identifying and fixing problems in JavaScript code.
        2. Prettier: For consistent code formatting.
        3. Debugger for Chrome: For debugging JavaScript code running in Google Chrome.
        4. Node.js: For Node.js debugging capabilities.

    Installing Required Libraries

    JavaScript libraries are managed via npm. Initialize your project and install the required libraries with:

    npm init -y
    npm install express body-parser crypto

    //express is the  node framework 
    //body-parser is the middle ware to parse the incoming requests
    //crypto function used for hashing

    Chapter 2: Understanding Blockchain Concepts with JavaScript

    Blockchain Basics in JavaScript

    A blockchain comprises of blocks, which contain:

    • Index: Position of the block in the chain.
    • Timestamp: Date and time when the block was created.
    • Data: Transaction data or other information stored in the block.
    • Previous Hash: Hash of the previous block in the chain, linking blocks together.
    • Hash: Unique identifier for the block, generated by hashing its content.
    const crypto = require(‘crypto’);

    class Block {    
    constructor(index, timestamp, data, previousHash = ”) {        
    this.index = index;        
    this.timestamp = timestamp;        
    this.data = data;        
    this.previousHash = previousHash;        
    this.hash = this.calculateHash();    
    }
        calculateHash() {        
    return crypto.createHash(‘sha256’)            
    .update(this.index + this.previousHash + this.timestamp + JSON.stringify(this.data))           
     .digest(‘hex’);    
    }
    }

    Importance of decentralization, immutability, and consensus mechanisms:

    Decentralization

    There is no central authority that holds all the necessary data or transaction validation rather it is all distributed across the network. As we know in blockchain, every node maintains a copy of the ledger which ensures there isn’t any discrepancy due to a single point of control. 

    Transparency:

    All the nodes and participants can view the ledger ensuring transparency throughout the network. In Ethrerneum the transactions are visible on the blockchain explorer.

    Immutability:

    One needs to be very careful before executing any transaction because once it’s done it can’t be further altered. This property is quite helpful in preventing fraud and double-spending.

    Consensus Mechanism:

    Consensus mechanisms are a set of protocols that the nodes should follow in the network to agree on the state of the ledger. These mechanisms are used for the validation and authentication of transactions. These mechanisms ensure all nodes in the DLT agree on the state of the ledger. 

    Components of a Blockchain Application

    Block structure in JavaScript:

    const crypto = require(‘crypto’);

    class Block {    
    constructor(index, timestamp, data, previousHash = ”) {        
    this.index = index;        
    this.timestamp = timestamp;        
    this.data = data;        
    this.previousHash = previousHash;        
    this.hash = this.calculateHash();        
    this.nonce = 0; // For Proof of Work    
    }
        
    calculateHash() {        
    return crypto.createHash(‘sha256’)            
    .update(this.index + this.previousHash + this.timestamp + JSON.stringify(this.data) + this.nonce)            
    .digest(‘hex’);    }
        
    mineBlock(difficulty) {        
    while (this.hash.substring(0, difficulty) !== Array(difficulty + 1).join(“0”)) {            
    this.nonce++;            
    this.hash = this.calculateHash();        
    }        
    console.log(“Block mined: ” + this.hash);    
    }
    }

    Creating and verifying transactions using JavaScript:

    Transactions form the basic building blocks of data in a blockchain. They show a shift in value, carry out a contract, or make other changes to the blockchain’s condition. The system groups these transactions into blocks and puts them on the blockchain.

    Details of the Transaction:

    • Sender: The public key or specific identification of who’s sending it over.
    • Receiver: The public key or specific identification of the lucky one who’s getting the transaction.
    • Amount: What’s getting passed around, be it money or some info.
    • Time Stamp: When they decided to hit send on this thing.
    • Authenticity Proof/Signature: Some super-secret code stuff that shows the deal’s legit and has not been tampered with. The one who sends it uses their secret key to seal the deal, and everyone else can check it’s for real with the public key.

    Code snippet for the transaction:

    class Transaction {    
    constructor(fromAddress, toAddress, amount) {        
    this.fromAddress = fromAddress;        
    this.toAddress = toAddress;        
    this.amount = amount;        
    this.timestamp = new Date().toISOString();    
    }
        calculateHash() {        
    return crypto.createHash(‘sha256’)            
    .update(this.fromAddress + this.toAddress + this.amount + this.timestamp)            
    .digest(‘hex’);    
    }
        
    signTransaction(signingKey) {        
    if (signingKey.getPublic(‘hex’) !== this.fromAddress) {            
    throw new Error(‘You cannot sign transactions for other wallets!’);        
    }
           
     const hashTx = this.calculateHash();        
    const sig = signingKey.sign(hashTx, ‘base64’);        
    this.signature = sig.toDER(‘hex’);    }
        isValid() {        
    if (this.fromAddress === null) return true;
            

    if (!this.signature || this.signature.length === 0) {            
    throw new Error(‘No signature in this transaction’);       
     }
            
    const publicKey = ec.keyFromPublic(this.fromAddress, ‘hex’);        
    return publicKey.verify(this.calculateHash(), this.signature);    
    }
    }

    Transaction verification confirms the legitimacy of a transaction by checking that the sender has properly signed it and that the sender has enough funds. This process usually involves validating the cryptographic signature and ensuring that the sender’s balance is equal to or greater than the transaction amount.

    class Blockchain {    
    constructor() {        
    this.chain = [this.createGenesisBlock()];        
    this.pendingTransactions = [];        
    this.miningReward = 100;    
    }
        
    createGenesisBlock() {        
    return new Block(Date.parse(‘2024-01-01’), [], ‘0’);    
    }
        getLatestBlock() {        
    return this.chain[this.chain.length – 1];    
    }
        
    minePendingTransactions(miningRewardAddress) {        
    let block = new Block(Date.now(), this.pendingTransactions, this.getLatestBlock().hash);        
    block.mineBlock(this.difficulty);
            
    console.log(‘Block successfully mined!’);        
    this.chain.push(block);
            this.pendingTransactions = [            
    new Transaction(null, miningRewardAddress, this.miningReward)        
    ];   
     }
        addTransaction(transaction) {        
    if (!transaction.fromAddress || !transaction.toAddress) {            
    throw new Error(‘Transaction must include from and to address’);        }
            
    if (!transaction.isValid()) {            
    throw new Error(‘Cannot add invalid transaction to chain’);        
    }
            this.pendingTransactions.push(transaction);    
    }
        
    getBalanceOfAddress(address) {        
    let balance = 0;
            
    for (const block of this.chain) {            
    for (const trans of block.data) {               
     if (trans.fromAddress === address) {                   
     balance -= trans.amount;               
     }
                    
    if (trans.toAddress === address) {                   
     balance += trans.amount;                
    }           
     }       
     }
            return balance;    
    }
        isChainValid() {        
    for (let i = 1; i < this.chain.length; i++) {            
    const currentBlock = this.chain[i];            
    const previousBlock = this.chain[i – 1];
                if (!currentBlock.hasValidTransactions()) {                
    return false;            
    }
                if (currentBlock.hash !== currentBlock.calculateHash()) {                
    return false;            
    }
                if (currentBlock.previousHash !== previousBlock.hash) {                
    return false;            
    }        
    }
            return true;    
    }
    }

    Overview of consensus algorithms compatible with JavaScript:

    Proof of Work (PoW):

    Technical Explanation: Proof of Work is also known as mining. In this consensus mechanism, the users have to solve cryptographic puzzles that reward them.It is a contest where the first one to solve gets to pass the new block. This algorithm uses hashing to secure the blockchain. 

    Developer Implementation: Tools for implementing PoW are provided by the Bitcoin Developer Environment like Bitcoin Core.

    Proof of Stake (PoS):

    Technical Explanation: Proof of Stake selects validators based on the number of coins they have and the stake as collateral. The selection process just doesn’t depend only upon the stake but also on factors such as the age of the coin and randomness. Validators having the lowest hash value and highest stake amount are chosen to add the new block

    Developer Implementation: Tools and libraries for PoS are provided by Ethereum 2.0 SDK

    Delegated Proof of Stake (DPoS):

    Technical Explanation:  Uses voting and delegates for validation of the transaction and creation of new blocks.

    Developer Implementation: EOSIO SDK provides tools and libraries for DPoS.

    Chapter 3: Building a Simple Blockchain with JavaScript

     In this you will learn about the blockchain structure, defining classes and block and block parameters, and how they are linked together.

    Creating the Block Class

      Blockchain as the name represents is comprised of blocks and each block class bas attributes like:

      • Index: A numerical identifier for the block’s position within the blockchain.
      • Timestamp: The time at which the block was created.
      • Data: The data or transactions stored in the block. This could include information like transaction details, user data, etc.
      • PreviousHash: The hash of the previous block in the chain, ensuring continuity and security.
      • Hash: A unique identifier for the block, generated by hashing the block’s contents.
      • Nonce: A number used for the Proof of Work algorithm, which is adjusted until a valid hash is found.

      Implement methods to calculate the hash of the block using JavaScript syntax:

      • createGenesisBlock(): Creates the first block in the blockchain, known as the genesis block.
      • getLatestBlock(): Retrieves the most recent block in the blockchain.
      • addBlock(): Adds a new block to the blockchain after mining it.
      • isChainValid(): Validates the integrity of the blockchain by ensuring each block’s hash matches and that the previous hashes are consistent.

      Creating the Blockchain Class

      Define a Blockchain class to manage the chain and implement methods to add new blocks:

      class Blockchain {    
      constructor() {        
      this.chain = [this.createGenesisBlock()];        
      this.difficulty = 4;  // Difficulty level for mining    
      }
          // Method to create the genesis block    
      createGenesisBlock() {        
      return new Block(0, “01/01/2024”, “Genesis Block”, “0”);    
      }
         
       // Method to retrieve the latest block in the chain    
      getLatestBlock() {        
      return this.chain[this.chain.length – 1];    
      }
          
      // Method to add a new block to the chain after mining it    
      addBlock(newBlock) {        
      newBlock.previousHash = this.getLatestBlock().hash;        
      newBlock.mineBlock(this.difficulty);        
      this.chain.push(newBlock);    
      }
         
       // Method to validate the integrity of the blockchain    
      isChainValid() {        
      for (let i = 1; i < this.chain.length; i++) {            
      const currentBlock = this.chain[i];            
      const previousBlock = this.chain[i – 1];
                  
      // Check if the current block’s hash is correct            
      if (currentBlock.hash !== currentBlock.calculateHash()) {                
      return false;           
       }
                  // Check if the current block’s previous hash matches the hash of the previous block            
      if (currentBlock.previousHash !== previousBlock.hash) {                
      return false;            
      }       
       }        
      return true;    
      }
      }

      Chapter 4: Implementing Consensus Mechanisms in JavaScript

      Proof of Work

        Proof of Work, often referred to as mining, is a decentralized system in which network members, or miners, compete to solve cryptographic puzzles. The first miner to solve the puzzle adds the next block to the blockchain and receives a reward. This process uses hashing to secure the blockchain. The difficulty of PoW puzzles ensures the blockchain remains secure and controls the speed at which new blocks are added.

        In the Block class, we can implement Proof of Work by adding a mineBlock method. This method adjusts the nonce until the block’s hash meets a specific difficulty target (e.g., the hash must start with a certain number of zeros).

        Code Snippet:

        class Block {    
        constructor(index, timestamp, data, previousHash = ”) {        
        this.index = index;        
        this.timestamp = timestamp;        
        this.data = data;        
        this.previousHash = previousHash;        
        this.hash = this.calculateHash();        
        this.nonce = 0;   
         }
           
         // Calculate the hash of the block using SHA-256    
        calculateHash() {        
        return crypto.createHash(‘sha256’)            
        .update(this.index + this.previousHash + this.timestamp + JSON.stringify(this.data) + this.nonce)            
        .digest(‘hex’);    
        }

            // Implementing Proof of Work    
        mineBlock(difficulty) {        
        while (this.hash.substring(0, difficulty) !== Array(difficulty +
        1).join(“0”)) {            
        this.nonce++;            
        this.hash = this.calculateHash();       
         }        
        console.log(`Block mined: ${this.hash}`);    
        }
        }

        Update the Blockchain class to validate proof before adding new blocks.

        class Blockchain {    
        constructor() {        
        this.chain = [this.createGenesisBlock()];        
        this.difficulty = 4;    
        }
           
         // Create the genesis block    createGenesisBlock() {        
        return new Block(0, “01/01/2024”, “Genesis Block”, “0”);    
        }
            
        // Get the latest block in the chain    
        getLatestBlock() {        
        return this.chain[this.chain.length – 1];    
        }
            
        // Add a new block to the chain    
        addBlock(newBlock) {        
        newBlock.previousHash = this.getLatestBlock().hash;        
        newBlock.mineBlock(this.difficulty);  // Implementing Proof of Work        
        this.chain.push(newBlock);    
        }
            
        // Check if the blockchain is valid    
        isChainValid() {        
        for (let i = 1; i < this.chain.length; i++) {            
        const currentBlock = this.chain[i];            
        const previousBlock = this.chain[i – 1];
                    if (currentBlock.hash !== currentBlock.calculateHash()) {                
        return false;           
         }
                    if (currentBlock.previousHash !== previousBlock.hash) {                
        return false;           
         }        
        }        
        return true;    
        }
        }

        Chapter 5: Creating a Simple Blockchain API with JavaScript

        Just creating a blockchain is not enough one needs to make it usable in real life. For this purpose, we need to create an interface for interaction which will be a simple API.

        Setting Up the API Environment

          Before you start with building the API setting up the environment with all the essential tools and frameworks is necessary.

          • Install node and npm 
          • Initialize your project with the command: npm init -y
          • Install Express: npm install express –save (Express is the node js framework that helps in building APIs faster)
          • Install Body parser to handle the incoming request: npm install body-parser –save

          Building the API

            Now that your environment is set up, let’s build the API. The API will allow users to interact with the blockchain, view the chain, and add new blocks.

            Create the server with Express:

            const express = require(‘express’);
            const bodyParser = require(‘body-parser’);
            const Blockchain = require(‘./blockchain’);  // Import the Blockchain class

            const app = express();
            app.use(bodyParser.json());

            let demoBlockchain = new Blockchain();  // Initialize a new Blockchain instance

            Define API endpoints

            app.get(‘/blocks’, (req, res) => {     //endpoint to get the blockchain    
            res.json(demoBlockchain.chain);});

            //this is the endpoint to create a newblock

            app.post(‘/mine’, (req, res) => {    
            const newBlock = new Block(        
            demoBlockchain.chain.length,        
            Date.now(),        
            req.body.data,        
            demoBlockchain.getLatestBlock().hash   
             );    
            demoBlockchain.addBlock(newBlock);
                res.send(`Block successfully mined: ${newBlock.hash}`);
            });

            Start the server

            app.listen(3000, () => {    
            console.log(‘Blockchain API running on port 3000’);
            });
            node server.js

            Chapter 6: Running and Testing the Application

            This phase is critical to ensure that your blockchain is functioning correctly and that all features work as expected.

            Running the Application

            1. Start the server: Navigate to your project directory and then run the target: node server.js
            2. Get Server Confirmation: Blockchain API running on port 3000
            3. Accessing the Application: Your application is now running locally on http://localhost:3000, making it ready to accept HTTP requests

            Testing with Postman

            Postman is a widely used tool for testing APIs, allowing you to send HTTP requests and view the responses. It’s particularly useful for verifying the functionality of your blockchain API.

            • Install Postman
            • Testing the Blockchain Endpoint
            • Test the Mining endpoint
            • Verify the blockchain
            (Step1)node server.js
            Blockchain API running on port 3000

            //http://localhost:3000/block

            (Step2)[    
            {        
            “index”: 0,        
            “timestamp”: 1636568887994,        
            “data”: “Genesis Block”,       
             “previousHash”: “0”,       
             “hash”:
            “81f1a4ab4d484c64f1b4c524b1d8f2fef8f2bca7853d44682e12022fb2d803b9”   
             }
            ]

            (Step3){    
            “data”: {        
            “amount”: 100,        
            “sender”: “John Doe”,        
            “receiver”: “Jane Smith”   
             }
            }

            (Step4){   
             “message”: “Block successfully mined”,    
            “block”: {        
            “index”: 1,        
            “timestamp”: 1636578990123,        
            “data”: {            
            “amount”: 100,            
            “sender”: “John Doe”,            
            “receiver”: “Jane Smith”        
            },        
            “previousHash”: “81f1a4ab4d484c64f1b4c524b1d8f2fef8f2bca7853d44682e12022fb2d803b9”,       
             “hash”:
            “5a1cdd657c8d0d3c0f12c2bb2c9fdf32a7d2d4ad13fcb78170a8caa82ff4a9a2”    
            }
            }

             (Step5)[
                {
                    “index”: 0,        
            “timestamp”: 1636568887994,       
             “data”: “Genesis Block”,       
             “previousHash”: “0”,        
            “hash”:

            “81f1a4ab4d484c64f1b4c524b1d8f2fef8f2bca7853d44682e12022fb2d803b9”

             

               },    
            {

             

                   “index”: 1,        
            “timestamp”: 1636578990123,       
             “data”: {            
            “amount”: 100,           
             “sender”: “John Doe”,           
             “receiver”: “Jane Smith”        
            },        
            “previousHash”: “81f1a4ab4d484c64f1b4c524b1d8f2fef8f2bca7853d44682e12022fb2d803b9”,       
             “hash”:
            “5a1cdd657c8d0d3c0f12c2bb2c9fdf32a7d2d4ad13fcb78170a8caa82ff4a9a2”   
             }
            ]
            curl http://localhost:3000/blocks //View the blockchain
            [   
             {       
             “index”: 0,        
            “timestamp”: 1636568887994,       
             “data”: “Genesis Block”,       
             “previousHash”: “0”,       
             “hash”:
            “81f1a4ab4d484c64f1b4c524b1d8f2fef8f2bca7853d44682e12022fb2d803b9”    
            }
            ]

            //Mining a new blockcurl -X POST -H “Content-Type: application/json” -d ‘{“data”: {“amount”: 100, “sender”: “John Doe”, “receiver”: “Jane Smith”}}’ http://localhost:3000/mine

            //verify the blockcurl http://localhost:3000/blocks

            [   
             {       
             “index”: 0,        
            “timestamp”: 1636568887994,       
             “data”: “Genesis Block”,       
             “previousHash”: “0”,       
             “hash”: “81f1a4ab4d484c64f1b4c524b1d8f2fef8f2bca7853d44682e12022fb2d803b9”    
            },    
            {       
             “index”: 1,       
             “timestamp”: 1636578990123,        
            “data”: {           
             “amount”: 100,            
            “sender”: “John Doe”,            
            “receiver”: “Jane Smith”       
             },        
            “previousHash”: “81f1a4ab4d484c64f1b4c524b1d8f2fef8f2bca7853d44682e12022fb2d803b9”,       
             “hash”:
            “5a1cdd657c8d0d3c0f12c2bb2c9fdf32a7d2d4ad13fcb78170a8caa82ff4a9a2”    
            }
            ]

            Chapter 7: Live Example of Building a Blockchain Application with JavaScript

            Step-by-Step Execution

            • Step 1: Create the Block class with necessary attributes using JavaScript syntax.
            class Block {    
            constructor(index, timestamp, data, previousHash = ”) {        
            this.index = index;        
            this.timestamp = timestamp;        
            this.data = data;        
            this.previousHash = previousHash;        
            this.hash = this.calculateHash();        
            this.nonce = 0;    
            }
            }
            • Step 2: Implement the calculateHash method.
            calculateHash() {   
             return crypto.createHash(‘sha256’)        
            .update(this.index + this.previousHash + this.timestamp + JSON.stringify(this.data) + this.nonce)       
             .digest(‘hex’);
            }
            • Step 3: Define the Blockchain class and initialize it with a genesis block.
            class Blockchain {    
            constructor() {        
            this.chain = [this.createGenesisBlock()];    
            }
            }
            • Step 4: Implement methods to add new blocks and retrieve the latest block using JavaScript.
            getLatestBlock() {    
            return this.chain[this.chain.length – 1];
            }

            addBlock(newBlock) {    
            newBlock.previousHash = this.getLatestBlock().hash;    
            newBlock.hash = newBlock.calculateHash();    
            this.chain.push(newBlock);}
            • Step 5: Add Proof of Work functionality to the Block class and update the Blockchain class.
            mineBlock(difficulty) {    
            while (this.hash.substring(0, difficulty) !== Array(difficulty + 1).join(“0”)) {        
            this.nonce++;        
            this.hash = this.calculateHash();    
            }
            }
            • Step 6: Set up the API environment to handle requests using Express.
            npm init -y
            npm install express –save                        //Setting up the project and
            the directory

            const express = require(‘express’);      //Setting up the express server
            const bodyParser = require(‘body-parser’);

            const Blockchain = require(‘./blockchain’); // Assuming you have the
            Blockchain class from previous chapters


            const app = express();
            app.use(bodyParser.json());


            const demoBlockchain = new Blockchain();

            app.get(‘/blocks’, (req, res) => {    
            res.json(demoBlockchain.chain);
            });      

            app.post(‘/mine’, (req, res) => {            //creating a new block        
                const newBlock = new Block(

            demoBlockchain.chain.length,
                    Date.now(),
                    req.body.data,
                    demoBlockchain.getLatestBlock().hash
            );
                newBlock.mineBlock(2); // Assuming a difficulty of 2 for PoW
                demoBlockchain.addBlock(newBlock);
                
            res.send(`Block successfully mined: ${newBlock.hash}`);
            });
            app.listen(3000, () => {                               //starting the server
                console.log(‘Blockchain API running on port 3000’);
            });


            node server.js
            • Step 7: Test the application by mining a new block and verifying the blockchain using Postman or curl.
            In postman send the request:
            GET request to http://localhost:3000/blocks.
            {    
            “data”: {       
             “amount”: 10,       
             “sender”: “Alice”,       
             “receiver”: “Bob”   
             }
            }

            In curl:curl
            http://localhost:3000/blocks

            Lets summarize the above steps in short

            Let’s go through the process step by step to bring your blockchain application to life:

            1. Begin by defining the Block and Blockchain classes to establish the core structure of your blockchain.
            2. Incorporate Proof of Work by adding the mineBlock method to the Block class, ensuring each block meets the required difficulty before being added to the chain.
            3. Set up an API using Express that allows you to interact with your blockchain, enabling operations like viewing the chain and adding new blocks.
            4. Execute and test your application with Postman or curl to verify that everything functions as expected, from mining blocks to retrieving the blockchain data.

            Happy Coding!!

            Read Entire Article