├── .gitignore
├── package.json
├── README.md
└── dev
├── test.js
├── blockchain.js
├── block-explorer
└── index.html
└── networkNode.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "javaScript-blockchain",
3 | "version": "1.0.0",
4 | "description": "Learn Blockchain By Building Your Own In JavaScript",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "node_1": "nodemon --watch dev -e js dev/networkNode.js 3001 http://localhost:3001",
9 | "node_2": "nodemon --watch dev -e js dev/networkNode.js 3002 http://localhost:3002",
10 | "node_3": "nodemon --watch dev -e js dev/networkNode.js 3003 http://localhost:3003",
11 | "node_4": "nodemon --watch dev -e js dev/networkNode.js 3004 http://localhost:3004",
12 | "node_5": "nodemon --watch dev -e js dev/networkNode.js 3005 http://localhost:3005"
13 | },
14 | "author": "",
15 | "license": "ISC",
16 | "dependencies": {
17 | "body-parser": "^1.18.2",
18 | "express": "^4.16.3",
19 | "nodemon": "^1.17.3",
20 | "request": "^2.87.0",
21 | "request-promise": "^4.2.2",
22 | "sha256": "^0.2.0",
23 | "uuid": "^3.2.1"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Learn Blockchain By Building Your Own In JavaScript
2 |
3 | This repository is the source code that accompanies a course on Udemy.com that teaches students how blockchain technology works by coding out their own blockchain prototype in javascript.
4 |
5 | The course is called **[Learn Blockchain By Building Your Own In JavaScript](https://www.udemy.com/build-a-blockchain-in-javascript/?couponCode=GHDISCOUNT)** and it can be found **[here](https://www.udemy.com/build-a-blockchain-in-javascript/?couponCode=GHDISCOUNT)**.
6 |
7 |
8 |
9 |
10 | ## Getting Started
11 |
12 | The first step in running this project is to run `npm install`.
13 |
14 | The rest of the steps can be found in the **[course](https://www.udemy.com/build-a-blockchain-in-javascript/?couponCode=GHDISCOUNT)**!
15 |
16 |
17 | ## Course Content
18 |
19 | In this course you will build out your very own **blockchain** and **decentralized blockchain network** using the javascript programming language.
20 |
21 | In this course you will learn all of the following concepts and your blockchain will have all of the following features:
22 |
23 | - A **proof of work** algorithm to secure the network.
24 | - **Hashing algorithms** to secure the data within the blockchain.
25 | - The ability to **mine (create) new blocks** that contain data.
26 | - The ability to **create transactions** and store them in blocks.
27 | - An **API/server** that will be used to interact with the blockchain from the internet.
28 | - It will be hosted on a **decentralized blockchain network**.
29 | - A **consensus algorithms** to verify that the network nodes have valid data and are synchronized.
30 | - A **broadcasting system** to keep the data in the blockchain network synchronized.
31 | - Many other awesome features!...
32 |
33 | When you have completed this course you will have built out **your own blockchain prototype in code**. You will have a thorough understanding of how blockchain technology actually works and why this technology is so **secure and valuable**. You will also have a deep understanding of how decentralized blockchain networks function and why decentralization is such an important feature for securing the blockchain. The whole process of **storing, securing, and validating data/transactions** on the blockchain will become very clear.
34 |
35 | ###### Copyright Disclaimer
36 | ###### The code in this repository is property of Eric Traub (owner). The code, all or portions of it, is not to be distributed in any way without written permission from the owner. The code is protected under United States copyright laws.
--------------------------------------------------------------------------------
/dev/test.js:
--------------------------------------------------------------------------------
1 | const Blockchain = require('./blockchain');
2 | const bitcoin = new Blockchain();
3 |
4 |
5 | const bc1 = {
6 | "chain": [
7 | {
8 | "index": 1,
9 | "timestamp": 1525295039150,
10 | "transactions": [],
11 | "nonce": 100,
12 | "hash": "0",
13 | "previousBlockHash": "0"
14 | },
15 | {
16 | "index": 2,
17 | "timestamp": 1525295064849,
18 | "transactions": [],
19 | "nonce": 18140,
20 | "hash": "0000b9135b054d1131392c9eb9d03b0111d4b516824a03c35639e12858912100",
21 | "previousBlockHash": "0"
22 | },
23 | {
24 | "index": 3,
25 | "timestamp": 1525295150900,
26 | "transactions": [
27 | {
28 | "amount": 12.5,
29 | "sender": "00",
30 | "recipient": "555dc5d04e4c11e89b44174d1b876bbf",
31 | "transactionId": "64b4c6504e4c11e89b44174d1b876bbf"
32 | },
33 | {
34 | "amount": 10,
35 | "sender": "NNFANSDFHYHTN90A09SNFAS",
36 | "recipient": "IUW099N0A90WENNU234UFAW",
37 | "transactionId": "881441704e4c11e89b44174d1b876bbf"
38 | },
39 | {
40 | "amount": 20,
41 | "sender": "NNFANSDFHYHTN90A09SNFAS",
42 | "recipient": "IUW099N0A90WENNU234UFAW",
43 | "transactionId": "8c835b604e4c11e89b44174d1b876bbf"
44 | },
45 | {
46 | "amount": 30,
47 | "sender": "NNFANSDFHYHTN90A09SNFAS",
48 | "recipient": "IUW099N0A90WENNU234UFAW",
49 | "transactionId": "92c6e7304e4c11e89b44174d1b876bbf"
50 | }
51 | ],
52 | "nonce": 59137,
53 | "hash": "0000c09685e31e57318e569b5fe3ca88ced727a29a0eb9cbea633e05056b4c29",
54 | "previousBlockHash": "0000b9135b054d1131392c9eb9d03b0111d4b516824a03c35639e12858912100"
55 | },
56 | {
57 | "index": 4,
58 | "timestamp": 1525295192141,
59 | "transactions": [
60 | {
61 | "amount": 12.5,
62 | "sender": "00",
63 | "recipient": "555dc5d04e4c11e89b44174d1b876bbf",
64 | "transactionId": "97fa3b804e4c11e89b44174d1b876bbf"
65 | },
66 | {
67 | "amount": 40,
68 | "sender": "NNFANSDFHYHTN90A09SNFAS",
69 | "recipient": "IUW099N0A90WENNU234UFAW",
70 | "transactionId": "a5d523504e4c11e89b44174d1b876bbf"
71 | },
72 | {
73 | "amount": 50,
74 | "sender": "NNFANSDFHYHTN90A09SNFAS",
75 | "recipient": "IUW099N0A90WENNU234UFAW",
76 | "transactionId": "a8b55fe04e4c11e89b44174d1b876bbf"
77 | },
78 | {
79 | "amount": 60,
80 | "sender": "NNFANSDFHYHTN90A09SNFAS",
81 | "recipient": "IUW099N0A90WENNU234UFAW",
82 | "transactionId": "ab0347804e4c11e89b44174d1b876bbf"
83 | },
84 | {
85 | "amount": 70,
86 | "sender": "NNFANSDFHYHTN90A09SNFAS",
87 | "recipient": "IUW099N0A90WENNU234UFAW",
88 | "transactionId": "ad9738d04e4c11e89b44174d1b876bbf"
89 | }
90 | ],
91 | "nonce": 16849,
92 | "hash": "00001f3f4e1635cc930cdc41a954d19bcf457eeba8bf6c7be7aa4fe1489e64d3",
93 | "previousBlockHash": "0000c09685e31e57318e569b5fe3ca88ced727a29a0eb9cbea633e05056b4c29"
94 | },
95 | {
96 | "index": 5,
97 | "timestamp": 1525295206369,
98 | "transactions": [
99 | {
100 | "amount": 12.5,
101 | "sender": "00",
102 | "recipient": "555dc5d04e4c11e89b44174d1b876bbf",
103 | "transactionId": "b08f1c104e4c11e89b44174d1b876bbf"
104 | }
105 | ],
106 | "nonce": 40153,
107 | "hash": "000067295fb567842799b887910fe31cc8ca7544ec15a000b65005f6ac50df21",
108 | "previousBlockHash": "00001f3f4e1635cc930cdc41a954d19bcf457eeba8bf6c7be7aa4fe1489e64d3"
109 | },
110 | {
111 | "index": 6,
112 | "timestamp": 1525295212959,
113 | "transactions": [
114 | {
115 | "amount": 12.5,
116 | "sender": "00",
117 | "recipient": "555dc5d04e4c11e89b44174d1b876bbf",
118 | "transactionId": "b90a6f704e4c11e89b44174d1b876bbf"
119 | }
120 | ],
121 | "nonce": 252386,
122 | "hash": "0000462c88b2814ebb930b13ac3c19dc698b2dca27b0c296e03f8a2ea104f74f",
123 | "previousBlockHash": "000067295fb567842799b887910fe31cc8ca7544ec15a000b65005f6ac50df21"
124 | }
125 | ],
126 | "pendingTransactions": [
127 | {
128 | "amount": 12.5,
129 | "sender": "00",
130 | "recipient": "555dc5d04e4c11e89b44174d1b876bbf",
131 | "transactionId": "bcf84b704e4c11e89b44174d1b876bbf"
132 | }
133 | ],
134 | "currentNodeUrl": "http://localhost:3001",
135 | "networkNodes": []
136 | };
137 |
138 |
139 |
140 |
141 | console.log('VALID: ', bitcoin.chainIsValid(bc1.chain));
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
--------------------------------------------------------------------------------
/dev/blockchain.js:
--------------------------------------------------------------------------------
1 | const sha256 = require('sha256');
2 | const currentNodeUrl = process.argv[3];
3 | const uuid = require('uuid/v1');
4 |
5 | function Blockchain() {
6 | this.chain = [];
7 | this.pendingTransactions = [];
8 |
9 | this.currentNodeUrl = currentNodeUrl;
10 | this.networkNodes = [];
11 |
12 | this.createNewBlock(100, '0', '0');
13 | };
14 |
15 |
16 | Blockchain.prototype.createNewBlock = function(nonce, previousBlockHash, hash) {
17 | const newBlock = {
18 | index: this.chain.length + 1,
19 | timestamp: Date.now(),
20 | transactions: this.pendingTransactions,
21 | nonce: nonce,
22 | hash: hash,
23 | previousBlockHash: previousBlockHash
24 | };
25 |
26 | this.pendingTransactions = [];
27 | this.chain.push(newBlock);
28 |
29 | return newBlock;
30 | };
31 |
32 |
33 | Blockchain.prototype.getLastBlock = function() {
34 | return this.chain[this.chain.length - 1];
35 | };
36 |
37 |
38 | Blockchain.prototype.createNewTransaction = function(amount, sender, recipient) {
39 | const newTransaction = {
40 | amount: amount,
41 | sender: sender,
42 | recipient: recipient,
43 | transactionId: uuid().split('-').join('')
44 | };
45 |
46 | return newTransaction;
47 | };
48 |
49 |
50 | Blockchain.prototype.addTransactionToPendingTransactions = function(transactionObj) {
51 | this.pendingTransactions.push(transactionObj);
52 | return this.getLastBlock()['index'] + 1;
53 | };
54 |
55 |
56 | Blockchain.prototype.hashBlock = function(previousBlockHash, currentBlockData, nonce) {
57 | const dataAsString = previousBlockHash + nonce.toString() + JSON.stringify(currentBlockData);
58 | const hash = sha256(dataAsString);
59 | return hash;
60 | };
61 |
62 |
63 | Blockchain.prototype.proofOfWork = function(previousBlockHash, currentBlockData) {
64 | let nonce = 0;
65 | let hash = this.hashBlock(previousBlockHash, currentBlockData, nonce);
66 | while (hash.substring(0, 4) !== '0000') {
67 | nonce++;
68 | hash = this.hashBlock(previousBlockHash, currentBlockData, nonce);
69 | }
70 |
71 | return nonce;
72 | };
73 |
74 |
75 |
76 | Blockchain.prototype.chainIsValid = function(blockchain) {
77 | let validChain = true;
78 |
79 | for (var i = 1; i < blockchain.length; i++) {
80 | const currentBlock = blockchain[i];
81 | const prevBlock = blockchain[i - 1];
82 | const blockHash = this.hashBlock(prevBlock['hash'], { transactions: currentBlock['transactions'], index: currentBlock['index'] }, currentBlock['nonce']);
83 | if (blockHash.substring(0, 4) !== '0000') validChain = false;
84 | if (currentBlock['previousBlockHash'] !== prevBlock['hash']) validChain = false;
85 | };
86 |
87 | const genesisBlock = blockchain[0];
88 | const correctNonce = genesisBlock['nonce'] === 100;
89 | const correctPreviousBlockHash = genesisBlock['previousBlockHash'] === '0';
90 | const correctHash = genesisBlock['hash'] === '0';
91 | const correctTransactions = genesisBlock['transactions'].length === 0;
92 |
93 | if (!correctNonce || !correctPreviousBlockHash || !correctHash || !correctTransactions) validChain = false;
94 |
95 | return validChain;
96 | };
97 |
98 |
99 | Blockchain.prototype.getBlock = function(blockHash) {
100 | let correctBlock = null;
101 | this.chain.forEach(block => {
102 | if (block.hash === blockHash) correctBlock = block;
103 | });
104 | return correctBlock;
105 | };
106 |
107 |
108 | Blockchain.prototype.getTransaction = function(transactionId) {
109 | let correctTransaction = null;
110 | let correctBlock = null;
111 |
112 | this.chain.forEach(block => {
113 | block.transactions.forEach(transaction => {
114 | if (transaction.transactionId === transactionId) {
115 | correctTransaction = transaction;
116 | correctBlock = block;
117 | };
118 | });
119 | });
120 |
121 | return {
122 | transaction: correctTransaction,
123 | block: correctBlock
124 | };
125 | };
126 |
127 |
128 | Blockchain.prototype.getAddressData = function(address) {
129 | const addressTransactions = [];
130 | this.chain.forEach(block => {
131 | block.transactions.forEach(transaction => {
132 | if(transaction.sender === address || transaction.recipient === address) {
133 | addressTransactions.push(transaction);
134 | };
135 | });
136 | });
137 |
138 | let balance = 0;
139 | addressTransactions.forEach(transaction => {
140 | if (transaction.recipient === address) balance += transaction.amount;
141 | else if (transaction.sender === address) balance -= transaction.amount;
142 | });
143 |
144 | return {
145 | addressTransactions: addressTransactions,
146 | addressBalance: balance
147 | };
148 | };
149 |
150 |
151 |
152 |
153 |
154 |
155 | module.exports = Blockchain;
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
--------------------------------------------------------------------------------
/dev/block-explorer/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Block Explorer
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
Block Explorer
17 |
18 |
19 |
43 |
44 |
45 |
46 |
47 |
Block
48 |
49 |
50 |
51 | Block Hash
52 | {{ block.hash }}
53 |
54 |
55 | Index
56 | {{ block.index }}
57 |
58 |
59 | Time Stamp
60 | {{ block.timestamp }}
61 |
62 |
63 | Nonce
64 | {{ block.nonce }}
65 |
66 |
67 | Previous Hash
68 | {{ block.previousBlockHash }}
69 |
70 |
71 | Number Transactions
72 | {{ block.transactions.length }}
73 |
74 |
75 |
76 |
77 |
78 |
79 |
Transaction
80 |
81 |
82 |
83 | Sender
84 | {{ transaction.sender }}
85 |
86 |
87 | Recipient
88 | {{ transaction.recipient }}
89 |
90 |
91 | Amount
92 | {{ transaction.amount }}
93 |
94 |
95 |
96 |
97 |
98 |
99 |
Address
100 |
(Balance: {{ addressData.addressBalance }})
101 |
102 |
103 |
104 | Sender
105 | Recipient
106 | Amount
107 |
108 |
109 |
110 |
111 | {{ transaction.sender }}
112 | {{ transaction.recipient }}
113 | {{ transaction.amount }}
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
176 |
177 |
218 |
219 |
220 |
221 |
222 |
--------------------------------------------------------------------------------
/dev/networkNode.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const app = express();
3 | const bodyParser = require('body-parser');
4 | const Blockchain = require('./blockchain');
5 | const uuid = require('uuid/v1');
6 | const port = process.argv[2];
7 | const rp = require('request-promise');
8 |
9 | const nodeAddress = uuid().split('-').join('');
10 |
11 | const bitcoin = new Blockchain();
12 |
13 |
14 | app.use(bodyParser.json());
15 | app.use(bodyParser.urlencoded({ extended: false }));
16 |
17 |
18 | // get entire blockchain
19 | app.get('/blockchain', function (req, res) {
20 | res.send(bitcoin);
21 | });
22 |
23 |
24 | // create a new transaction
25 | app.post('/transaction', function(req, res) {
26 | const newTransaction = req.body;
27 | const blockIndex = bitcoin.addTransactionToPendingTransactions(newTransaction);
28 | res.json({ note: `Transaction will be added in block ${blockIndex}.` });
29 | });
30 |
31 |
32 | // broadcast transaction
33 | app.post('/transaction/broadcast', function(req, res) {
34 | const newTransaction = bitcoin.createNewTransaction(req.body.amount, req.body.sender, req.body.recipient);
35 | bitcoin.addTransactionToPendingTransactions(newTransaction);
36 |
37 | const requestPromises = [];
38 | bitcoin.networkNodes.forEach(networkNodeUrl => {
39 | const requestOptions = {
40 | uri: networkNodeUrl + '/transaction',
41 | method: 'POST',
42 | body: newTransaction,
43 | json: true
44 | };
45 |
46 | requestPromises.push(rp(requestOptions));
47 | });
48 |
49 | Promise.all(requestPromises)
50 | .then(data => {
51 | res.json({ note: 'Transaction created and broadcast successfully.' });
52 | });
53 | });
54 |
55 |
56 | // mine a block
57 | app.get('/mine', function(req, res) {
58 | const lastBlock = bitcoin.getLastBlock();
59 | const previousBlockHash = lastBlock['hash'];
60 | const currentBlockData = {
61 | transactions: bitcoin.pendingTransactions,
62 | index: lastBlock['index'] + 1
63 | };
64 | const nonce = bitcoin.proofOfWork(previousBlockHash, currentBlockData);
65 | const blockHash = bitcoin.hashBlock(previousBlockHash, currentBlockData, nonce);
66 | const newBlock = bitcoin.createNewBlock(nonce, previousBlockHash, blockHash);
67 |
68 | const requestPromises = [];
69 | bitcoin.networkNodes.forEach(networkNodeUrl => {
70 | const requestOptions = {
71 | uri: networkNodeUrl + '/receive-new-block',
72 | method: 'POST',
73 | body: { newBlock: newBlock },
74 | json: true
75 | };
76 |
77 | requestPromises.push(rp(requestOptions));
78 | });
79 |
80 | Promise.all(requestPromises)
81 | .then(data => {
82 | const requestOptions = {
83 | uri: bitcoin.currentNodeUrl + '/transaction/broadcast',
84 | method: 'POST',
85 | body: {
86 | amount: 12.5,
87 | sender: "00",
88 | recipient: nodeAddress
89 | },
90 | json: true
91 | };
92 |
93 | return rp(requestOptions);
94 | })
95 | .then(data => {
96 | res.json({
97 | note: "New block mined & broadcast successfully",
98 | block: newBlock
99 | });
100 | });
101 | });
102 |
103 |
104 | // receive new block
105 | app.post('/receive-new-block', function(req, res) {
106 | const newBlock = req.body.newBlock;
107 | const lastBlock = bitcoin.getLastBlock();
108 | const correctHash = lastBlock.hash === newBlock.previousBlockHash;
109 | const correctIndex = lastBlock['index'] + 1 === newBlock['index'];
110 |
111 | if (correctHash && correctIndex) {
112 | bitcoin.chain.push(newBlock);
113 | bitcoin.pendingTransactions = [];
114 | res.json({
115 | note: 'New block received and accepted.',
116 | newBlock: newBlock
117 | });
118 | } else {
119 | res.json({
120 | note: 'New block rejected.',
121 | newBlock: newBlock
122 | });
123 | }
124 | });
125 |
126 |
127 | // register a node and broadcast it the network
128 | app.post('/register-and-broadcast-node', function(req, res) {
129 | const newNodeUrl = req.body.newNodeUrl;
130 | if (bitcoin.networkNodes.indexOf(newNodeUrl) == -1) bitcoin.networkNodes.push(newNodeUrl);
131 |
132 | const regNodesPromises = [];
133 | bitcoin.networkNodes.forEach(networkNodeUrl => {
134 | const requestOptions = {
135 | uri: networkNodeUrl + '/register-node',
136 | method: 'POST',
137 | body: { newNodeUrl: newNodeUrl },
138 | json: true
139 | };
140 |
141 | regNodesPromises.push(rp(requestOptions));
142 | });
143 |
144 | Promise.all(regNodesPromises)
145 | .then(data => {
146 | const bulkRegisterOptions = {
147 | uri: newNodeUrl + '/register-nodes-bulk',
148 | method: 'POST',
149 | body: { allNetworkNodes: [ ...bitcoin.networkNodes, bitcoin.currentNodeUrl ] },
150 | json: true
151 | };
152 |
153 | return rp(bulkRegisterOptions);
154 | })
155 | .then(data => {
156 | res.json({ note: 'New node registered with network successfully.' });
157 | });
158 | });
159 |
160 |
161 | // register a node with the network
162 | app.post('/register-node', function(req, res) {
163 | const newNodeUrl = req.body.newNodeUrl;
164 | const nodeNotAlreadyPresent = bitcoin.networkNodes.indexOf(newNodeUrl) == -1;
165 | const notCurrentNode = bitcoin.currentNodeUrl !== newNodeUrl;
166 | if (nodeNotAlreadyPresent && notCurrentNode) bitcoin.networkNodes.push(newNodeUrl);
167 | res.json({ note: 'New node registered successfully.' });
168 | });
169 |
170 |
171 | // register multiple nodes at once
172 | app.post('/register-nodes-bulk', function(req, res) {
173 | const allNetworkNodes = req.body.allNetworkNodes;
174 | allNetworkNodes.forEach(networkNodeUrl => {
175 | const nodeNotAlreadyPresent = bitcoin.networkNodes.indexOf(networkNodeUrl) == -1;
176 | const notCurrentNode = bitcoin.currentNodeUrl !== networkNodeUrl;
177 | if (nodeNotAlreadyPresent && notCurrentNode) bitcoin.networkNodes.push(networkNodeUrl);
178 | });
179 |
180 | res.json({ note: 'Bulk registration successful.' });
181 | });
182 |
183 |
184 | // consensus
185 | app.get('/consensus', function(req, res) {
186 | const requestPromises = [];
187 | bitcoin.networkNodes.forEach(networkNodeUrl => {
188 | const requestOptions = {
189 | uri: networkNodeUrl + '/blockchain',
190 | method: 'GET',
191 | json: true
192 | };
193 |
194 | requestPromises.push(rp(requestOptions));
195 | });
196 |
197 | Promise.all(requestPromises)
198 | .then(blockchains => {
199 | const currentChainLength = bitcoin.chain.length;
200 | let maxChainLength = currentChainLength;
201 | let newLongestChain = null;
202 | let newPendingTransactions = null;
203 |
204 | blockchains.forEach(blockchain => {
205 | if (blockchain.chain.length > maxChainLength) {
206 | maxChainLength = blockchain.chain.length;
207 | newLongestChain = blockchain.chain;
208 | newPendingTransactions = blockchain.pendingTransactions;
209 | };
210 | });
211 |
212 |
213 | if (!newLongestChain || (newLongestChain && !bitcoin.chainIsValid(newLongestChain))) {
214 | res.json({
215 | note: 'Current chain has not been replaced.',
216 | chain: bitcoin.chain
217 | });
218 | }
219 | else {
220 | bitcoin.chain = newLongestChain;
221 | bitcoin.pendingTransactions = newPendingTransactions;
222 | res.json({
223 | note: 'This chain has been replaced.',
224 | chain: bitcoin.chain
225 | });
226 | }
227 | });
228 | });
229 |
230 |
231 | // get block by blockHash
232 | app.get('/block/:blockHash', function(req, res) {
233 | const blockHash = req.params.blockHash;
234 | const correctBlock = bitcoin.getBlock(blockHash);
235 | res.json({
236 | block: correctBlock
237 | });
238 | });
239 |
240 |
241 | // get transaction by transactionId
242 | app.get('/transaction/:transactionId', function(req, res) {
243 | const transactionId = req.params.transactionId;
244 | const trasactionData = bitcoin.getTransaction(transactionId);
245 | res.json({
246 | transaction: trasactionData.transaction,
247 | block: trasactionData.block
248 | });
249 | });
250 |
251 |
252 | // get address by address
253 | app.get('/address/:address', function(req, res) {
254 | const address = req.params.address;
255 | const addressData = bitcoin.getAddressData(address);
256 | res.json({
257 | addressData: addressData
258 | });
259 | });
260 |
261 |
262 | // block explorer
263 | app.get('/block-explorer', function(req, res) {
264 | res.sendFile('./block-explorer/index.html', { root: __dirname });
265 | });
266 |
267 |
268 |
269 |
270 |
271 | app.listen(port, function() {
272 | console.log(`Listening on port ${port}...`);
273 | });
274 |
275 |
276 |
277 |
278 |
279 |
--------------------------------------------------------------------------------