Add dynamic join instructions endpoint to live API
- Add get_join_instructions() function that generates structured join data
- Include environment variables, config files, P2P config, RPC config sections
- Add route handlers for /agent/join/{chain_id}.json (FastAPI and Flask)
- Update discovery endpoint to include join endpoint in agent APIs
- Add nginx proxy configuration for /agent/join/ path
This commit is contained in:
@@ -188,6 +188,82 @@ def get_live_chain_data() -> Dict[str, Any]:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_join_instructions(chain_id: str) -> Dict[str, Any]:
|
||||||
|
"""Get dynamic join instructions for a specific chain"""
|
||||||
|
# Validate chain_id matches this node's chain
|
||||||
|
if chain_id != CHAIN_ID:
|
||||||
|
return {"error": "Chain not supported by this node", "supported_chain": CHAIN_ID}
|
||||||
|
|
||||||
|
# Get current network info
|
||||||
|
head = rpc_query("head")
|
||||||
|
info = rpc_query("info")
|
||||||
|
islands_rpc = rpc_query("islands")
|
||||||
|
|
||||||
|
block_height = head.get("height", 0) if head else 0
|
||||||
|
network_id = info.get("network_id", 1337) if info else 1337
|
||||||
|
block_time = info.get("block_time", 5) if info else 5
|
||||||
|
|
||||||
|
# Get peer addresses from islands RPC
|
||||||
|
p2p_peers = [f"{NODE_ID}:7070"]
|
||||||
|
if islands_rpc and isinstance(islands_rpc, dict) and "islands" in islands_rpc:
|
||||||
|
for island in islands_rpc["islands"]:
|
||||||
|
if island.get("island_id") == ISLAND_ID:
|
||||||
|
endpoints = island.get("endpoints", {})
|
||||||
|
p2p_list = endpoints.get("p2p", [])
|
||||||
|
p2p_peers = [peer.get("address", peer) for peer in p2p_list]
|
||||||
|
break
|
||||||
|
|
||||||
|
return {
|
||||||
|
"chain_id": CHAIN_ID,
|
||||||
|
"island_id": ISLAND_ID,
|
||||||
|
"chain_name": "AIT Mainnet" if CHAIN_ID == "ait-mainnet" else "AIT Testnet",
|
||||||
|
"chain_type": "production" if CHAIN_ID == "ait-mainnet" else "test",
|
||||||
|
"current_height": block_height,
|
||||||
|
"environment_variables": {
|
||||||
|
"NODE_ID": "your-node-id",
|
||||||
|
"ISLAND_ID": ISLAND_ID,
|
||||||
|
"CHAIN_ID": CHAIN_ID,
|
||||||
|
"NODE_ROLE": "follower",
|
||||||
|
"AITBC_RPC_URL": f"http://{NODE_ID}:8006/rpc",
|
||||||
|
"P2P_BIND_PORT": "7070",
|
||||||
|
"ENABLE_BLOCK_PRODUCTION": "false"
|
||||||
|
},
|
||||||
|
"config_files": {
|
||||||
|
"/etc/aitbc/.env": f"AITBC_RPC_URL=http://{NODE_ID}:8006/rpc\nENABLE_BLOCK_PRODUCTION=false\n",
|
||||||
|
"/etc/aitbc/node.env": f"NODE_ID=your-node-id\nISLAND_ID={ISLAND_ID}\nCHAIN_ID={CHAIN_ID}\nNODE_ROLE=follower\nP2P_BIND_PORT=7070\n"
|
||||||
|
},
|
||||||
|
"p2p_configuration": {
|
||||||
|
"peers": p2p_peers,
|
||||||
|
"bootstrap_nodes": [f"{NODE_ID}:7070"],
|
||||||
|
"bind_port": 7070,
|
||||||
|
"external_address": "your-node-ip:7070"
|
||||||
|
},
|
||||||
|
"rpc_configuration": {
|
||||||
|
"endpoints": [
|
||||||
|
f"http://{NODE_ID}:8006/rpc",
|
||||||
|
f"http://{'aitbc1' if NODE_ID == 'aitbc' else 'aitbc'}:8006/rpc"
|
||||||
|
],
|
||||||
|
"network_id": network_id,
|
||||||
|
"block_time": block_time,
|
||||||
|
"consensus": "proof_of_authority"
|
||||||
|
},
|
||||||
|
"setup_steps": [
|
||||||
|
"1. Clone the AITBC repository: git clone https://gitea.bubuit.net/oib/aitbc.git /opt/aitbc",
|
||||||
|
"2. Run the setup script: sudo /opt/aitbc/scripts/setup.sh",
|
||||||
|
"3. Configure environment variables in /etc/aitbc/.env and /etc/aitbc/node.env",
|
||||||
|
"4. Start the blockchain node: sudo systemctl start aitbc-blockchain-node",
|
||||||
|
"5. Verify connection: curl http://localhost:8006/rpc/head"
|
||||||
|
],
|
||||||
|
"documentation": "/docs/deployment/SETUP.md",
|
||||||
|
"_meta": {
|
||||||
|
"generated_at": datetime.now(timezone.utc).isoformat(),
|
||||||
|
"generated_by": NODE_ID,
|
||||||
|
"data_source": "live_rpc",
|
||||||
|
"note": "Replace 'your-node-id' and 'your-node-ip' with your actual node configuration"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_live_discovery() -> Dict[str, Any]:
|
def get_live_discovery() -> Dict[str, Any]:
|
||||||
"""Get live discovery data"""
|
"""Get live discovery data"""
|
||||||
head = rpc_query("head")
|
head = rpc_query("head")
|
||||||
@@ -215,7 +291,8 @@ def get_live_discovery() -> Dict[str, Any]:
|
|||||||
"discovery": "/agent/discovery.json",
|
"discovery": "/agent/discovery.json",
|
||||||
"islands": "/agent/islands.json",
|
"islands": "/agent/islands.json",
|
||||||
"chains": "/agent/chains.json",
|
"chains": "/agent/chains.json",
|
||||||
"health": "/agent/health"
|
"health": "/agent/health",
|
||||||
|
"join": f"/agent/join/{CHAIN_ID}.json"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"islands": [
|
"islands": [
|
||||||
@@ -274,6 +351,13 @@ if HAS_FASTAPI:
|
|||||||
"timestamp": datetime.now(timezone.utc).isoformat()
|
"timestamp": datetime.now(timezone.utc).isoformat()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@app.get("/agent/join/{chain_id}.json")
|
||||||
|
async def join_instructions(chain_id: str):
|
||||||
|
instructions = get_join_instructions(chain_id)
|
||||||
|
if "error" in instructions:
|
||||||
|
raise HTTPException(status_code=404, detail=instructions["error"])
|
||||||
|
return JSONResponse(content=instructions)
|
||||||
|
|
||||||
elif HAS_FLASK:
|
elif HAS_FLASK:
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
@@ -300,6 +384,13 @@ elif HAS_FLASK:
|
|||||||
"timestamp": datetime.now(timezone.utc).isoformat()
|
"timestamp": datetime.now(timezone.utc).isoformat()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@app.route("/agent/join/<chain_id>.json")
|
||||||
|
def join_instructions(chain_id):
|
||||||
|
instructions = get_join_instructions(chain_id)
|
||||||
|
if "error" in instructions:
|
||||||
|
abort(404, description=instructions["error"])
|
||||||
|
return jsonify(instructions)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import argparse
|
import argparse
|
||||||
|
|||||||
Reference in New Issue
Block a user