#!/usr/bin/env python3
"""
Simple AITBC Blockchain Explorer - Demonstrating the issues described in the analysis
"""
import asyncio
import httpx
from datetime import datetime
from typing import Dict, Any, Optional
from fastapi import FastAPI, HTTPException
from fastapi.responses import HTMLResponse
import uvicorn
app = FastAPI(title="Simple AITBC Explorer", version="0.1.0")
# Configuration
BLOCKCHAIN_RPC_URL = "http://localhost:8025"
# HTML Template with the problematic frontend
HTML_TEMPLATE = """
Simple AITBC Explorer
AITBC Blockchain Explorer
"""
# Problem 1: Only /api/chain/head and /api/blocks/{height} defined, missing /api/transactions/{hash}
@app.get("/api/chain/head")
async def get_chain_head():
"""Get current chain head"""
try:
async with httpx.AsyncClient() as client:
response = await client.get(f"{BLOCKCHAIN_RPC_URL}/rpc/head")
if response.status_code == 200:
return response.json()
except Exception as e:
print(f"Error getting chain head: {e}")
return {"height": 0, "hash": "", "timestamp": None}
@app.get("/api/blocks/{height}")
async def get_block(height: int):
"""Get block by height"""
try:
async with httpx.AsyncClient() as client:
response = await client.get(f"{BLOCKCHAIN_RPC_URL}/rpc/blocks/{height}")
if response.status_code == 200:
return response.json()
except Exception as e:
print(f"Error getting block {height}: {e}")
return {"height": height, "hash": "", "timestamp": None, "transactions": []}
@app.get("/api/transactions/{tx_hash}")
async def get_transaction(tx_hash: str):
"""Get transaction by hash - Problem 1: This endpoint was missing"""
try:
async with httpx.AsyncClient() as client:
response = await client.get(f"{BLOCKCHAIN_RPC_URL}/rpc/tx/{tx_hash}")
if response.status_code == 200:
tx_data = response.json()
# Problem 2: Map RPC schema to UI schema
return {
"hash": tx_data.get("tx_hash", tx_hash), # tx_hash -> hash
"from": tx_data.get("sender", "unknown"), # sender -> from
"to": tx_data.get("recipient", "unknown"), # recipient -> to
"amount": tx_data.get("payload", {}).get("value", "0"), # payload.value -> amount
"fee": tx_data.get("payload", {}).get("fee", "0"), # payload.fee -> fee
"timestamp": tx_data.get("created_at"), # created_at -> timestamp
"block_height": tx_data.get("block_height", "pending")
}
elif response.status_code == 404:
raise HTTPException(status_code=404, detail="Transaction not found")
except HTTPException:
raise
except Exception as e:
print(f"Error getting transaction {tx_hash}: {e}")
raise HTTPException(status_code=500, detail=f"Failed to fetch transaction: {str(e)}")
# Missing: @app.get("/api/transactions/{tx_hash}") - THIS IS THE PROBLEM
@app.get("/", response_class=HTMLResponse)
async def root():
"""Serve the explorer UI"""
return HTML_TEMPLATE
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8017)