6. Build a web3 web with windows
6.1 tree folder
fhe-web-python/
├── app.py
├── abi.json
├── requirements.txt
├── .env
├── README.md
└── templates/
└── index.html6.2 . Create app.py
from flask import Flask, jsonify, render_template
from web3 import Web3
from dotenv import load_dotenv
import os
import json
load_dotenv()
app = Flask(__name__)
# Kiểm tra file
if not os.path.exists('abi.json'):
raise FileNotFoundError("Không tìm thấy abi.json!")
# Kết nối
RPC_URL = os.getenv('RPC_URL')
w3 = Web3(Web3.HTTPProvider(RPC_URL))
if not w3.is_connected():
raise Exception("Không kết nối được Sepolia!")
print(f"Kết nối thành công! Block: {w3.eth.block_number}")
# Contract
CONTRACT_ADDRESS = os.getenv('CONTRACT_ADDRESS')
with open('abi.json', 'r') as f:
ABI = json.load(f)
contract = w3.eth.contract(address=CONTRACT_ADDRESS, abi=ABI)
# Account
PRIVATE_KEY = os.getenv('PRIVATE_KEY')
account = w3.eth.account.from_key(PRIVATE_KEY)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/get_count')
def get_count():
try:
encrypted = contract.functions.getCount().call()
return jsonify({'count': 'Encrypted'})
except Exception as e:
return jsonify({'error': str(e)}), 500
@app.route('/increment', methods=['POST'])
def increment():
return send_tx('increment')
@app.route('/decrement', methods=['POST'])
def decrement():
return send_tx('decrement')
def send_tx(func_name):
try:
func = getattr(contract.functions, func_name)
# Tạo input đúng định dạng
encrypted_input = b'\x00' * 32 # bytes32
proof = b'\x00' * 64 # proof giả
tx = func(encrypted_input, proof).build_transaction({
'from': account.address,
'gas': 3000000,
'gasPrice': w3.to_wei('20', 'gwei'),
'nonce': w3.eth.get_transaction_count(account.address),
})
signed_tx = w3.eth.account.sign_transaction(tx, PRIVATE_KEY)
tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)
return jsonify({'tx_hash': tx_hash.hex()})
except Exception as e:
return jsonify({'error': str(e)}), 500
if __name__ == '__main__':
app.run(debug=True, port=5000)
6.3 . Create abi.json : coppy your abi contract
6.4 . Create requirements.txt
flask==3.0.0
web3==6.15.1
python-dotenv==1.0.06.5. Create .env
RPC_URL=https://sepolia.infura.io/v3/YOUR_INFURA_KEY
PRIVATE_KEY=0xYOUR_PRIVATE_KEY_HERE
CONTRACT_ADDRESS=0xdcc73F30E59FB1bb4D1292f796b7e574a092ea6f
RELAYER_URL=https://relayer.testnet.zama.cloud6.6 Create index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>FHE Counter DApp</title>
<style>
body { font-family: 'Segoe UI', sans-serif; text-align: center; padding: 50px; background: #f4f6f9; }
.card { max-width: 500px; margin: 0 auto; background: white; padding: 30px; border-radius: 16px; box-shadow: 0 4px 20px rgba(0,0,0,0.1); }
h1 { color: #2c3e50; }
.count { font-size: 3.5em; font-weight: bold; color: #3498db; margin: 20px 0; }
button { padding: 12px 24px; margin: 8px; font-size: 1.1em; border: none; border-radius: 8px; cursor: pointer; transition: 0.3s; }
.btn-inc { background: #27ae60; color: white; }
.btn-dec { background: #e74c3c; color: white; }
.btn-refresh { background: #3498db; color: white; }
button:hover { transform: translateY(-2px); }
#status { margin-top: 15px; font-style: italic; color: #7f8c8d; }
code { background: #ecf0f1; padding: 2px 6px; border-radius: 4px; font-size: 0.9em; }
</style>
</head>
<body>
<div class="card">
<h1>FHE Counter DApp</h1>
<p>Contract: <code>0xdcc73F30E59FB1bb4D1292f796b7e574a092ea6f</code></p>
<div class="count" id="count">Loading...</div>
<button class="btn-inc" onclick="inc()">+1</button>
<button class="btn-dec" onclick="dec()">-1</button>
<br><br>
<button class="btn-refresh" onclick="fetchCount()">Refresh</button>
<p id="status"></p>
</div>
<script>
const API = '';
async function fetchCount() {
document.getElementById('status').textContent = 'Đang đọc count...';
try {
const res = await fetch(API + 'get_count');
const data = await res.json();
if (data.error) throw new Error(data.error);
document.getElementById('count').textContent = data.count;
document.getElementById('status').textContent = 'Sẵn sàng!';
} catch (e) {
document.getElementById('status').textContent = 'Lỗi: ' + e.message;
}
}
async function send(action) {
document.getElementById('status').textContent = 'Đang gửi giao dịch...';
try {
const res = await fetch(API + action, { method: 'POST' });
const data = await res.json();
if (data.error) throw new Error(data.error);
document.getElementById('status').textContent = 'Tx: ' + data.tx_hash.substring(0, 10) + '...';
setTimeout(fetchCount, 3000);
} catch (e) {
document.getElementById('status').textContent = 'Lỗi: ' + e.message;
}
}
function inc() { send('increment'); }
function dec() { send('decrement'); }
// Load ban đầu
fetchCount();
</script>
</body>
</html>6.7 :Create virtual environment + settings:
python -m venv venv
venv\Scripts\activate
pip install -r requirements.txtok done , now run sever
python app.pyLast updated