Skip to content

Commit bc00336

Browse files
committed
Complete Section: Frontend Cryptocurrency
1 parent c180240 commit bc00336

File tree

10 files changed

+302
-5
lines changed

10 files changed

+302
-5
lines changed

backend/app/__init__.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,20 @@ def route_wallet_transact():
7575
def route_wallet_info():
7676
return jsonify({ 'address': wallet.address, 'balance': wallet.balance })
7777

78+
@app.route('/known-addresses')
79+
def route_known_addresses():
80+
known_addresses = set()
81+
82+
for block in blockchain.chain:
83+
for transaction in block.data:
84+
known_addresses.update(transaction['output'].keys())
85+
86+
return jsonify(list(known_addresses))
87+
88+
@app.route('/transactions')
89+
def route_transactions():
90+
return jsonify(transaction_pool.transaction_data())
91+
7892
ROOT_PORT = 5000
7993
PORT = ROOT_PORT
8094

@@ -97,4 +111,9 @@ def route_wallet_info():
97111
Transaction(Wallet(), Wallet().address, random.randint(2, 50)).to_json()
98112
])
99113

114+
for i in range(3):
115+
transaction_pool.set_transaction(
116+
Transaction(Wallet(), Wallet().address, random.randint(2, 50))
117+
)
118+
100119
app.run(port=PORT)

frontend/package-lock.json

