Archie
fix: correct API field names, add URL encoding + user-agent
7cbcde6
"""
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 "<p style='color:#888'>Enter at least 2 characters to search</p>"
data = fetch_api("search", q=query, network=network)
if "error" in data:
return f"<p style='color:#f66'>Error: {data['error']}</p>"
results = data.get("results", [])
if not results:
return "<p style='color:#888'>No results found</p>"
rows = ""
for r in results:
name = r.get("asset", "?")
desc = r.get("description", "β€”")[:80]
supply = r.get("supply", "?")
rows += f"""
<div class="asset-card">
<div class="asset-name">{name}</div>
<div class="asset-desc">{desc}</div>
<div class="asset-supply">Supply: {supply}</div>
</div>"""
return f"<div class='results-grid'>{rows}</div>"
def get_stats(network):
data = fetch_api("stats", network=network)
if "error" in data:
return f"<p style='color:#f66'>Error: {data['error']}</p>"
total = data.get("total", "?")
named = data.get("named", "?")
numeric = data.get("numeric", "?")
return f"""
<div class="stats-container">
<div class="stat-box">
<div class="stat-number">{total}</div>
<div class="stat-label">Total Assets</div>
</div>
<div class="stat-box">
<div class="stat-number">{named}</div>
<div class="stat-label">Named</div>
</div>
<div class="stat-box">
<div class="stat-number">{numeric}</div>
<div class="stat-label">Numeric</div>
</div>
</div>"""
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()