fix: add TTY handling to transactions commands and improve genesis info
Some checks failed
CLI Tests / test-cli (push) Has been cancelled
Cross-Node Transaction Testing / transaction-test (push) Has been cancelled
Deploy to Testnet / deploy-testnet (push) Has been cancelled
Multi-Node Stress Testing / stress-test (push) Has been cancelled
Security Scanning / security-scan (push) Has been cancelled

- Added sys.stdin.isatty() check before getpass in transactions send and batch commands
- Added environment variable fallback (AITBC_WALLET_PASSWORD) for non-interactive environments
- Added --data-dir option to genesis info command to allow custom data directory paths
- Improved error messages in genesis info to show chain_id and data directory
- Fixes termios.error in non-interactive environments for transactions
This commit is contained in:
aitbc
2026-05-26 13:14:03 +02:00
parent d365b84885
commit 99ef26e464
2 changed files with 41 additions and 6 deletions

View File

@@ -163,8 +163,9 @@ def verify(ctx, chain_id: str):
@genesis.command() @genesis.command()
@click.option("--chain-id", default=None, help="Chain ID to show info for (auto-detected from config if not provided)") @click.option("--chain-id", default=None, help="Chain ID to show info for (auto-detected from config if not provided)")
@click.option("--data-dir", default=None, help="Data directory path (default: /var/lib/aitbc/data)")
@click.pass_context @click.pass_context
def info(ctx, chain_id: str): def info(ctx, chain_id: str, data_dir: Optional[str]):
"""Show genesis block information""" """Show genesis block information"""
# Auto-detect chain_id from config if not provided # Auto-detect chain_id from config if not provided
if not chain_id: if not chain_id:
@@ -172,12 +173,18 @@ def info(ctx, chain_id: str):
config = get_config() config = get_config()
chain_id = getattr(config, 'chain_id', 'ait-mainnet') chain_id = getattr(config, 'chain_id', 'ait-mainnet')
# Use provided data dir or default
if not data_dir:
data_dir = "/var/lib/aitbc/data"
import json import json
import sqlite3 import sqlite3
genesis_path = Path(f"/var/lib/aitbc/data/{chain_id}/genesis.json") genesis_path = Path(data_dir) / chain_id / "genesis.json"
if not genesis_path.exists(): if not genesis_path.exists():
error(f"Genesis config not found: {genesis_path}") error(f"Genesis config not found: {genesis_path}")
error(f"Chain ID: {chain_id}, Data directory: {data_dir}")
error("Run 'aitbc genesis init' to create genesis block")
return return
try: try:

View File

@@ -3,6 +3,8 @@ Transaction commands for AITBC CLI
""" """
import json import json
import os
import sys
from pathlib import Path from pathlib import Path
from typing import Optional, Dict, Any, List from typing import Optional, Dict, Any, List
@@ -136,8 +138,21 @@ def send(from_wallet: str, to_address: str, amount: float, fee: float, password:
with open(password_file) as f: with open(password_file) as f:
password = f.read().strip() password = f.read().strip()
elif not password: elif not password:
import getpass # Check if we're in a TTY environment
password = getpass.getpass("Enter wallet password: ") if not sys.stdin.isatty():
# Non-interactive: try environment variable
password = os.environ.get("AITBC_WALLET_PASSWORD")
if not password:
error("No TTY available for password prompt. Use --password or --password-file, or set AITBC_WALLET_PASSWORD environment variable.")
raise click.Abort()
else:
# Interactive: prompt for password
import getpass
try:
password = getpass.getpass("Enter wallet password: ")
except Exception as e:
error(f"Password prompt failed: {e}")
raise click.Abort()
if not rpc_url: if not rpc_url:
rpc_url = DEFAULT_RPC_URL rpc_url = DEFAULT_RPC_URL
@@ -158,8 +173,21 @@ def batch(transactions_file: str, password: Optional[str], password_file: Option
with open(password_file) as f: with open(password_file) as f:
password = f.read().strip() password = f.read().strip()
elif not password: elif not password:
import getpass # Check if we're in a TTY environment
password = getpass.getpass("Enter wallet password: ") if not sys.stdin.isatty():
# Non-interactive: try environment variable
password = os.environ.get("AITBC_WALLET_PASSWORD")
if not password:
error("No TTY available for password prompt. Use --password or --password-file, or set AITBC_WALLET_PASSWORD environment variable.")
raise click.Abort()
else:
# Interactive: prompt for password
import getpass
try:
password = getpass.getpass("Enter wallet password: ")
except Exception as e:
error(f"Password prompt failed: {e}")
raise click.Abort()
if not rpc_url: if not rpc_url:
rpc_url = DEFAULT_RPC_URL rpc_url = DEFAULT_RPC_URL