From b920476ad9252017d0c26e0add029140a71fdef6 Mon Sep 17 00:00:00 2001 From: aitbc Date: Mon, 30 Mar 2026 15:22:56 +0200 Subject: [PATCH] fix: chain command N/A output + deduplicate RPC messaging routes - get_chain_info now fetches from both /health (chain_id, supported_chains, proposer_id) and /rpc/head (height, hash, timestamp) - chain command displays Chain ID, Supported Chains, Height, Latest Block, Proposer instead of N/A values - Removed 4x duplicated messaging route definitions in router.py - Fixed /rpc/ prefix on routes inside router (was causing /rpc/rpc/... paths) - Fixed broken blocks-range route that was accidentally assigned to get_messaging_contract_state - Removed reference to non-existent contract_service --- .../src/aitbc_chain/rpc/router.py | 135 +++++------------- cli/aitbc_cli.py | 28 ++-- 2 files changed, 52 insertions(+), 111 deletions(-) diff --git a/apps/blockchain-node/src/aitbc_chain/rpc/router.py b/apps/blockchain-node/src/aitbc_chain/rpc/router.py index 572f8e73..355a420c 100755 --- a/apps/blockchain-node/src/aitbc_chain/rpc/router.py +++ b/apps/blockchain-node/src/aitbc_chain/rpc/router.py @@ -225,7 +225,30 @@ async def get_account(address: str) -> Dict[str, Any]: @router.get("/blocks-range", summary="Get blocks in height range") -# Working contract endpoints +async def get_blocks_range(start: int = 0, end: int = 10) -> Dict[str, Any]: + """Get blocks in a height range""" + with session_scope() as session: + from ..config import settings as cfg + blocks = session.exec( + select(Block).where( + Block.chain_id == cfg.chain_id, + Block.height >= start, + Block.height <= end, + ).order_by(Block.height.asc()) + ).all() + return { + "success": True, + "blocks": [{"height": b.height, "hash": b.hash, "timestamp": b.timestamp.isoformat(), "tx_count": b.tx_count} for b in blocks], + "count": len(blocks), + } + +@router.post("/contracts/deploy/messaging", summary="Deploy messaging contract") +async def deploy_messaging_contract(deploy_data: dict) -> Dict[str, Any]: + """Deploy the agent messaging contract to the blockchain""" + contract_address = "0xagent_messaging_001" + return {"success": True, "contract_address": contract_address, "status": "deployed"} + +@router.get("/contracts/messaging/state", summary="Get messaging contract state") async def get_messaging_contract_state() -> Dict[str, Any]: """Get the current state of the messaging contract""" state = { @@ -235,21 +258,12 @@ async def get_messaging_contract_state() -> Dict[str, Any]: } return {"success": True, "contract_state": state} -@router.post("/messaging/contract/deploy", summary="Deploy messaging contract") -async def deploy_messaging_contract(deploy_data: dict) -> Dict[str, Any]: - """Deploy the agent messaging contract to the blockchain""" - contract_address = "0xagent_messaging_001" - return {"success": True, "contract_address": contract_address, "status": "deployed"} - -@router.get("/contracts", summary="List deployed contracts") -async def list_contracts() -> Dict[str, Any]: - return contract_service.list_contracts() - +@router.get("/messaging/topics", summary="Get forum topics") async def get_forum_topics(limit: int = 50, offset: int = 0, sort_by: str = "last_activity") -> Dict[str, Any]: """Get list of forum topics""" return messaging_contract.get_topics(limit, offset, sort_by) -@router.post("/rpc/messaging/topics/create", summary="Create forum topic") +@router.post("/messaging/topics/create", summary="Create forum topic") async def create_forum_topic(topic_data: dict) -> Dict[str, Any]: """Create a new forum topic""" return messaging_contract.create_topic( @@ -260,12 +274,12 @@ async def create_forum_topic(topic_data: dict) -> Dict[str, Any]: topic_data.get("tags", []) ) -@router.get("/rpc/messaging/topics/{topic_id}/messages", summary="Get topic messages") +@router.get("/messaging/topics/{topic_id}/messages", summary="Get topic messages") async def get_topic_messages(topic_id: str, limit: int = 50, offset: int = 0, sort_by: str = "timestamp") -> Dict[str, Any]: """Get messages from a forum topic""" return messaging_contract.get_messages(topic_id, limit, offset, sort_by) -@router.post("/rpc/messaging/messages/post", summary="Post message") +@router.post("/messaging/messages/post", summary="Post message") async def post_message(message_data: dict) -> Dict[str, Any]: """Post a message to a forum topic""" return messaging_contract.post_message( @@ -277,7 +291,7 @@ async def post_message(message_data: dict) -> Dict[str, Any]: message_data.get("parent_message_id") ) -@router.post("/rpc/messaging/messages/{message_id}/vote", summary="Vote on message") +@router.post("/messaging/messages/{message_id}/vote", summary="Vote on message") async def vote_message(message_id: str, vote_data: dict) -> Dict[str, Any]: """Vote on a message (upvote/downvote)""" return messaging_contract.vote_message( @@ -287,17 +301,17 @@ async def vote_message(message_id: str, vote_data: dict) -> Dict[str, Any]: vote_data.get("vote_type") ) -@router.get("/rpc/messaging/messages/search", summary="Search messages") +@router.get("/messaging/messages/search", summary="Search messages") async def search_messages(query: str, limit: int = 50) -> Dict[str, Any]: """Search messages by content""" return messaging_contract.search_messages(query, limit) -@router.get("/rpc/messaging/agents/{agent_id}/reputation", summary="Get agent reputation") +@router.get("/messaging/agents/{agent_id}/reputation", summary="Get agent reputation") async def get_agent_reputation(agent_id: str) -> Dict[str, Any]: """Get agent reputation information""" return messaging_contract.get_agent_reputation(agent_id) -@router.post("/rpc/messaging/messages/{message_id}/moderate", summary="Moderate message") +@router.post("/messaging/messages/{message_id}/moderate", summary="Moderate message") async def moderate_message(message_id: str, moderation_data: dict) -> Dict[str, Any]: """Moderate a message (moderator only)""" return messaging_contract.moderate_message( @@ -307,88 +321,3 @@ async def moderate_message(message_id: str, moderation_data: dict) -> Dict[str, moderation_data.get("action"), moderation_data.get("reason", "") ) - -@router.get("/rpc/messaging/topics", summary="Get forum topics") -async def get_forum_topics(limit: int = 50, offset: int = 0, sort_by: str = "last_activity") -> Dict[str, Any]: - """Get list of forum topics""" - return messaging_contract.get_topics(limit, offset, sort_by) -@router.post("/rpc/messaging/topics/create", summary="Create forum topic") -async def create_forum_topic(topic_data: dict) -> Dict[str, Any]: - """Create a new forum topic""" - return messaging_contract.create_topic(topic_data.get("agent_id"), topic_data.get("agent_address"), topic_data.get("title"), topic_data.get("description"), topic_data.get("tags", [])) -@router.post("/rpc/messaging/messages/post", summary="Post message") -async def post_message(message_data: dict) -> Dict[str, Any]: - """Post a message to a forum topic""" - return messaging_contract.post_message(message_data.get("agent_id"), message_data.get("agent_address"), message_data.get("topic_id"), message_data.get("content"), message_data.get("message_type", "post"), message_data.get("parent_message_id")) -@router.post("/rpc/contracts/deploy/messaging", summary="Deploy messaging contract") -async def deploy_messaging_contract(deploy_data: dict) -> Dict[str, Any]: - """Deploy the agent messaging contract to the blockchain""" - contract_address = "0xagent_messaging_001" - return {"success": True, "contract_address": contract_address, "status": "deployed"} -@router.get("/rpc/contracts/messaging/state", summary="Get messaging contract state") -async def get_messaging_contract_state() -> Dict[str, Any]: - """Get the current state of the messaging contract""" - state = { - "total_topics": len(messaging_contract.topics), - "total_messages": len(messaging_contract.messages), - "total_agents": len(messaging_contract.agent_reputations) - } - return {"success": True, "contract_state": state} - -# Agent messaging endpoints -@router.get("/rpc/messaging/topics", summary="Get forum topics") -async def get_forum_topics(limit: int = 50, offset: int = 0, sort_by: str = "last_activity") -> Dict[str, Any]: - """Get list of forum topics""" - return messaging_contract.get_topics(limit, offset, sort_by) - -@router.post("/rpc/messaging/topics/create", summary="Create forum topic") -async def create_forum_topic(topic_data: dict) -> Dict[str, Any]: - """Create a new forum topic""" - return messaging_contract.create_topic( - topic_data.get("agent_id"), - topic_data.get("agent_address"), - topic_data.get("title"), - topic_data.get("description"), - topic_data.get("tags", []) - ) - -@router.post("/rpc/messaging/messages/post", summary="Post message") -async def post_message(message_data: dict) -> Dict[str, Any]: - """Post a message to a forum topic""" - return messaging_contract.post_message( - message_data.get("agent_id"), - message_data.get("agent_address"), - message_data.get("topic_id"), - message_data.get("content"), - message_data.get("message_type", "post"), - message_data.get("parent_message_id") - ) - -# Agent messaging contract endpoints -@router.get("/rpc/messaging/topics", summary="Get forum topics") -async def get_forum_topics(limit: int = 50, offset: int = 0, sort_by: str = "last_activity") -> Dict[str, Any]: - """Get list of forum topics""" - return messaging_contract.get_topics(limit, offset, sort_by) - -@router.post("/rpc/messaging/topics/create", summary="Create forum topic") -async def create_forum_topic(topic_data: dict) -> Dict[str, Any]: - """Create a new forum topic""" - return messaging_contract.create_topic( - topic_data.get("agent_id"), - topic_data.get("agent_address"), - topic_data.get("title"), - topic_data.get("description"), - topic_data.get("tags", []) - ) - -@router.post("/rpc/messaging/messages/post", summary="Post message") -async def post_message(message_data: dict) -> Dict[str, Any]: - """Post a message to a forum topic""" - return messaging_contract.post_message( - message_data.get("agent_id"), - message_data.get("agent_address"), - message_data.get("topic_id"), - message_data.get("content"), - message_data.get("message_type", "post"), - message_data.get("parent_message_id") - ) diff --git a/cli/aitbc_cli.py b/cli/aitbc_cli.py index 717a27c8..30719622 100644 --- a/cli/aitbc_cli.py +++ b/cli/aitbc_cli.py @@ -638,13 +638,24 @@ def get_balance(wallet_name: str, rpc_url: str = DEFAULT_RPC_URL) -> Optional[Di def get_chain_info(rpc_url: str = DEFAULT_RPC_URL) -> Optional[Dict]: """Get blockchain information""" try: - # Use the head endpoint to get chain info - response = requests.get(f"{rpc_url}/rpc/head") - if response.status_code == 200: - return response.json() - else: - print(f"Error getting chain info: {response.text}") - return None + result = {} + # Get chain metadata from health endpoint + health_response = requests.get(f"{rpc_url}/health") + if health_response.status_code == 200: + health = health_response.json() + chains = health.get('supported_chains', []) + result['chain_id'] = chains[0] if chains else 'ait-mainnet' + result['supported_chains'] = ', '.join(chains) if chains else 'ait-mainnet' + result['proposer_id'] = health.get('proposer_id', '') + # Get head block for height + head_response = requests.get(f"{rpc_url}/rpc/head") + if head_response.status_code == 200: + head = head_response.json() + result['height'] = head.get('height', 0) + result['hash'] = head.get('hash', 'N/A') + result['timestamp'] = head.get('timestamp', 'N/A') + result['tx_count'] = head.get('tx_count', 0) + return result if result else None except Exception as e: print(f"Error: {e}") return None @@ -1331,8 +1342,9 @@ def main(): print("Blockchain Information:") print(f" Chain ID: {chain_info.get('chain_id', 'N/A')}") print(f" Supported Chains: {chain_info.get('supported_chains', 'N/A')}") - print(f" RPC Version: {chain_info.get('rpc_version', 'N/A')}") print(f" Height: {chain_info.get('height', 'N/A')}") + print(f" Latest Block: {str(chain_info.get('hash', 'N/A'))[:16]}...") + print(f" Proposer: {chain_info.get('proposer_id', 'N/A') or 'none'}") else: sys.exit(1)