Atharva Deosthale Web Developer and Designer | JavaScript = ❤ | MERN Stack Developer

How to create your own cryptocurrency with JavaScript

6 min read 1710

Nowadays, there are a lot of methods to send money digitally to someone else. Most of the ways are through a bank or some wallets, but recently, using cryptocurrency has become popular.

Cryptocurrency is a great way to send money anonymously to others. Another advantage of cryptocurrencies is that their network is decentralized, which means there’s no one looking over the transaction, and there’s no middleman. Some people think this is not good because most scammers operate on cryptocurrencies, but some think that this is another step towards privacy.

Today, we are going to create a cryptocurrency using JavaScript. Hopefully, this article will give you a basic idea of how to create your own cryptocurrency, and you can continue to work on these skills for improving privacy in your finances.

Requirements

You can always refer to the GitHub repository if you want to have a look at the code.

Getting started

Let’s get started by creating a Node project. Navigate to a safe directory and enter the following command to create a new project:

npm init -y

This should generate a package.json file for you. If the file is created, then the project is created.

Now let’s create a new file called index.js. First, import the crypto package so that we can deal with hashes in our project. The crypto package helps us to work with hashes, signatures, and keys. It allows us to perform cryptographic conversion in Node.

This is a pre-installed package with Node, so you don’t need to install it separately:

const crypto = require("crypto");

We will be dealing with four classes in these projects. They are:

  • Transaction
  • Block
  • Chain
  • Wallet

First let’s create the Transaction class.

We made a custom demo for .
No really. Click here to check it out.

Creating the Transaction class

The basic properties of a transaction will be the amount, senderPublicKey, and recieverPublicKey. So let’s set up a constructor for the properties so that we can use the class later:

class Transaction {
  constructor(amount, senderPublicKey, recieverPublicKey) {
    this.amount = amount;
    this.senderPublicKey = senderPublicKey;
    this.recieverPublicKey = recieverPublicKey;
  }
}

We also need a method to convert the object of the class into a string so as to convert it into a hash. So, we will create a function to convert the object to string for later use:

toString() {
  return JSON.stringify(this);
}

Your complete Transaction class should look like the following:

class Transaction {
  constructor(amount, senderPublicKey, recieverPublicKey) {
    this.amount = amount;
    this.senderPublicKey = senderPublicKey;
    this.recieverPublicKey = recieverPublicKey;
  }
  // convert the data of the class to json so that
  // it can be converted into a hash
  toString() {
    return JSON.stringify(this);
  }
}

We can now store these transactions inside a block, which we will create next.

Creating the Block class

The term “blockchain” means exactly what it sounds like – a chain of blocks. The chain is the collection of blocks (that contain the transactions) linked to each other so that we can access them in a systematic manner.

To get things started, let’s set up the constructors and properties we will be using with the Block class:

class Block {
  constructor(previousHash, transaction, timestamp = Date.now()) {
    this.previousHash = previousHash;
    this.transaction = transaction;
    this.timestamp = timestamp;
  }
}

In a block, we will have previousHash (the hash of previous block on the chain), transaction (the object of class Transaction), and timestamp (the time the block was created).

Now, let’s create a function to generate a hash of the block:

getHash() {
  const json = JSON.stringify(this);
  const hash = crypto.createHash("SHA256");
  hash.update(json).end();
  const hex = hash.digest("hex");
  return hex;
}

Firstly, we convert the object into JSON format. Then, we create a SHA256 hash, which is a hashing method that cannot be decrypted. We use the hash to verify the blocks later; it provides legitimacy for a block once a hash is verified.

Next, we add the JSON as the data so that it gets converted to a SHA256 hash. Finally, we create a HEX digest for the hash and we return it.

Now again, we create a function to convert the block object into JSON:

toString() {
  JSON.stringify(this);
}

Your complete Block class should now look like this:

class Block {
  constructor(previousHash, transaction, timestamp = Date.now()) {
    this.previousHash = previousHash;
    this.transaction = transaction;
    this.timestamp = timestamp;
  }
  getHash() {
    const json = JSON.stringify(this);
    const hash = crypto.createHash("SHA256");
    hash.update(json).end();
    const hex = hash.digest("hex");
    return hex;
  }
  toString() {
    return JSON.stringify(this);
  }
}

Now let’s create the Chain class.

Creating the Chain class

Now that we have our Block class ready, we can fill in those blocks in a Chain. A chain holds every block, or every transaction, that takes place on the blockchain. As discussed before, a blockchain contains all the blocks linked to each other, and our project needs a Chain class in order to keep all the blocks together in one place.

Because we only need to initialize the chain once and not multiple times, we will initialize it right away in the class itself:

class Chain {
  static instance = new Chain();
}

Let’s set up our constructor so that we have the first block ready in the chain whenever the program is run. This will also set up the array where our blocks are placed.

We do this to eliminate any errors in our project, because we depend on the previous block in parts of our code, so we need a dummy block initialized at first:

constructor() {
  this.chain = [new Block("", new Transaction(100, "temp", "temp"))];
}

Now, we need a function to get the last hash of the chain, in order to use the information in new blocks:

getPreviousBlockHash() {
    // sending the entire block itself
    return this.chain[this.chain.length - 1].getHash();
  }

Next, let’s create a function that will actually create and insert a block into our chain array:

