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.
Transaction
classBlock
classChain
classWallet
classBefore we jump into making our own cryptocurrency using JavaScript, let’s discuss what a blockchain is.
Blockchain is a chain of data that cannot be altered. In the case of cryptocurrency, a blockchain contains blocks (containing information about transactions) connected to each other. Each block has a hash value that can be verified if it is legitimate and has not been injected by some hacker.
Since the blocks are connected to each other, the existing blocks cannot be changed, because all the blocks are linked together.
In the above diagram, A, B, and C are three blocks. These contain transaction data (amount of cryptocurrency sent, recipient wallet address, and other metadata). As we can see, each new block is linked to the previous block. This is done by storing the hash of the previous block in Prev and hash of next block in Next.
Transactions on the blockchain are kept on track using this method. To find any block, the other blocks are required. So, it’s not possible to delete one of the blocks or edit them because their hashes are verified, and maliciously altered blocks can easily be identified.
The blockchain is decentralized, which means no single authority has control over it. A blockchain is run by a lot of different computers computing hashes and checking if a block is legitimate. This process is called mining, and in return, the people running these mining operations receive some amount of cryptocurrency as a reward if they manage to solve a block first.
Different cryptocurrencies have different methods to mine, but mining ensures the overall security of the blockchain. Although in this tutorial we won’t be covering mining, you will get the basic idea of how you can develop your own cryptocurrency.
JavaScript might not be the best language to create your “production-level” cryptocurrency, it will still manage to give people like web developers introduction to this space quickly.
You can always refer to the GitHub repository if you want to have a look at the code.
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.
Transaction
classThe 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.
Block
classThe 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.
Chain
classNow 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); } } }
Wallet
classNow 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.
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 } ] }
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.
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 see exactly what the user did that led to an error.
LogRocket records console logs, page load times, stack traces, slow network requests/responses with headers + bodies, browser metadata, and custom logs. Understanding the impact of your JavaScript code will never be easier!
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to implement one-way and two-way data binding in Vue.js, using v-model and advanced techniques like defineModel for better apps.
Compare Prisma and Drizzle ORMs to learn their differences, strengths, and weaknesses for data access and migrations.
It’s easy for devs to default to JavaScript to fix every problem. Let’s use the RoLP to find simpler alternatives with HTML and CSS.
Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.