Files
aitbc/tests/fixtures/mock_blockchain_node.py
oib 15427c96c0 chore: update file permissions to executable across repository
- Change file mode from 644 to 755 for all project files
- Add chain_id parameter to get_balance RPC endpoint with default "ait-devnet"
- Rename Miner.extra_meta_data to extra_metadata for consistency
2026-03-06 22:17:54 +01:00

97 lines
2.8 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Mock blockchain node server for testing purposes.
Implements the minimal API endpoints required by the test suite.
"""
import json
import threading
import time
from typing import Dict, Any
from fastapi import FastAPI
from fastapi.responses import JSONResponse
import uvicorn
# Create FastAPI app
app = FastAPI(title="Mock Blockchain Node", version="0.1.0")
# Mock state
mock_chain_state = {
"height": 100,
"hash": "0xabcdef1234567890",
"balances": {
"aitbc1alice00000000000000000000000000000000000": 1000,
"aitbc1bob0000000000000000000000000000000000000": 500,
"aitbc1charl0000000000000000000000000000000000": 100
},
"transactions": []
}
@app.get("/openapi.json")
async def openapi():
"""Return OpenAPI spec"""
return {
"openapi": "3.0.0",
"info": {
"title": "AITBC Blockchain API",
"version": "0.1.0"
},
"paths": {}
}
@app.get("/rpc/head")
async def get_chain_head():
"""Get current chain head"""
return JSONResponse(mock_chain_state)
@app.get("/rpc/getBalance/{address}")
async def get_balance(address: str):
"""Get balance for an address"""
balance = mock_chain_state["balances"].get(address, 0)
return JSONResponse({"balance": balance})
@app.post("/rpc/admin/mintFaucet")
async def mint_faucet(request: Dict[str, Any]):
"""Mint tokens to an address (devnet only)"""
address = request.get("address")
amount = request.get("amount", 0)
if address in mock_chain_state["balances"]:
mock_chain_state["balances"][address] += amount
else:
mock_chain_state["balances"][address] = amount
return JSONResponse({"success": True, "new_balance": mock_chain_state["balances"][address]})
@app.post("/rpc/sendTx")
async def send_transaction(request: Dict[str, Any]):
"""Send a transaction"""
# Generate mock transaction hash
tx_hash = f"0x{hash(str(request)) % 1000000000000000000000000000000000000000000000000000000000000000:x}"
# Add to transactions list
mock_chain_state["transactions"].append({
"hash": tx_hash,
"type": request.get("type", "TRANSFER"),
"sender": request.get("sender"),
"timestamp": time.time()
})
return JSONResponse({"tx_hash": tx_hash, "status": "pending"})
@app.get("/health")
async def health():
"""Health check endpoint"""
return JSONResponse({"status": "ok", "height": mock_chain_state["height"]})
def run_mock_server(port: int):
"""Run the mock server on specified port"""
uvicorn.run(app, host="127.0.0.1", port=port, log_level="warning")
if __name__ == "__main__":
import sys
port = int(sys.argv[1]) if len(sys.argv) > 1 else 8081
print(f"Starting mock blockchain node on port {port}")
run_mock_server(port)