Lines changed: 97 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
"version": "0.1.0",
44
"private": true,
55
"dependencies": {
6+
"history": "^4.9.0",
67
"react": "^16.10.2",
78
"react-bootstrap": "^1.0.0-beta.14",
89
"react-dom": "^16.10.2",
10+
"react-router": "^5.0.1",
11+
"react-router-dom": "^5.0.1",
912
"react-scripts": "3.2.0"
1013
},
1114
"scripts": {

frontend/src/components/App.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { useState, useEffect } from 'react';
2+
import { Link } from 'react-router-dom';
23
import logo from '../assets/logo.png';
34
import { API_BASE_URL } from '../config';
4-
import Blockchain from './Blockchain';
55

66
function App() {
77
const [walletInfo, setWalletInfo] = useState({});
@@ -19,12 +19,14 @@ function App() {
1919
<img className="logo" src={logo} alt="application-logo" />
2020
<h3>Welcome to pychain</h3>
2121
<br />
22+
<Link to="/blockchain">Blockchain</Link>
23+
<Link to="/conduct-transaction">Conduct a Transaction</Link>
24+
<Link to="/transaction-pool">Transaction Pool</Link>
25+
<br />
2226
<div className="WalletInfo">
2327
<div>Address: {address}</div>
2428
<div>Balance: {balance}</div>
2529
</div>
26-
<br />
27-
<Blockchain />
2830
</div>
2931
);
3032
}

frontend/src/components/Blockchain.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React, { useState, useEffect } from 'react';
2+
import { Link } from 'react-router-dom';
23
import { Button } from 'react-bootstrap';
34
import { API_BASE_URL } from '../config';
45
import Block from './Block';
@@ -30,6 +31,8 @@ function Blockchain() {
3031

3132
return (
3233
<div className="Blockchain">
34+
<Link to='/'>Home</Link>
35+
<hr />
3336
<h3>Blockchain</h3>
3437
<div>
3538
{
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import React, { useState, useEffect } from 'react';
2+
import { Link } from 'react-router-dom';
3+
import { FormGroup, FormControl, Button } from 'react-bootstrap';
4+
import { API_BASE_URL } from '../config';
5+
import history from '../history';
6+
7+
function ConductTransaction() {
8+
const [amount, setAmount] = useState(0);
9+
const [recipient, setRecipient] = useState('');
10+
const [knownAddresses, setKnownAddresses] = useState([]);
11+
12+
useEffect(() => {
13+
fetch(`${API_BASE_URL}/known-addresses`)
14+
.then(response => response.json())
15+
.then(json => setKnownAddresses(json));
16+
}, []);
17+
18+
const updateRecipient = event => {
19+
setRecipient(event.target.value);
20+
}
21+
22+
const updateAmount = event => {
23+
setAmount(Number(event.target.value));
24+
}
25+
26+
const submitTransaction = () => {
27+
fetch(`${API_BASE_URL}/wallet/transact`, {
28+
method: 'POST',
29+
headers: { 'Content-Type': 'application/json' },
30+
body: JSON.stringify({ recipient, amount })
31+
}).then(response => response.json())
32+
.then(json => {
33+
console.log('submitTransaction json', json);
34+
35+
alert('Success!');
36+
37+
history.push('/transaction-pool');
38+
});
39+
}
40+
41+
return (
42+
<div className="ConductTransaction">
43+
<Link to="/">Home</Link>
44+
<hr />
45+
<h3>Conduct a Transaction</h3>
46+
<br />
47+
<FormGroup>
48+
<FormControl
49+
input="text"
50+
placeholder="recipient"
51+
value={recipient}
52+
onChange={updateRecipient}
53+
/>
54+
</FormGroup>
55+
<FormGroup>
56+
<FormControl
57+
input="number"
58+
placeholder="amount"
59+
value={amount}
60+
onChange={updateAmount}
61+
/>
62+
</FormGroup>
63+
<div>
64+
<Button
65+
variant="danger"
66+
onClick={submitTransaction}
67+
>
68+
Submit
69+
</Button>
70+
</div>
71+
<br />
72+
<h4>Known Addresses</h4>
73+
<div>
74+
{
75+
knownAddresses.map((knownAddress, i) => (
76+
<span key={knownAddress}>
77+
<u>{knownAddress}</u>{i !== knownAddresses.length - 1 ? ', ' : ''}
78+
</span>
79+
))
80+
}
81+
</div>
82+
</div>
83+
)
84+
}
85+
86+
export default ConductTransaction;
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import React, { useState, useEffect } from 'react';
2+
import { Link } from 'react-router-dom';
3+
import { Button } from 'react-bootstrap';
4+
import Transaction from './Transaction';
5+
import { API_BASE_URL, SECONDS_JS } from '../config';
6+
import history from '../history';
7+
8+
const POLL_INTERVAL = 10 * SECONDS_JS;
9+
10+
function TransactionPool() {
11+
const [transactions, setTransactions] = useState([]);
12+
13+
const fetchTransactions = () => {
14+
fetch(`${API_BASE_URL}/transactions`)
15+
.then(response => response.json())
16+
.then(json => {
17+
console.log('transactions json', json);
18+
19+
setTransactions(json);
20+
});
21+
}
22+
23+
useEffect(() => {
24+
fetchTransactions();
25+
26+
const intervalId = setInterval(fetchTransactions, POLL_INTERVAL);
27+
28+
return () => clearInterval(intervalId);
29+
}, []);
30+
31+
const fetchMineBlock = () => {
32+
fetch(`${API_BASE_URL}/blockchain/mine`)
33+
.then(() => {
34+
alert('Success!');
35+
36+
history.push('/blockchain');
37+
});
38+
}
39+
40+
return (
41+
<div className="TransactionPool">
42+
<Link to="/">Home</Link>
43+
<hr />
44+
<h3>Transaction Pool</h3>
45+
<div>
46+
{
47+
transactions.map(transaction => (
48+
<div key={transaction.id}>
49+
<hr />
50+
<Transaction transaction={transaction} />
51+
</div>
52+
))
53+
}
54+
</div>
55+
<hr />
56+
<Button
57+
variant="danger"
58+
onClick={fetchMineBlock}
59+
>
60+
Mine a block of these transactions
61+
</Button>
62+
</div>
63+
)
64+
}
65+
66+
export default TransactionPool;

frontend/src/config.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,7 @@ const NANOSECONDS_PY = 1;
33
const MICROSECONDS_PY = 1000 * NANOSECONDS_PY;
44
const MILLISECONDS_PY = 1000 * MICROSECONDS_PY;
55

6-
export { API_BASE_URL, MILLISECONDS_PY };
6+
const MILLISECONDS_JS = 1;
7+
const SECONDS_JS = MILLISECONDS_JS * 1000;
8+
9+
export { API_BASE_URL, MILLISECONDS_PY, SECONDS_JS };

frontend/src/history.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { createBrowserHistory } from 'history';
2+
3+
export default createBrowserHistory();

0 commit comments

Comments
 (0)