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:
node -v
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:
Download VsCode from the official site
Install the extensions as follows:
ESLint: For identifying and fixing problems in JavaScript code.
Prettier: For consistent code formatting.
Debugger for Chrome: For debugging JavaScript code running in Google Chrome.
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 -ynpm 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 classconst 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 newblockapp.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
Start the server: Navigate to your project directory and then run the target: node server.js
Get Server Confirmation: Blockchain API running on port 3000
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.jsBlockchain 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 -ynpm install express –save //Setting up the project andthe directoryconst express = require(‘express’); //Setting up the express serverconst bodyParser = require(‘body-parser’);const Blockchain = require(‘./blockchain’); // Assuming you have the Blockchain class from previous chaptersconst 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:
Begin by defining the Block and Blockchain classes to establish the core structure of your blockchain.
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.
Set up an API using Express that allows you to interact with your blockchain, enabling operations like viewing the chain and adding new blocks.
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!!