btc-api/main.py
2026-04-29 19:04:18 +00:00

119 lines
4.4 KiB
Python

import os
from flask import Flask, jsonify, request
from bitcoinlib.services.bitcoind import BitcoindClient
from dotenv import load_dotenv
# Lade die Variablen aus der .env-Datei in die Umgebung
load_dotenv()
app = Flask(__name__)
# --- ZUGANGSDATEN AUS UMGEBUNGSVARIABLEN LADEN ---
# os.getenv sucht nach dem Namen und liest den Wert aus
RPC_USER = os.getenv('RPC_USER')
RPC_PASS = os.getenv('RPC_PASS')
# Da das Skript IN der Windows-VM läuft, ist der Node lokal erreichbar:
IP_ADRESSE = '192.168.178.225'
# Sicherheits-Check: Falls die .env fehlt oder leer ist, bricht das Skript ab
if not RPC_USER or not RPC_PASS:
raise ValueError("Fehler: RPC_USER oder RPC_PASS wurden nicht in der Umgebung gefunden!")
rpc_url = f'http://{RPC_USER}:{RPC_PASS}@{IP_ADRESSE}:8332'
def get_node():
return BitcoindClient(network='bitcoin', base_url=rpc_url).proxy
# ==========================================
# ENDPUNKT 1: Aktuelle Blockhöhe abfragen
# ==========================================
@app.route('/api/blockhoehe', methods=['GET'])
def get_blockhoehe():
try:
node = get_node()
info = node.getblockchaininfo()
return jsonify({
'status': 'success',
'blockhoehe': info['blocks'],
'sync_fortschritt_prozent': round(info.get('verificationprogress', 0) * 100, 2)
})
except Exception as e:
return jsonify({'status': 'error', 'message': str(e)}), 500
# ==========================================
# ENDPUNKT 2: Bestimmten Block abfragen
# ==========================================
@app.route('/api/block/<int:hoehe>', methods=['GET'])
def get_block(hoehe):
try:
node = get_node()
block_hash = node.getblockhash(hoehe)
block_daten = node.getblock(block_hash, 2)
return jsonify({'status': 'success', 'block': block_daten})
except Exception as e:
return jsonify({'status': 'error', 'message': str(e)}), 500
# ==========================================
# ENDPUNKT 3: Einzelne Transaktion abfragen
# ==========================================
@app.route('/api/tx/<txid>', methods=['GET'])
def get_tx(txid):
try:
node = get_node()
tx_daten = node.getrawtransaction(txid, True)
return jsonify({'status': 'success', 'transaction': tx_daten})
except Exception as e:
return jsonify({'status': 'error', 'message': str(e)}), 500
# ==========================================
# ENDPUNKT 4: Guthaben einer beliebigen Adresse
# ==========================================
@app.route('/api/guthaben/<adresse>', methods=['GET'])
def get_guthaben(adresse):
try:
node = get_node()
scan_result = node.scantxoutset("start", [f"addr({adresse})"])
return jsonify({
'status': 'success',
'adresse': adresse,
'guthaben_btc': scan_result.get('total_amount', 0),
'anzahl_utxos': len(scan_result.get('unspents', [])),
# NEU: Wir schicken die komplette Liste der Münzen mit!
'utxos': scan_result.get('unspents', [])
})
except Exception as e:
return jsonify({'status': 'error', 'message': str(e)}), 500
# ==========================================
# NEU: ENDPUNKT 5: Transaktion senden (POST)
# ==========================================
@app.route('/api/sendtx', methods=['POST'])
def send_tx():
try:
# Wir erwarten ein JSON-Body mit dem Inhalt: {"hex": "01000000..."}
daten = request.get_json()
if not daten or 'hex' not in daten:
return jsonify({'status': 'error', 'message': 'Kein gueltiger Hex-String uebergeben. Sende ein JSON mit dem Key "hex".'}), 400
raw_tx_hex = daten['hex']
node = get_node()
# Sende die Transaktion an den Node, der sie ins Netzwerk broadcastet
txid = node.sendrawtransaction(raw_tx_hex)
return jsonify({
'status': 'success',
'message': 'Transaktion erfolgreich an das Netzwerk uebermittelt!',
'txid': txid
})
except Exception as e:
return jsonify({'status': 'error', 'message': str(e)}), 500
# ==========================================
# Server starten
# ==========================================
if __name__ == '__main__':
print("🚀 API Server startet...")
# host='0.0.0.0' bedeutet, dass die API von anderen Geräten im Heimnetzwerk erreichbar ist!
app.run(host='0.0.0.0', port=5001)