Skip to content

Commit c65acb1

Browse files
created view_transactions.html on client side to view minned transaction on a specific node, added a configure page to add nodes and view all the avaliable nodes, added method to process and compare nodes and replace them if node is not updated
1 parent f629340 commit c65acb1

File tree

4 files changed

+286
-12
lines changed

4 files changed

+286
-12
lines changed

Diff for: blockchain/blockchain.py

+30-7
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,11 @@ def register_node(self, node_url):
3131
if parsed_url.netloc:
3232
self.nodes.add(parsed_url.netloc)
3333
elif parsed_url.path:
34-
self.nodes.add(parsed_url.path)
34+
true_url = parsed_url.scheme + ":" + parsed_url.path
35+
self.nodes.add(true_url)
3536
else:
3637
raise ValueError('Invalid URL')
3738

38-
39-
4039
def create_block(self, nonce, previous_hash):
4140
"""
4241
Add a block of transactions to the blockchain
@@ -163,6 +162,11 @@ def index():
163162
return render_template('./index.html')
164163

165164

165+
@app.route("/configure")
166+
def configure():
167+
return render_template('./configure.html')
168+
169+
166170
@app.route("/transactions_get", methods=['GET'])
167171
def get_transactions():
168172
transactions = blockchain.transactions
@@ -228,19 +232,38 @@ def get_nodes():
228232
return jsonify(response), 200
229233

230234

231-
@app.route("/register_node", methods=['GET'])
235+
@app.route('/resolve_nodes', methods=['GET'])
236+
def consensus():
237+
replaced = blockchain.resolve_conflicts()
238+
239+
if replaced:
240+
response = {
241+
'message': 'Our chain was replaced',
242+
'new_chain': blockchain.chain
243+
}
244+
else:
245+
response = {
246+
'message': 'Our chain is authoritative',
247+
'chain': blockchain.chain
248+
}
249+
return jsonify(response), 200
250+
251+
252+
@app.route("/register_node", methods=['POST'])
232253
def register_node():
233254
values = request.form
255+
# 127.0.0.1:5002,127.0.0.1:5003, 127.0.0.1:5004
234256
nodes = values.get('nodes').replace(' ', '').split(',')
257+
235258
if nodes is None:
236-
return 'Error: Supply valid nodes', 400
259+
return 'Error: Please supply a valid list of nodes', 400
237260

238261
for node in nodes:
239262
blockchain.register_node(node)
240263

241264
response = {
242-
"message": "Added nodes",
243-
"total_nodes": [node for nodes in blockchain.nodes]
265+
'message': 'Nodes have been added',
266+
'total_nodes': [node for node in blockchain.nodes]
244267
}
245268
return jsonify(response), 200
246269

Diff for: blockchain/templates/configure.html

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport"
6+
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
7+
<meta http-equiv="X-UA-Compatible" content="ie=edge">
8+
<title>Blockchain Frontend</title>
9+
10+
<link rel="stylesheet" href="/static/vendor/bootstrap/css/bootstrap.min.css">
11+
<link rel="stylesheet" href="/static/vendor/DataTables/css/datatables.min.css">
12+
<link rel="stylesheet" href="/static/vendor/font-awesome/font-awesome.min.css">
13+
<link rel="stylesheet" href="/static/css/custom.css">
14+
15+
</head>
16+
<body style="background: linear-gradient(110deg, #ecc9b9 60%, #d2c2ef 60%);">
17+
18+
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
19+
<div class="container">
20+
<a href="#" class="navbar-brand">Blockchain Frontend</a>
21+
22+
<div class="collapse navbar-collapse">
23+
<ul class="navbar-nav ml-auto">
24+
<li class="nav-item">
25+
<a href="/" class="nav-link">Home</a>
26+
</li>
27+
<li class="nav-item active">
28+
<a href="/configure" class="nav-link">Configure</a>
29+
</li>
30+
</ul>
31+
</div>
32+
</div>
33+
</nav>
34+
35+
<!-- Add nodes -->
36+
<div class="container">
37+
<div class="row">
38+
<div class="col-lg-12">
39+
<div class="card-body">
40+
<h4 class="card-title">Add Blockchain nodes</h4>
41+
<p class="card-text">Enter a list of Blockchain node URLs separated by comma and click on "Add" button to add them to the list of nodes</p>
42+
</div>
43+
</div>
44+
</div>
45+
</div>
46+
47+
<div class="container alert alert-secondary">
48+
<form id="node_form">
49+
<div class="row">
50+
<label class="col-sm-2">Node URLs:</label>
51+
<div class="col-sm-10">
52+
<input type="text" name="nodes" id="nodes" rows="2" class="form-control">
53+
</div>
54+
</div>
55+
56+
<br>
57+
58+
<div class="row">
59+
<div class="col-lg-12 text-center">
60+
<input type="button" id="add_node_button" class="btn btn-primary btn-lg" value="Add Node">
61+
</div>
62+
</div>
63+
</form>
64+
</div>
65+
66+
<hr>
67+
68+
<!-- List of nodes -->
69+
<div class="container">
70+
<div class="row">
71+
72+
<div class="col-lg-12">
73+
<div class="card-body">
74+
<h4 class="card-title">This node can retrieve Blockchain data from the following nodes:</h4>
75+
</div>
76+
</div>
77+
78+
<div class="col-lg-12" id="list_nodes">
79+
80+
</div>
81+
82+
</div>
83+
</div>
84+
85+
<script src="/static/vendor/jquery/jquery.min.js"></script>
86+
<script src="/static/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
87+
<script src="/static/vendor/DataTables/js/datatables.min.js"></script>
88+
<script src="/static/vendor/DataTables/js/ellipsis.js"></script>
89+
90+
<script>
91+
$(function() {
92+
$('#add_node_button').click(function() {
93+
$.ajax({
94+
url: '/register_node',
95+
type: 'POST',
96+
dataType: 'json',
97+
data: $('#node_form').serialize(),
98+
success: function(response) {
99+
document.getElementById('nodes').value = '';
100+
window.location.reload();
101+
},
102+
error: function(error) {
103+
console.log(error);
104+
}
105+
});
106+
});
107+
108+
$.ajax({
109+
url: '/get_nodes',
110+
type: 'GET',
111+
success: function(response) {
112+
let nodes = '';
113+
for (let i=0; i<response['nodes'].length; i++) {
114+
node = "<li><a href=http://" + response['nodes'][i] + ">" + response['nodes'][i] + "</a></li>"
115+
document.getElementById('list_nodes').innerHTML += node;
116+
}
117+
},
118+
error: function(error) {
119+
console.log(error);
120+
}
121+
});
122+
123+
});
124+
125+
</script>
126+
127+
</body>
128+
</html>

Diff for: blockchain/templates/index.html

+18-1
Original file line numberDiff line numberDiff line change
@@ -170,14 +170,31 @@ <h4 class="card-title">Transactions on the blockchain</h4>
170170
url: '/mine',
171171
type: 'GET',
172172
success: function(response) {
173-
// window.location.reload();
173+
window.location.reload();
174174
},
175175
error: function(error) {
176176
console.log(error);
177177
}
178178

179179
});
180180
});
181+
182+
$('#refresh_transactions').click(function() {
183+
window.location.reload();
184+
});
185+
186+
$('#refresh_blockchain').click(function() {
187+
$.ajax({
188+
url: '/resolve_nodes',
189+
type: 'GET',
190+
success: function(response) {
191+
window.location.reload();
192+
},
193+
error: function(error) {
194+
console.log(error);
195+
}
196+
});
197+
});
181198
});
182199

183200
</script>

Diff for: blockchain_client/templates/view_transactions.html

+110-4
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,119 @@
2222
<li class="nav-item">
2323
<a href="/" class="nav-link">Wallet Generator</a>
2424
</li>
25-
<li class="nav-item active">
25+
<li class="nav-item">
2626
<a href="/make_transaction" class="nav-link">Make Transaction</a>
2727
</li>
28-
<li class="nav-item">
29-
<a href="/view_transactions" class="nav-link">View transactions</a>
28+
<li class="nav-item active">
29+
<a href="/view_transactions" class="nav-link">View Transactions</a>
3030
</li>
3131
</ul>
3232
</div>
3333
</div>
34-
</nav>
34+
</nav>
35+
36+
<!-- Blockchain Node URL Selector -->
37+
<div class="container">
38+
<div class="row">
39+
<div class="col-lg-12">
40+
41+
<div class="card-body">
42+
<h4 class="card-title">View Transactions</h4>
43+
<p class="card-text">Enter a blockchain node URL and click on "View Transactions" button to check all transactions</p>
44+
</div>
45+
46+
</div>
47+
</div>
48+
</div>
49+
50+
<div class="container alert alert-secondary">
51+
52+
<div class="row">
53+
<label class="col-sm-2">Node URL:</label>
54+
<div class="col-sm-10">
55+
<textarea id="node_url" rows="1" class="form-control">http://127.0.0.1:5001</textarea>
56+
</div>
57+
</div>
58+
59+
<br>
60+
61+
<div class="row">
62+
<div class="col-lg-12 text-center">
63+
<input type="button" id="view_transactions" class="btn btn-primary btn-lg" value="View Transactions">
64+
</div>
65+
</div>
66+
67+
</div>
68+
69+
<br>
70+
<!-- Blockchain Transactions Table -->
71+
<div class="container">
72+
<table id="transactions_table" class="table table-striped table-bordered" cellspacing="0" width="100%">
73+
</table>
74+
</div>
75+
76+
<script src="/static/vendor/jquery/jquery.min.js"></script>
77+
<script src="/static/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
78+
<script src="/static/vendor/DataTables/js/datatables.min.js"></script>
79+
<script src="/static/vendor/DataTables/js/ellipsis.js"></script>
80+
81+
<script>
82+
$(function() {
83+
84+
$('#view_transactions').click(function(){
85+
86+
$.ajax({
87+
url: document.getElementById("node_url").value + "/chain",
88+
type: 'GET',
89+
success: function(response){
90+
91+
console.log(response);
92+
//Generate Transactions Table
93+
var transactions = [];
94+
count = 1;
95+
96+
for (i = 1; i < response.length; i++) {
97+
for (j = 0; j < response["chain"][i]["transactions"].length; j++) {
98+
99+
//format date
100+
var options = { year: "numeric", month: "short", day: "numeric", hour: "2-digit", minute: "2-digit", second: "2-digit" };
101+
var date = new Date(response["chain"][i]["timestamp"] * 1000);
102+
var formattedDateTime = date.toLocaleTimeString("en-us", options);
103+
104+
transaction = [count,
105+
response["chain"][i]["transactions"][j]["recipient_public_key"],
106+
response["chain"][i]["transactions"][j]["sender_public_key"],
107+
response["chain"][i]["transactions"][j]["amount"],
108+
formattedDateTime,
109+
response["chain"][i]["block_number"]];
110+
transactions.push(transaction);
111+
112+
count += 1;
113+
};
114+
};
115+
116+
// Restrict a column to 10 characters, do split words
117+
$('#transactions_table').dataTable( {
118+
data: transactions,
119+
columns: [{ title: "#" },
120+
{ title: "Recipient Public Key"},
121+
{ title: "Sender Public Key"},
122+
{ title: "Amount"},
123+
{ title: "Timestamp"},
124+
{ title: "Block"}],
125+
columnDefs: [ {targets: [1,2,3,4,5], render: $.fn.dataTable.render.ellipsis( 25 )}]
126+
} );
127+
128+
},
129+
error: function(error){
130+
console.log(error);
131+
}
132+
});
133+
});
134+
135+
});
136+
137+
</script>
138+
139+
</body>
140+
</html>

0 commit comments

Comments
 (0)