pyblock/pybitblock/block_explorer.py
2024-07-31 18:10:04 -03:00

117 lines
4.5 KiB
Python

import asyncio
from rich.live import Live
from rich.table import Table
from rich.panel import Panel
from rich.layout import Layout
from rich.text import Text
from rich.align import Align
from rich.console import Group
import subprocess
import json
import time
from threading import Event, Thread
from execute_load_config import load_config
# Load configuration
path, settings, settingsClock = load_config()
def fetch_blockchain_info(path):
raw_info = subprocess.run([path["bitcoincli"], "getblockchaininfo"], capture_output=True, text=True)
blockchain_info = json.loads(raw_info.stdout)
return blockchain_info
def fetch_block_info(path, blockhash):
raw_block_info = subprocess.run([path["bitcoincli"], "getblock", blockhash], capture_output=True, text=True)
block_info = json.loads(raw_block_info.stdout)
return block_info
def create_block_info_table(block_height, block_data):
table = Table(title=f"Block #{block_height}")
table.add_column("Metric", style="green")
table.add_column("Value", style="yellow")
table.add_row("Transactions", str(block_data['nTx']))
table.add_row("Size", f"{block_data['size']} bytes")
table.add_row("Weight", f"{block_data['weight']} weight units")
table.add_row("Version", str(block_data['version']))
table.add_row("Merkle Root", block_data['merkleroot'])
table.add_row("Time", time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(block_data['time'])))
table.add_row("Median Time", time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(block_data['mediantime'])))
table.add_row("Nonce", str(block_data['nonce']))
table.add_row("Bits", str(block_data['bits']))
table.add_row("Difficulty", f"{block_data['difficulty']:.2f}")
table.add_row("Chainwork", block_data['chainwork'])
table.add_row("Previous Block", block_data['previousblockhash'])
if 'nextblockhash' in block_data:
table.add_row("Next Block", block_data['nextblockhash'])
return table
def fetch_and_store_block_data(path, start_height, count, block_tables):
latest_height = start_height
for i in range(count): # Limitar a los bloques solicitados
block_height = latest_height - i
block_hash = subprocess.run([path["bitcoincli"], "getblockhash", str(block_height)], capture_output=True, text=True).stdout.strip()
block_data = fetch_block_info(path, block_hash)
table = create_block_info_table(block_height, block_data)
block_tables.append(table)
def background_block_fetch(path, block_tables, stop_event):
latest_height = fetch_blockchain_info(path)['blocks']
while not stop_event.is_set():
current_height = fetch_blockchain_info(path)['blocks']
if current_height > latest_height:
latest_height = current_height
block_tables.clear()
fetch_and_store_block_data(path, current_height, 3, block_tables)
time.sleep(10)
async def display_blocks_info():
layout = Layout()
layout.split_column(
Layout(name="header", size=3),
Layout(name="main", ratio=1),
Layout(name="footer", size=1),
)
layout["main"].split_row(
Layout(name="recent_blocks", ratio=1),
)
layout["footer"].update(Text("Cypherpunk style loading..."))
layout["recent_blocks"].update(Panel(Text("Cypherpunk Style loading..."), title="Recent Blocks"))
layout["header"].update(Text("Block Monitor", style="bold cyan"))
block_tables = []
blockchain_info = fetch_blockchain_info(path)
latest_block_height = blockchain_info['blocks']
fetch_and_store_block_data(path, latest_block_height, 3, block_tables)
stop_event = Event()
fetch_thread = Thread(target=background_block_fetch, args=(path, block_tables, stop_event))
fetch_thread.start()
async def input_handler():
while True:
key = await asyncio.get_event_loop().run_in_executor(None, input)
if key == 'q':
stop_event.set()
fetch_thread.join()
break
with Live(layout, refresh_per_second=1, screen=True):
input_task = asyncio.create_task(input_handler())
while not stop_event.is_set():
recent_blocks_group = Group(*block_tables)
centered_recent_blocks = Align.center(recent_blocks_group)
layout["recent_blocks"].update(Panel(centered_recent_blocks, title="Recent Blocks"))
layout["footer"].update(Text("Running the node."))
await asyncio.sleep(1)
def call_blocks():
asyncio.run(display_blocks_info())
if __name__ == "__main__":
call_blocks()