mirror of
https://github.com/curly60e/pyblock.git
synced 2026-08-14 12:43:15 +02:00
- Replace all shell=True subprocess calls with Python-native processing (nodeconnection.py, SPV/nodeconnection.py, SPV/ppi.py) - Mask sensitive inputs (private keys, passwords, tokens) with getpass - Add threading.Lock to block_explorer.py shared state - Use json.loads() instead of fragile string splitting in apisnd.py - Add path validation before file open in apisnd.py - Replace random.randint with secrets.randbelow for mining nonces - Fix destructive exception handlers in clone.py and feed.py - Replace bare except clauses with specific exceptions + logging - Remove unused imports (psutil, xmltodict, block_visualizer, base64, say) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
76 lines
2.5 KiB
Python
76 lines
2.5 KiB
Python
"""Async data workers for fetching Bitcoin data."""
|
|
|
|
import requests
|
|
|
|
|
|
def fetch_block_height():
|
|
"""Fetch current block height from mempool.space."""
|
|
try:
|
|
r = requests.get("https://mempool.space/api/blocks/tip/height", timeout=5)
|
|
return str(r.json())
|
|
except (requests.RequestException, ValueError, KeyError):
|
|
return "---"
|
|
|
|
|
|
def fetch_btc_price():
|
|
"""Fetch current BTC/USD price from mempool.space."""
|
|
try:
|
|
r = requests.get("https://mempool.space/api/v1/prices", timeout=5)
|
|
price = r.json().get("USD", 0)
|
|
return f"{price:,}"
|
|
except (requests.RequestException, ValueError, KeyError):
|
|
return "---"
|
|
|
|
|
|
def fetch_fees():
|
|
"""Fetch recommended fees from mempool.space."""
|
|
try:
|
|
r = requests.get("https://mempool.space/api/v1/fees/recommended", timeout=5)
|
|
return r.json()
|
|
except (requests.RequestException, ValueError, KeyError):
|
|
return {"fastestFee": "?", "halfHourFee": "?", "hourFee": "?"}
|
|
|
|
|
|
def fetch_mempool_info():
|
|
"""Fetch mempool summary."""
|
|
try:
|
|
r = requests.get("https://mempool.space/api/mempool", timeout=5)
|
|
data = r.json()
|
|
return {
|
|
"count": data.get("count", 0),
|
|
"vsize": data.get("vsize", 0),
|
|
"total_fee": data.get("total_fee", 0),
|
|
}
|
|
except (requests.RequestException, ValueError, KeyError):
|
|
return {"count": "?", "vsize": "?", "total_fee": "?"}
|
|
|
|
|
|
def fetch_latest_blocks():
|
|
"""Fetch latest 5 blocks from mempool.space."""
|
|
try:
|
|
r = requests.get("https://mempool.space/api/v1/blocks", timeout=5)
|
|
blocks = r.json()[:5]
|
|
return [
|
|
{
|
|
"height": b.get("height", "?"),
|
|
"tx_count": b.get("tx_count", "?"),
|
|
"size": round(b.get("size", 0) / 1_000_000, 2),
|
|
"pool": b.get("extras", {}).get("pool", {}).get("name", "Unknown"),
|
|
}
|
|
for b in blocks
|
|
]
|
|
except (requests.RequestException, ValueError, KeyError):
|
|
return []
|
|
|
|
|
|
def fetch_hashrate():
|
|
"""Fetch network hashrate info."""
|
|
try:
|
|
r = requests.get("https://mempool.space/api/v1/mining/hashrate/3d", timeout=5)
|
|
data = r.json()
|
|
current = data.get("currentHashrate", 0)
|
|
difficulty = data.get("currentDifficulty", 0)
|
|
eh = current / 1e18
|
|
return {"hashrate_eh": f"{eh:.1f}", "difficulty": f"{difficulty:.2e}"}
|
|
except (requests.RequestException, ValueError, KeyError):
|
|
return {"hashrate_eh": "?", "difficulty": "?"}
|