""" BlockchainToken Explorer — Gradio 6 gr.HTML Single-File App Deploy: huggingface-cli repo create blockchaintoken-explorer-v2 --type space --space-sdk gradio """ import gradio as gr import urllib.request import urllib.parse import json API = "https://blockchaintoken.com/api.php" def fetch_api(action, **params): params["action"] = action qs = "&".join(f"{k}={urllib.parse.quote(str(v))}" for k, v in params.items()) url = f"{API}?{qs}" try: req = urllib.request.Request(url, headers={"User-Agent": "BlockchainToken-Explorer/2.0"}) with urllib.request.urlopen(req, timeout=15) as r: return json.loads(r.read()) except Exception as e: return {"error": str(e)} def search_assets(query, network): if not query or len(query) < 2: return "

Enter at least 2 characters to search

" data = fetch_api("search", q=query, network=network) if "error" in data: return f"

Error: {data['error']}

" results = data.get("results", []) if not results: return "

No results found

" rows = "" for r in results: name = r.get("asset", "?") desc = r.get("description", "—")[:80] supply = r.get("supply", "?") rows += f"""
{name}
{desc}
Supply: {supply}
""" return f"
{rows}
" def get_stats(network): data = fetch_api("stats", network=network) if "error" in data: return f"

Error: {data['error']}

" total = data.get("total", "?") named = data.get("named", "?") numeric = data.get("numeric", "?") return f"""
{total}
Total Assets
{named}
Named
{numeric}
Numeric
""" CSS = """ .gradio-container { background: #0a0a0a !important; } .asset-card { background: #141414; border: 1px solid #2a2a2a; border-radius: 8px; padding: 16px; margin: 8px 0; transition: border-color 0.2s; } .asset-card:hover { border-color: #d4a017; } .asset-name { color: #d4a017; font-family: 'JetBrains Mono', monospace; font-size: 1.1em; font-weight: bold; } .asset-desc { color: #aaa; margin-top: 4px; font-size: 0.9em; } .asset-supply { color: #666; margin-top: 4px; font-size: 0.8em; } .results-grid { max-height: 500px; overflow-y: auto; } .stats-container { display: flex; gap: 16px; justify-content: center; margin: 16px 0; } .stat-box { background: #141414; border: 1px solid #2a2a2a; border-radius: 8px; padding: 24px 32px; text-align: center; min-width: 120px; } .stat-number { color: #d4a017; font-size: 2em; font-weight: bold; font-family: 'JetBrains Mono', monospace; } .stat-label { color: #888; margin-top: 4px; } """ with gr.Blocks(css=CSS, title="BlockchainToken Explorer", theme=gr.themes.Base()) as demo: gr.Markdown("# 🔗 BlockchainToken Explorer\n*Dogeparty & Counterparty Asset Search*") with gr.Row(): network = gr.Radio(["dogeparty", "counterparty"], value="dogeparty", label="Network") stats_html = gr.HTML() network.change(get_stats, inputs=[network], outputs=[stats_html]) demo.load(get_stats, inputs=[network], outputs=[stats_html]) with gr.Row(): query = gr.Textbox(label="Search Assets", placeholder="PEPECASH, FLDC, RARE...", scale=4) search_btn = gr.Button("🔍 Search", scale=1) results_html = gr.HTML() search_btn.click(search_assets, inputs=[query, network], outputs=[results_html]) query.submit(search_assets, inputs=[query, network], outputs=[results_html]) if __name__ == "__main__": demo.launch()