• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar

I Like Kill Nerds

The blog of Australian Front End / Aurelia Javascript Developer & brewing aficionado Dwayne Charrington // Aurelia.io Core Team member.

  • Home
  • Aurelia 2
  • Aurelia 1
  • About
  • Aurelia 2 Consulting/Freelance Work

How to Create a Blockchain With TypeScript

Cryptocurrency, Javascript · January 22, 2023

If you have been a reader of my blog for a while, you would know that I am an avid cryptocurrency enthusiast. I believe in the tech more so than the financial side. I find blockchains fascinating because, despite their perceived complexity, you can implement a blockchain in any programming language; Javascript included.

I thought it would be fun to create a blockchain using TypeScript and then iteratively change the code to offer more flexibility, such as the ability to add metadata into the blocks and query the blocks themselves.

Disclaimer: This is all proof of concept and if you’re planning on using this for actual financial purposes, I would consider making the code better. This is just a bit of fun.

Please also note that the crypto-js package is being used here to handle the sha256 hashes.

import * as CryptoJS from "crypto-js";

class Block {
  public index: number;
  public timestamp: number;
  public data: string;
  public jsonData: any;
  public previousHash: string;
  public hash: string;

  constructor(index: number, data: string, jsonData: any, previousHash: string) {
    this.index = index;
    this.timestamp = Date.now();
    this.data = data;
    this.jsonData = jsonData;
    this.previousHash = previousHash;
    this.hash = this.calculateHash();
  }

  public calculateHash(): string {
    // Use SHA256 to generate a hash for the current block
    return CryptoJS.SHA256(this.index + this.timestamp + this.data + JSON.stringify(this.jsonData) + this.previousHash).toString();
  }
}

class Blockchain {
  public chain: Block[];

  constructor() {
    this.chain = [this.createGenesisBlock()];
  }

  public createGenesisBlock(): Block {
    // The first block in the blockchain is called the Genesis Block
    return new Block(0, "Genesis Block", "0");
  }

  public getLatestBlock(): Block {
    // Returns the last block in the chain
    return this.chain[this.chain.length - 1];
  }

  public addBlock(newBlock: Block): void {
    // Assign the hash of the previous block to the new block's previousHash property
    newBlock.previousHash = this.getLatestBlock().hash;
    // Calculate the new block's hash
    newBlock.hash = newBlock.calculateHash();
    // Add the new block to the chain
    this.chain.push(newBlock);
  }

  public isChainValid(): boolean {
    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 still valid
      if (currentBlock.hash !== currentBlock.calculateHash()) {
        return false;
      }

      // Check if the previousHash of the current block is still valid
      if (currentBlock.previousHash !== previousBlock.hash) {
        return false;
      }
    }

    // If all checks pass, the chain is valid
    return true;
  }
}

We have a simplistic blockchain where the chain and blocks are separate, using classes to clean things up.

And to use our newfound blockchain, here is how we would implement it:

// Import crypto-js library
import * as CryptoJS from "crypto-js";

// Create a new blockchain
const myBlockchain = new Blockchain();

// Add some blocks to the blockchain
myBlockchain.addBlock(new Block(1, "This is block 1", {name: "John", age: 30}, myBlockchain.getLatestBlock().hash));
myBlockchain.addBlock(new Block(2, "This is block 2", {name: "Jane", age: 25}, myBlockchain.getLatestBlock().hash));
myBlockchain.addBlock(new Block(3, "This is block 3", {name: "Bob", age: 35}, myBlockchain.getLatestBlock().hash));

// Check if the blockchain is valid
console.log(myBlockchain.isChainValid()); // Output: true

We have a functional blockchain now, but let’s make one more change to make it useful—the ability to get blocks by ID or metadata properties in the block. Inside the Blockchain class we create a method called getBlock which can query for blocks in our chain.

import * as CryptoJS from "crypto-js";

class Block {
    public index: number;
    public timestamp: number;
    public data: string;
    public jsonData: any;
    public previousHash: string;
    public hash: string;

    constructor(index: number, data: string, jsonData: any, previousHash: string) {
        this.index = index;
        this.timestamp = Date.now();
        this.data = data;
        this.jsonData = jsonData;
        this.previousHash = previousHash;
        this.hash = this.calculateHash();
    }

    public calculateHash(): string {
        // Use SHA256 to generate a hash for the current block
        return CryptoJS.SHA256(this.index + this.timestamp + this.data + JSON.stringify(this.jsonData) + this.previousHash).toString();
    }
}

