In this tutorial, we’re gonna build an API that allows us to interact with our Blockchain.
Previous Post: How to build a Blockchain in Javascript
Next Post: How to build a Decentralized Blockchain Network in Javascript
Overview
We will create a server using Express.js, then build three endpoints that will allow us to interact with our Blockchain (in previous article):
const express = require('express'); app.get('/blockchain', function (req, res) { ... }); app.post('/transaction', function (req, res) { ... }); app.get('/mine', function (req, res) { ... });
– GET /blockchain
allows us to fetch our entire Blockchain so that we can look at the data inside.
– POST /transaction
to create a new transaction.
– GET /mine
for mining new Block using the Proof of Work method.
Practice
Setup Environment
This was our project folder before:
Now, under src folder, create new javascript file named api.js.
Install Express.js
Run command: npm install express
.
Inside app.js, import and initialize Express.js:
const express = require('express'); const app = express();
Install Body Parser
This is Node.js body parsing middleware that can parse incoming request bodies before handlers, available under the req.body
property.
To install it, run command: npm install body-parser
.
Inside app.js, add the code below:
const bodyParser = require('body-parser'); app.use(bodyParser.json());
bodyParser.json()
returns middleware that only parses json.
Install nodemon
During development of a NodeJs based application, nodemon will watch the files in the directory, and if any files change, it will automatically restart our node application.
To install it, run command: npm install nodemon
.
Then add start
script to package.json file:
{ "name": "blockchain", "version": "1.0.0", "description": "JSA blockchain demo", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "nodemon --watch src -e js src/api.js" }, "author": "JavaSampleApproach", "license": "ISC", "dependencies": { "body-parser": "^1.18.3", "express": "^4.16.3", "nodemon": "^1.17.5", "sha256": "^0.2.0" }, "keywords": [ "jsa-blockchain" ] }
After setup environment, our project folder structure will be like:
Build Blockchain API
Add code for endpoints in app.js:
const express = require('express'); const app = express(); const bodyParser = require('body-parser'); app.use(bodyParser.json()); const nodeAddr = 'JavaSampleApproach'; const Blockchain = require('../src/blockchain'); const bitcoin = new Blockchain(); app.get('/blockchain', function (req, res) { res.send(bitcoin); }); app.post('/transaction', function (req, res) { const blockIndex = bitcoin.makeNewTransaction( req.body.amount, req.body.sender, req.body.recipient ); res.json( { message: `Transaction is added to block with index: ${blockIndex}` } ); }); app.get('/mine', function (req, res) { const latestBlock = bitcoin.getLatestBlock(); const prevBlockHash = latestBlock.hash; const currentBlockData = { transactions: bitcoin.pendingTransactions, index: latestBlock.index + 1 } const nonce = bitcoin.proofOfWork(prevBlockHash, currentBlockData); const blockHash = bitcoin.hashBlock(prevBlockHash, currentBlockData, nonce); // reward for mining bitcoin.makeNewTransaction(1, '00000', nodeAddr); const newBlock = bitcoin.creatNewBlock(nonce, prevBlockHash, blockHash) res.json( { message: 'Mining new Block successfully!', newBlock } ); }); app.listen(3000, function () { console.log('> listening on port 3000...'); });
Run and Check results
– Run the API with command: npm start
.
– Open browser with url: http://localhost:3000/blockchain
.
– http://localhost:3000/mine
:
– http://localhost:3000/blockchain
again:
– POST a transaction with Advanced REST client:
– http://localhost:3000/blockchain
:
– http://localhost:3000/mine
:
– POST other 2 transactions, then http://localhost:3000/blockchain
:
– http://localhost:3000/mine
again:
– http://localhost:3000/blockchain
:
This is all Blocks inside our Blockchain:
{ "chain":[ { "index":1, "timestamp":1527739433288, "transactions":[ ], "nonce":100, "hash":"Genesis block", "prevBlockHash":"0" }, { "index":2, "timestamp":1527739588736, "transactions":[ { "amount":1, "sender":"00000", "recipient":"JavaSampleApproach" } ], "nonce":44, "hash":"00669af06fa8d395bea4f6325d39f43a3c87788152fc3050608aa23e55dfe964", "prevBlockHash":"Genesis block" }, { "index":3, "timestamp":1527739995327, "transactions":[ { "amount":190, "sender":"JACKIE", "recipient":"HELEN" }, { "amount":1, "sender":"00000", "recipient":"JavaSampleApproach" } ], "nonce":71, "hash":"00766767c03993c1c5269bd531599c7e67f414c27f0d8bd56b5de2c7f5964e5f", "prevBlockHash":"00669af06fa8d395bea4f6325d39f43a3c87788152fc3050608aa23e55dfe964" }, { "index":4, "timestamp":1527740237053, "transactions":[ { "amount":60, "sender":"JASON", "recipient":"KATHERIN" }, { "amount":210, "sender":"JASON", "recipient":"ADAM" }, { "amount":1, "sender":"00000", "recipient":"JavaSampleApproach" } ], "nonce":376, "hash":"00ca5d9c8ea5686547394d4d0ceaf612cee64fcc2f4f57b63d006eb48da60c55", "prevBlockHash":"00766767c03993c1c5269bd531599c7e67f414c27f0d8bd56b5de2c7f5964e5f" } ], "pendingTransactions":[ ] }