insertBlock(transaction, senderPublicKey, sig) {
  // create verifier
  const verify = crypto.createVerify("SHA256");
  // add the transaction JSON
  verify.update(transaction.toString());
  // Verify it with the sender's public key
  const isValid = verify.verify(senderPublicKey, sig);
  if (isValid) {
    const block = new Block(this.getPreviousBlockHash(), transaction);
    console.log("Block added", block.toString());
    this.chain.push(block);
  }
}

Here, we are first using the createVerify function from the crypto package to verify hashes with the public keys. We then use the data from the JSON of a particular transaction, and finally verify by providing the sender’s public key and the signature.

This will return a boolean value that we can use to check if verification was successful or failed. If the verification was successful, we simply create a new block with that information and add it to the chain array.

Now your Chain class should look like this:

class Chain {
  static instance = new Chain();
  // initializing our chain with no records
  constructor() {
    this.chain = [new Block("", new Transaction(100, "temp", "temp"))];
  }
  getPreviousBlockHash() {
    // sending the entire block itself
    return this.chain[this.chain.length - 1].getHash();
  }
  insertBlock(transaction, senderPublicKey, sig) {
    // create verifier
    const verify = crypto.createVerify("SHA256");
    // add the transaction JSON
    verify.update(transaction.toString());
    // Verify it with the sender's public key
    const isValid = verify.verify(senderPublicKey, sig);
    if (isValid) {
      const block = new Block(this.getPreviousBlockHash(), transaction);
      console.log("Block added", block.toString());
      this.chain.push(block);
    }
  }
}

Creating the Wallet class

Now let’s create the wallets, which the users can use to send cryptocurrencies to other people. Each crypto wallet has a pair of keys: a public key and a private key. The private keys are used to create new transactions (e.g., send cryptocurrencies) and the public key is used to verify them and receive cryptocurrencies.

Let’s first set up the constructor so that we can generate a key pair as soon as the wallet is initiated:

constructor() {
  const keys = crypto.generateKeyPairSync("rsa", {
    modulusLength: 2048,
    publicKeyEncoding: { type: "spki", format: "pem" },
    privateKeyEncoding: { type: "pkcs8", format: "pem" },
  });
  this.privateKey = keys.privateKey;
  this.publicKey = keys.publicKey;
}

Here, we are using the PEM format for the keys. It is a well known format and can be saved on the user’s PC. The RSA algorithm allows us to create public and private keys.

Now let’s create a function that will help us to send cryptocurrencies to other wallets on the network:

send(amount, recieverPublicKey) {
  const transaction = new Transaction(
    amount,
    this.publicKey,
    recieverPublicKey
  );
  const shaSign = crypto.createSign("SHA256");
  // add the transaction json
  shaSign.update(transaction.toString()).end();
  // sign the SHA with the private key
  const signature = shaSign.sign(this.privateKey);
  Chain.instance.insertBlock(transaction, this.publicKey, signature);
}

In the above code, we take amount and recieverPublicKey as parameters and create a new object from the Transaction class using that information. We then create the hash of the transaction and sign it with the private key. Finally, we add it to the chain using the insertBlock function.

Testing things out

Now that everything is ready, you can test things out by creating wallets and creating transactions using them:

const itachi = new Wallet();
const madara = new Wallet();
const orochimaru = new Wallet();

itachi.send(50, madara.publicKey);
madara.send(23, orochimaru.publicKey);
orochimaru.send(5, madara.publicKey);

console.log(Chain.instance);

In the above code, I created wallets with random names (not quite random, they are the villains in Naruto), and then sent money from one wallet to other and finally logging the chain to see how it looks.

For me, my chain looked like this (yours might be different because of different hashes):

Chain {
  chain: [
    Block {
      previousHash: '',
      transaction: [Transaction],
      timestamp: 1634561976555
    },
    Block {
      previousHash: 'c22300510c923a8ebf4d804f6edb4370731fcfd58f938d255852b4ea2744f20e',
      transaction: [Transaction],
      timestamp: 1634561976623
    },
    Block {
      previousHash: '1799ab15685e086cdb539e1851a759c713b3f71205664286cd4024c9f74d2a69',
      transaction: [Transaction],
      timestamp: 1634561976628
    },
    Block {
      previousHash: '1eb1f51c1b94a18f1c35e0cd81245ea6c69bac0100573cb76f3dac8026132597',
      transaction: [Transaction],
      timestamp: 1634561976629
    }
  ]
}

What’s next?

This was just the basics of creating cryptocurrencies using JavaScript. You should not use this in production because cryptocurrencies involve a lot of different things such as mining and a lot of security is involved.

If you are stuck somewhere, you can always visit my GitHub repository to have a look at the code.

If you want to experiment even more, I’d recommend incorporating a wallet balance system and mining system into this project.

: Debug JavaScript errors more easily by understanding the context

Debugging code is always a tedious task. But the more you understand your errors the easier it is to fix them.

LogRocket allows you to understand these errors in new and unique ways. Our frontend monitoring solution tracks user engagement with your JavaScript frontends to give you the ability to find out exactly what the user did that led to an error.

LogRocket records console logs, page load times, stacktraces, slow network requests/responses with headers + bodies, browser metadata, and custom logs. Understanding the impact of your JavaScript code will never be easier!

.
Atharva Deosthale Web Developer and Designer | JavaScript = ❤ | MERN Stack Developer

Leave a Reply