Written by Atharva Deosthale ✏️
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
- Node.js installed on your machine
- A code editor (I prefer Visual Studio Code)
- Working knowledge of Node
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.
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.
LogRocket: 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!
Top comments (3)
So if we're talking about cryptocurrencies and generating money with it, you should definitely buy in or use the most popular virtual coins. From my experience, I can tell that using the popular tools on this tabtrader.com/price/dogecoin to locate the greatest bargains to buy or sell crypto is a wonderful solution right now. I strongly advise everyone who is interested to pay close attention.
Awesome! This tutorial should really help if someone wants to learn more about how blockchain works.
I knew I shouldn't have bought all that A$$coin.