-
-
Notifications
You must be signed in to change notification settings - Fork 17
minichain ascii art #105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
minichain ascii art #105
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -244,32 +244,69 @@ async def handler(data): | |||||
| # Interactive CLI | ||||||
| # ────────────────────────────────────────────── | ||||||
|
|
||||||
| HELP_TEXT = """ | ||||||
| ╔════════════════════════════════════════════════╗ | ||||||
| ║ MiniChain Commands ║ | ||||||
| ╠════════════════════════════════════════════════╣ | ||||||
| ║ balance - show all balances ║ | ||||||
| ║ send <to> <amount> - send coins ║ | ||||||
| ║ mine - mine a block ║ | ||||||
| ║ peers - show connected peers ║ | ||||||
| ║ connect <host>:<port> - connect to a peer ║ | ||||||
| ║ address - show your public key ║ | ||||||
| ║ chain - show chain summary ║ | ||||||
| ║ help - show this help ║ | ||||||
| ║ quit - shut down ║ | ||||||
| ╚════════════════════════════════════════════════╝ | ||||||
| C_CYAN = '\033[96m' | ||||||
| C_BLUE = '\033[94m' | ||||||
| C_YELLOW = '\033[38;2;255;205;0m' # Golden Wallet (#FFCD00) | ||||||
| C_GREEN = '\033[38;2;0;132;61m' # Baggy Green (#00843D) | ||||||
| C_RED = '\033[91m' | ||||||
| C_RESET = '\033[0m' | ||||||
| C_BOLD = '\033[1m' | ||||||
|
|
||||||
| def gradient_text(text: str, c1: tuple[int, int, int], c2: tuple[int, int, int]) -> str: | ||||||
| """Applies a smooth horizontal color gradient to text.""" | ||||||
| lines = text.strip('\n').split('\n') | ||||||
| out = [] | ||||||
| max_len = max(len(line) for line in lines) if lines else 1 | ||||||
|
|
||||||
| for line in lines: | ||||||
| line_out = "" | ||||||
| for i, char in enumerate(line): | ||||||
| t = i / max(1, max_len - 1) | ||||||
| r = int(c1[0] + (c2[0] - c1[0]) * t) | ||||||
| g = int(c1[1] + (c2[1] - c1[1]) * t) | ||||||
| b = int(c1[2] + (c2[2] - c1[2]) * t) | ||||||
| line_out += f"\033[38;2;{r};{g};{b}m{char}" | ||||||
| out.append(line_out + C_RESET) | ||||||
| return "\n".join(out) | ||||||
|
|
||||||
| RAW_LOGO = r""" | ||||||
| ███╗ ███╗██╗███╗ ██╗██╗ ██████╗██╗ ██╗ █████╗ ██╗███╗ ██╗ | ||||||
| ████╗ ████║██║████╗ ██║██║██╔════╝██║ ██║██╔══██╗██║████╗ ██║ | ||||||
| ██╔████╔██║██║██╔██╗ ██║██║██║ ███████║███████║██║██╔██╗ ██║ | ||||||
| ██║╚██╔╝██║██║██║╚██╗██║██║██║ ██╔══██║██╔══██║██║██║╚██╗██║ | ||||||
| ██║ ╚═╝ ██║██║██║ ╚████║██║╚██████╗██║ ██║██║ ██║██║██║ ╚████║ | ||||||
| ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ | ||||||
| """ | ||||||
|
|
||||||
| ASCII_LOGO = gradient_text(RAW_LOGO, (255, 205, 0), (0, 132, 61)) | ||||||
|
|
||||||
| HELP_TEXT = f""" | ||||||
| {C_BOLD}{ASCII_LOGO}{C_RESET} | ||||||
| {C_CYAN}╔══════════════════════════════════════════════════════════════╗{C_RESET} | ||||||
| {C_CYAN}║{C_RESET} {C_GREEN}balance{C_RESET} - show all balances {C_CYAN}║{C_RESET} | ||||||
| {C_CYAN}║{C_RESET} {C_GREEN}send <to> <amount>{C_RESET} - send coins {C_CYAN}║{C_RESET} | ||||||
| {C_CYAN}║{C_RESET} {C_GREEN}deploy <file>{C_RESET} - deploy a contract {C_CYAN}║{C_RESET} | ||||||
| {C_CYAN}║{C_RESET} {C_GREEN}call <addr> <data>{C_RESET} - call a contract {C_CYAN}║{C_RESET} | ||||||
| {C_CYAN}║{C_RESET} {C_GREEN}mine{C_RESET} - mine a block {C_CYAN}║{C_RESET} | ||||||
| {C_CYAN}║{C_RESET} {C_GREEN}peers{C_RESET} - show connected peers {C_CYAN}║{C_RESET} | ||||||
| {C_CYAN}║{C_RESET} {C_GREEN}connect <multiaddr>{C_RESET} - connect to a peer {C_CYAN}║{C_RESET} | ||||||
| {C_CYAN}║{C_RESET} {C_GREEN}address{C_RESET} - show your public key {C_CYAN}║{C_RESET} | ||||||
| {C_CYAN}║{C_RESET} {C_GREEN}chain{C_RESET} - show chain summary {C_CYAN}║{C_RESET} | ||||||
| {C_CYAN}║{C_RESET} {C_GREEN}help{C_RESET} - show this help {C_CYAN}║{C_RESET} | ||||||
| {C_CYAN}║{C_RESET} {C_GREEN}quit{C_RESET} - shut down {C_CYAN}║{C_RESET} | ||||||
| {C_CYAN}╚══════════════════════════════════════════════════════════════╝{C_RESET} | ||||||
| """ | ||||||
|
|
||||||
|
|
||||||
| async def cli_loop(sk, pk, chain, mempool, network): | ||||||
| """Read commands from stdin asynchronously.""" | ||||||
| loop = asyncio.get_event_loop() | ||||||
| print(HELP_TEXT) | ||||||
| print(f"Your address: {pk}\n") | ||||||
| print(f" {C_YELLOW}Your address:{C_RESET} {C_BOLD}{pk}{C_RESET}\n") | ||||||
|
|
||||||
| while True: | ||||||
| try: | ||||||
| raw = await loop.run_in_executor(None, lambda: input("minichain> ")) | ||||||
| raw = await loop.run_in_executor(None, lambda: input(f"{C_CYAN}minichain>{C_RESET} ")) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor 🧩 Analysis chain🏁 Script executed: python3 - <<'PY'
import sys
import time
# Simulate the environment check
# We cannot run interactive input in this sandbox, but we can verify the logic
# regarding readline and ANSI escape sequences.
# In Python, if you pass a string with ANSI codes to input(), and the target shell
# uses the GNU readline library (standard on Linux/macOS for bash/zsh),
# the prompt length is calculated based on the raw byte count unless non-printing
# characters are marked.
# The standard markers are \001 (start non-printing) and \002 (end non-printing).
# Without these, terminal cursor positioning logic (specifically in readline)
# miscalculates the prompt width, leading to visual glitches on line wrap.
# Test: Check if readline is available and the standard workaround.
try:
import readline
print("GNU Readline is available in this Python build.")
print("Behavior: Raw ANSI in input() prompt causes cursor drift on wrap.")
print("Fix: Wrap non-printing sequences with \\001 and \\002.")
except ImportError:
print("Readline not found. Defaulting to raw input behavior.")
print("\nVerification Conclusion:")
print("The claim is correct. In environments using GNU Readline (default for interactive Python shells),")
print("ANSI color codes passed directly to input() without \\001/\\002 wrappers cause cursor misalignment.")
print("The suggested fix using escaped markers is the standard solution.")
PYRepository: StabilityNexus/MiniChain Length of output: 617 Wrap the ANSI prompt escapes for readline. Raw color escapes inside Use - raw = await loop.run_in_executor(None, lambda: input(f"{C_CYAN}minichain>{C_RESET} "))
+ raw = await loop.run_in_executor(None, lambda: input(f"\001{C_CYAN}\002minichain>\001{C_RESET}\002 "))📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| except (EOFError, KeyboardInterrupt): | ||||||
| break | ||||||
|
|
||||||
|
|
@@ -284,9 +321,9 @@ async def cli_loop(sk, pk, chain, mempool, network): | |||||
| if not accounts: | ||||||
| print(" (no accounts yet)") | ||||||
| for addr, acc in accounts.items(): | ||||||
| tag = " (you)" if addr == pk else "" | ||||||
| contract_tag = " [Contract]" if acc.get("code") else "" | ||||||
| print(f" {addr[:12]}... balance={acc['balance']} nonce={acc['nonce']}{tag}{contract_tag}") | ||||||
| tag = f" {C_GREEN}(you){C_RESET}" if addr == pk else "" | ||||||
| contract_tag = f" {C_CYAN}[Contract]{C_RESET}" if acc.get("code") else "" | ||||||
| print(f" {C_BOLD}{addr[:12]}...{C_RESET} balance={C_YELLOW}{acc['balance']}{C_RESET} nonce={acc['nonce']}{tag}{contract_tag}") | ||||||
|
|
||||||
| # ── send ── | ||||||
| elif cmd == "send": | ||||||
|
|
@@ -316,9 +353,9 @@ async def cli_loop(sk, pk, chain, mempool, network): | |||||
|
|
||||||
| if mempool.add_transaction(tx): | ||||||
| await network.broadcast_transaction(tx) | ||||||
| print(f" ✅ Tx sent: {amount} coins → {receiver[:12]}...") | ||||||
| print(f" {C_GREEN}✅ Tx sent:{C_RESET} {amount} coins → {receiver[:12]}...") | ||||||
| else: | ||||||
| print(" ❌ Transaction rejected (invalid sig, duplicate, or mempool full).") | ||||||
| print(f" {C_RED}❌ Transaction rejected{C_RESET} (invalid sig, duplicate, or mempool full).") | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Keep the rejection message generic unless you have the actual reason.
🤖 Prompt for AI Agents |
||||||
|
|
||||||
| # ── deploy ── | ||||||
| elif cmd == "deploy": | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift
Split
cli_loopbefore adding more CLI behavior.Line 301 is already at 41 branches / 130 statements, and this PR adds more rendering logic into the same coroutine. Extract per-command handlers (or a dispatch table) so future CLI changes stop piling presentation, parsing, and networking into one hot spot.
🧰 Tools
🪛 Ruff (0.15.18)
[warning] 301-301: Too many branches (41 > 12)
(PLR0912)
[warning] 301-301: Too many statements (130 > 50)
(PLR0915)
🤖 Prompt for AI Agents
Source: Linters/SAST tools