class Blockchain {
    public chain: Block[];

    constructor() {
        this.chain = [this.createGenesisBlock()];
    }

    public createGenesisBlock(): Block {
        // The first block in the blockchain is called the Genesis Block
        return new Block(0, "Genesis Block", "0");
    }

    public getLatestBlock(): Block {
        // Returns the last block in the chain
        return this.chain[this.chain.length - 1];
    }

    public addBlock(newBlock: Block): void {
        // Assign the hash of the previous block to the new block's previousHash property
        newBlock.previousHash = this.getLatestBlock().hash;
        // Calculate the new block's hash
        newBlock.hash = newBlock.calculateHash();
        // Add the new block to the chain
        this.chain.push(newBlock);
    }

    public getBlock(searchTerm: string | number, by: 'id' | 'metadata' = 'id'): Block | undefined {
      if (by === 'id') {
        const block = this.chain.find((b) => b.index === searchTerm);
        return block;
      } else if (by === 'metadata') {
        // define a function to check if the jsonData of a block contains the searchTerm
        const checkMetadata = (jsonData: any) => {
          for (let key in jsonData) {
            if (jsonData[key] === searchTerm) {
              return true;
            }
          }
          return false;
        }
        
        // check if jsonData property exists before searching by metadata values
        const block = this.chain.find((b) => b.jsonData && checkMetadata(b.jsonData));
        
        return block;
      }
    }

    public isChainValid(): boolean {
        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 still valid
            if (currentBlock.hash !== currentBlock.calculateHash()) {
                return false;
            }

            // Check if the previousHash of the current block is still valid
            if (currentBlock.previousHash !== previousBlock.hash) {
                return false;
            }
        }

        // If all checks pass, the chain is valid
        return true;
    }
}

This method takes two parameters searchTerm and by, where searchTerm is the value you want to search for and by is either ‘id’ or ‘metadata’ to define what you want to search by. By default, it is set to ‘id’, so if you call the method without passing any second parameter, it will search by id.

If by is ‘id’, it uses the Array.prototype.find method to search the chain array for a block with a matching index property. If it finds a match, it returns the block. Otherwise, it returns undefined.

If by is ‘metadata’, it uses the Array.prototype.find method to search the chain array for a block with metadata that matches the searchTerm . It uses a helper function checkMetadata that iterates over the jsonData of the block and checks if any of the values match the searchTerm. If it finds a match, it returns the block. Otherwise, it returns undefined.

You can then use this method to search for blocks by ID or metadata values like this:

console.log(myBlockchain.getBlock(1)); 
console.log(myBlockchain.getBlock("John", 'metadata'));

Conclusion

As you can see, a blockchain is just a collection of objects with hashes. While this is a rather simplistic implementation of a blockchain, it shows that it’s not as complicated as you would think.

Dwayne

Leave a Reply Cancel reply

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Kevmeister68
Kevmeister68
1 month ago

Call me a pessimist but of itself what does this actually give you? The idea of the hashes is to somehow prevent non-tampering, but what’s to stop an entire blockchain being modified and hashes recomputed?

Point is, the underlying data itself still needs to be protected from modification.

0
Dwayne
Dwayne
Author
Reply to  Kevmeister68
1 month ago

This just shows how the concept of a blockchain works, but it doesn’t handle immutable storage or anything else you’d associate with a blockchain. I just thought it would be cool to show what a blockchain looks like in a Web based language.

0

Primary Sidebar

Popular

  • I Joined Truth Social Using a VPN and Editing Some HTML to Bypass the Phone Verification
  • Testing Event Listeners In Jest (Without Using A Library)
  • How To Get The Hash of A File In Node.js
  • Thoughts on the Flipper Zero
  • Waiting for an Element to Exist With JavaScript
  • How To Paginate An Array In Javascript
  • How To Mock uuid In Jest
  • How To Decompile And Compile Android APK's On A Mac Using Apktool
  • How To Get Last 4 Digits of A Credit Card Number in Javascript
  • Wild Natural Deodorant Review

Recent Comments

  • CJ on Microsoft Modern Wireless Headset Review
  • Dwayne on Microsoft Modern Wireless Headset Review
  • CJ on Microsoft Modern Wireless Headset Review
  • john on Microsoft Modern Wireless Headset Review
  • Dwayne on Why You Should Be Using globalThis Instead of Window In Your Javascript Code

Copyright © 2023 · Dwayne Charrington · Log in

wpDiscuz