- Remove standalone explorer-web app (README, HTML, package files) - Add /web endpoint to blockchain-explorer for web interface access - Update .gitignore to exclude application backup archives (*.tar.gz, *.zip) - Add backup documentation files to .gitignore (BACKUP_INDEX.md, README.md) - Consolidate explorer functionality into main blockchain-explorer application
652 lines
24 KiB
Python
Executable File
652 lines
24 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Complete Cross-Chain AITBC Exchange
|
|
Multi-chain trading with cross-chain swaps and bridging
|
|
"""
|
|
|
|
import sqlite3
|
|
import json
|
|
import asyncio
|
|
import httpx
|
|
from datetime import datetime, timedelta
|
|
from typing import Dict, List, Optional, Any
|
|
from fastapi import FastAPI, HTTPException, Query, BackgroundTasks
|
|
from pydantic import BaseModel, Field
|
|
import uvicorn
|
|
import os
|
|
import uuid
|
|
import hashlib
|
|
|
|
app = FastAPI(title="AITBC Complete Cross-Chain Exchange", version="3.0.0")
|
|
|
|
# Database configuration
|
|
DB_PATH = os.path.join(os.path.dirname(__file__), "exchange_multichain.db")
|
|
|
|
# Supported chains
|
|
SUPPORTED_CHAINS = {
|
|
"ait-devnet": {
|
|
"name": "AITBC Development Network",
|
|
"status": "active",
|
|
"blockchain_url": "http://localhost:8007",
|
|
"token_symbol": "AITBC-DEV",
|
|
"bridge_contract": "0x1234567890123456789012345678901234567890"
|
|
},
|
|
"ait-testnet": {
|
|
"name": "AITBC Test Network",
|
|
"status": "inactive",
|
|
"blockchain_url": None,
|
|
"token_symbol": "AITBC-TEST",
|
|
"bridge_contract": "0x0987654321098765432109876543210987654321"
|
|
}
|
|
}
|
|
|
|
# Models
|
|
class OrderRequest(BaseModel):
|
|
order_type: str = Field(..., regex="^(BUY|SELL)$")
|
|
amount: float = Field(..., gt=0)
|
|
price: float = Field(..., gt=0)
|
|
chain_id: str = Field(..., regex="^(ait-devnet|ait-testnet)$")
|
|
user_address: str = Field(..., min_length=1)
|
|
|
|
class CrossChainSwapRequest(BaseModel):
|
|
from_chain: str = Field(..., regex="^(ait-devnet|ait-testnet)$")
|
|
to_chain: str = Field(..., regex="^(ait-devnet|ait-testnet)$")
|
|
from_token: str = Field(..., min_length=1)
|
|
to_token: str = Field(..., min_length=1)
|
|
amount: float = Field(..., gt=0)
|
|
min_amount: float = Field(..., gt=0)
|
|
user_address: str = Field(..., min_length=1)
|
|
slippage_tolerance: float = Field(default=0.01, ge=0, le=0.1)
|
|
|
|
class BridgeRequest(BaseModel):
|
|
source_chain: str = Field(..., regex="^(ait-devnet|ait-testnet)$")
|
|
target_chain: str = Field(..., regex="^(ait-devnet|ait-testnet)$")
|
|
token: str = Field(..., min_length=1)
|
|
amount: float = Field(..., gt=0)
|
|
recipient_address: str = Field(..., min_length=1)
|
|
|
|
# Database functions
|
|
def get_db_connection():
|
|
"""Get database connection"""
|
|
conn = sqlite3.connect(DB_PATH)
|
|
conn.row_factory = sqlite3.Row
|
|
return conn
|
|
|
|
def init_database():
|
|
"""Initialize complete cross-chain database"""
|
|
try:
|
|
conn = get_db_connection()
|
|
cursor = conn.cursor()
|
|
|
|
# Chains table
|
|
cursor.execute('''
|
|
CREATE TABLE IF NOT EXISTS chains (
|
|
chain_id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
status TEXT NOT NULL CHECK(status IN ('active', 'inactive', 'maintenance')),
|
|
blockchain_url TEXT,
|
|
token_symbol TEXT,
|
|
bridge_contract TEXT,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
)
|
|
''')
|
|
|
|
# Orders table with chain support
|
|
cursor.execute('''
|
|
CREATE TABLE IF NOT EXISTS orders (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
order_type TEXT NOT NULL CHECK(order_type IN ('BUY', 'SELL')),
|
|
amount REAL NOT NULL,
|
|
price REAL NOT NULL,
|
|
total REAL NOT NULL,
|
|
filled REAL DEFAULT 0,
|
|
remaining REAL NOT NULL,
|
|
status TEXT DEFAULT 'open' CHECK(status IN ('open', 'filled', 'cancelled')),
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
user_address TEXT,
|
|
tx_hash TEXT,
|
|
chain_id TEXT NOT NULL DEFAULT 'ait-devnet',
|
|
blockchain_tx_hash TEXT,
|
|
chain_status TEXT DEFAULT 'pending' CHECK(chain_status IN ('pending', 'confirmed', 'failed'))
|
|
)
|
|
''')
|
|
|
|
# Trades table with chain support
|
|
cursor.execute('''
|
|
CREATE TABLE IF NOT EXISTS trades (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
buy_order_id INTEGER,
|
|
sell_order_id INTEGER,
|
|
amount REAL NOT NULL,
|
|
price REAL NOT NULL,
|
|
total REAL NOT NULL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
chain_id TEXT NOT NULL DEFAULT 'ait-devnet',
|
|
blockchain_tx_hash TEXT,
|
|
chain_status TEXT DEFAULT 'pending' CHECK(chain_status IN ('pending', 'confirmed', 'failed'))
|
|
)
|
|
''')
|
|
|
|
# Cross-chain swaps table
|
|
cursor.execute('''
|
|
CREATE TABLE IF NOT EXISTS cross_chain_swaps (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
swap_id TEXT UNIQUE NOT NULL,
|
|
from_chain TEXT NOT NULL,
|
|
to_chain TEXT NOT NULL,
|
|
from_token TEXT NOT NULL,
|
|
to_token TEXT NOT NULL,
|
|
amount REAL NOT NULL,
|
|
min_amount REAL NOT NULL,
|
|
expected_amount REAL NOT NULL,
|
|
actual_amount REAL DEFAULT NULL,
|
|
user_address TEXT NOT NULL,
|
|
status TEXT DEFAULT 'pending' CHECK(status IN ('pending', 'executing', 'completed', 'failed', 'refunded')),
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
completed_at TIMESTAMP NULL,
|
|
from_tx_hash TEXT NULL,
|
|
to_tx_hash TEXT NULL,
|
|
bridge_fee REAL DEFAULT 0,
|
|
slippage REAL DEFAULT 0,
|
|
error_message TEXT NULL
|
|
)
|
|
''')
|
|
|
|
# Bridge transactions table
|
|
cursor.execute('''
|
|
CREATE TABLE IF NOT EXISTS bridge_transactions (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
bridge_id TEXT UNIQUE NOT NULL,
|
|
source_chain TEXT NOT NULL,
|
|
target_chain TEXT NOT NULL,
|
|
token TEXT NOT NULL,
|
|
amount REAL NOT NULL,
|
|
recipient_address TEXT NOT NULL,
|
|
status TEXT DEFAULT 'pending' CHECK(status IN ('pending', 'locked', 'transferred', 'completed', 'failed')),
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
completed_at TIMESTAMP NULL,
|
|
source_tx_hash TEXT NULL,
|
|
target_tx_hash TEXT NULL,
|
|
bridge_fee REAL DEFAULT 0,
|
|
lock_address TEXT NULL,
|
|
error_message TEXT NULL
|
|
)
|
|
''')
|
|
|
|
# Cross-chain liquidity pools
|
|
cursor.execute('''
|
|
CREATE TABLE IF NOT EXISTS cross_chain_pools (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
pool_id TEXT UNIQUE NOT NULL,
|
|
token_a TEXT NOT NULL,
|
|
token_b TEXT NOT NULL,
|
|
chain_a TEXT NOT NULL,
|
|
chain_b TEXT NOT NULL,
|
|
reserve_a REAL DEFAULT 0,
|
|
reserve_b REAL DEFAULT 0,
|
|
total_liquidity REAL DEFAULT 0,
|
|
apr REAL DEFAULT 0,
|
|
fee_rate REAL DEFAULT 0.003,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
)
|
|
''')
|
|
|
|
# Insert default chains
|
|
for chain_id, chain_info in SUPPORTED_CHAINS.items():
|
|
cursor.execute('''
|
|
INSERT OR REPLACE INTO chains
|
|
(chain_id, name, status, blockchain_url, token_symbol, bridge_contract)
|
|
VALUES (?, ?, ?, ?, ?, ?)
|
|
''', (chain_id, chain_info["name"], chain_info["status"],
|
|
chain_info["blockchain_url"], chain_info["token_symbol"],
|
|
chain_info.get("bridge_contract")))
|
|
|
|
# Create sample liquidity pool
|
|
cursor.execute('''
|
|
INSERT OR IGNORE INTO cross_chain_pools
|
|
(pool_id, token_a, token_b, chain_a, chain_b, reserve_a, reserve_b, total_liquidity)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
''', ("ait-devnet-ait-testnet-AITBC", "AITBC", "AITBC", "ait-devnet", "ait-testnet", 1000, 1000, 2000))
|
|
|
|
# Create indexes
|
|
cursor.execute('CREATE INDEX IF NOT EXISTS idx_orders_chain_id ON orders(chain_id)')
|
|
cursor.execute('CREATE INDEX IF NOT EXISTS idx_trades_chain_id ON trades(chain_id)')
|
|
cursor.execute('CREATE INDEX IF NOT EXISTS idx_swaps_user ON cross_chain_swaps(user_address)')
|
|
cursor.execute('CREATE INDEX IF NOT EXISTS idx_swaps_status ON cross_chain_swaps(status)')
|
|
cursor.execute('CREATE INDEX IF NOT EXISTS idx_bridge_status ON bridge_transactions(status)')
|
|
|
|
conn.commit()
|
|
conn.close()
|
|
return True
|
|
except Exception as e:
|
|
print(f"Database initialization error: {e}")
|
|
return False
|
|
|
|
# Cross-chain rate calculation
|
|
def get_cross_chain_rate(from_chain: str, to_chain: str, from_token: str, to_token: str) -> Optional[float]:
|
|
"""Get cross-chain exchange rate"""
|
|
try:
|
|
conn = get_db_connection()
|
|
cursor = conn.cursor()
|
|
|
|
# Check liquidity pool
|
|
cursor.execute('''
|
|
SELECT reserve_a, reserve_b FROM cross_chain_pools
|
|
WHERE ((chain_a = ? AND chain_b = ? AND token_a = ? AND token_b = ?) OR
|
|
(chain_a = ? AND chain_b = ? AND token_a = ? AND token_b = ?))
|
|
''', (from_chain, to_chain, from_token, to_token, to_chain, from_chain, to_token, from_token))
|
|
|
|
pool = cursor.fetchone()
|
|
if pool and pool["reserve_a"] > 0 and pool["reserve_b"] > 0:
|
|
return pool["reserve_b"] / pool["reserve_a"]
|
|
|
|
# Fallback to 1:1 for same tokens
|
|
if from_token == to_token:
|
|
return 1.0
|
|
|
|
return 1.0 # Default fallback rate
|
|
except Exception as e:
|
|
print(f"Rate calculation error: {e}")
|
|
return None
|
|
|
|
# Cross-chain swap execution
|
|
async def execute_cross_chain_swap(swap_request: CrossChainSwapRequest) -> Dict[str, Any]:
|
|
"""Execute cross-chain swap"""
|
|
try:
|
|
# Validate chains
|
|
if swap_request.from_chain == swap_request.to_chain:
|
|
raise HTTPException(status_code=400, detail="Cannot swap within same chain")
|
|
|
|
# Get exchange rate
|
|
rate = get_cross_chain_rate(swap_request.from_chain, swap_request.to_chain,
|
|
swap_request.from_token, swap_request.to_token)
|
|
if not rate:
|
|
raise HTTPException(status_code=400, detail="No exchange rate available")
|
|
|
|
# Calculate expected amount (including fees)
|
|
bridge_fee = swap_request.amount * 0.003 # 0.3% bridge fee
|
|
swap_fee = swap_request.amount * 0.001 # 0.1% swap fee
|
|
total_fees = bridge_fee + swap_fee
|
|
net_amount = swap_request.amount - total_fees
|
|
expected_amount = net_amount * rate
|
|
|
|
# Check slippage
|
|
if expected_amount < swap_request.min_amount:
|
|
raise HTTPException(status_code=400, detail="Insufficient output due to slippage")
|
|
|
|
# Create swap record
|
|
swap_id = str(uuid.uuid4())
|
|
conn = get_db_connection()
|
|
cursor = conn.cursor()
|
|
|
|
cursor.execute('''
|
|
INSERT INTO cross_chain_swaps
|
|
(swap_id, from_chain, to_chain, from_token, to_token, amount, min_amount,
|
|
expected_amount, user_address, bridge_fee, slippage)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
''', (swap_id, swap_request.from_chain, swap_request.to_chain, swap_request.from_token,
|
|
swap_request.to_token, swap_request.amount, swap_request.min_amount, expected_amount,
|
|
swap_request.user_address, bridge_fee, swap_request.slippage_tolerance))
|
|
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
# Process swap in background
|
|
asyncio.create_task(process_cross_chain_swap(swap_id))
|
|
|
|
return {
|
|
"success": True,
|
|
"swap_id": swap_id,
|
|
"from_chain": swap_request.from_chain,
|
|
"to_chain": swap_request.to_chain,
|
|
"from_token": swap_request.from_token,
|
|
"to_token": swap_request.to_token,
|
|
"amount": swap_request.amount,
|
|
"expected_amount": expected_amount,
|
|
"rate": rate,
|
|
"total_fees": total_fees,
|
|
"bridge_fee": bridge_fee,
|
|
"swap_fee": swap_fee,
|
|
"status": "pending"
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=f"Swap execution failed: {str(e)}")
|
|
|
|
async def process_cross_chain_swap(swap_id: str):
|
|
"""Process cross-chain swap"""
|
|
try:
|
|
conn = get_db_connection()
|
|
cursor = conn.cursor()
|
|
|
|
cursor.execute("SELECT * FROM cross_chain_swaps WHERE swap_id = ?", (swap_id,))
|
|
swap = cursor.fetchone()
|
|
|
|
if not swap:
|
|
return
|
|
|
|
# Update status
|
|
cursor.execute("UPDATE cross_chain_swaps SET status = 'executing' WHERE swap_id = ?", (swap_id,))
|
|
conn.commit()
|
|
|
|
# Simulate cross-chain execution
|
|
await asyncio.sleep(3) # Simulate blockchain processing
|
|
|
|
# Generate mock transaction hashes
|
|
from_tx_hash = f"0x{uuid.uuid4().hex[:64]}"
|
|
to_tx_hash = f"0x{uuid.uuid4().hex[:64]}"
|
|
|
|
# Complete swap
|
|
actual_amount = swap["expected_amount"] * 0.98 # Small slippage
|
|
|
|
cursor.execute('''
|
|
UPDATE cross_chain_swaps SET status = 'completed', actual_amount = ?,
|
|
from_tx_hash = ?, to_tx_hash = ?, completed_at = CURRENT_TIMESTAMP
|
|
WHERE swap_id = ?
|
|
''', (actual_amount, from_tx_hash, to_tx_hash, swap_id))
|
|
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
except Exception as e:
|
|
print(f"Cross-chain swap processing error: {e}")
|
|
|
|
# API Endpoints
|
|
@app.get("/health")
|
|
async def health_check():
|
|
"""Complete cross-chain health check"""
|
|
chain_status = {}
|
|
for chain_id, chain_info in SUPPORTED_CHAINS.items():
|
|
chain_status[chain_id] = {
|
|
"name": chain_info["name"],
|
|
"status": chain_info["status"],
|
|
"blockchain_url": chain_info["blockchain_url"],
|
|
"connected": False,
|
|
"bridge_contract": chain_info.get("bridge_contract")
|
|
}
|
|
|
|
if chain_info["status"] == "active" and chain_info["blockchain_url"]:
|
|
try:
|
|
async with httpx.AsyncClient() as client:
|
|
response = await client.get(f"{chain_info['blockchain_url']}/health", timeout=5.0)
|
|
chain_status[chain_id]["connected"] = response.status_code == 200
|
|
except:
|
|
pass
|
|
|
|
return {
|
|
"status": "ok",
|
|
"service": "complete-cross-chain-exchange",
|
|
"version": "3.0.0",
|
|
"supported_chains": list(SUPPORTED_CHAINS.keys()),
|
|
"chain_status": chain_status,
|
|
"cross_chain": True,
|
|
"features": ["trading", "swaps", "bridging", "liquidity_pools"],
|
|
"timestamp": datetime.now().isoformat()
|
|
}
|
|
|
|
@app.get("/api/v1/chains")
|
|
async def get_chains():
|
|
"""Get all supported chains"""
|
|
chains = []
|
|
for chain_id, chain_info in SUPPORTED_CHAINS.items():
|
|
chains.append({
|
|
"chain_id": chain_id,
|
|
"name": chain_info["name"],
|
|
"status": chain_info["status"],
|
|
"blockchain_url": chain_info["blockchain_url"],
|
|
"token_symbol": chain_info["token_symbol"],
|
|
"bridge_contract": chain_info.get("bridge_contract")
|
|
})
|
|
|
|
return {
|
|
"chains": chains,
|
|
"total_chains": len(chains),
|
|
"active_chains": len([c for c in chains if c["status"] == "active"])
|
|
}
|
|
|
|
@app.post("/api/v1/cross-chain/swap")
|
|
async def create_cross_chain_swap(swap_request: CrossChainSwapRequest):
|
|
"""Create cross-chain swap"""
|
|
return await execute_cross_chain_swap(swap_request)
|
|
|
|
@app.get("/api/v1/cross-chain/swap/{swap_id}")
|
|
async def get_cross_chain_swap(swap_id: str):
|
|
"""Get cross-chain swap details"""
|
|
try:
|
|
conn = get_db_connection()
|
|
cursor = conn.cursor()
|
|
|
|
cursor.execute("SELECT * FROM cross_chain_swaps WHERE swap_id = ?", (swap_id,))
|
|
swap = cursor.fetchone()
|
|
|
|
conn.close()
|
|
|
|
if not swap:
|
|
raise HTTPException(status_code=404, detail="Swap not found")
|
|
|
|
return dict(swap)
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=f"Failed to get swap: {str(e)}")
|
|
|
|
@app.get("/api/v1/cross-chain/swaps")
|
|
async def get_cross_chain_swaps(user_address: Optional[str] = None, status: Optional[str] = None):
|
|
"""Get cross-chain swaps"""
|
|
try:
|
|
conn = get_db_connection()
|
|
cursor = conn.cursor()
|
|
|
|
query = "SELECT * FROM cross_chain_swaps"
|
|
params = []
|
|
|
|
if user_address:
|
|
query += " WHERE user_address = ?"
|
|
params.append(user_address)
|
|
|
|
if status:
|
|
if user_address:
|
|
query += " AND status = ?"
|
|
else:
|
|
query += " WHERE status = ?"
|
|
params.append(status)
|
|
|
|
query += " ORDER BY created_at DESC"
|
|
|
|
cursor.execute(query, params)
|
|
swaps = [dict(row) for row in cursor.fetchall()]
|
|
|
|
conn.close()
|
|
|
|
return {
|
|
"swaps": swaps,
|
|
"total_swaps": len(swaps)
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=f"Failed to get swaps: {str(e)}")
|
|
|
|
@app.post("/api/v1/cross-chain/bridge")
|
|
async def create_bridge_transaction(bridge_request: BridgeRequest):
|
|
"""Create bridge transaction"""
|
|
try:
|
|
if bridge_request.source_chain == bridge_request.target_chain:
|
|
raise HTTPException(status_code=400, detail="Cannot bridge to same chain")
|
|
|
|
bridge_id = str(uuid.uuid4())
|
|
bridge_fee = bridge_request.amount * 0.001 # 0.1% bridge fee
|
|
|
|
conn = get_db_connection()
|
|
cursor = conn.cursor()
|
|
|
|
cursor.execute('''
|
|
INSERT INTO bridge_transactions
|
|
(bridge_id, source_chain, target_chain, token, amount, recipient_address, bridge_fee)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
''', (bridge_id, bridge_request.source_chain, bridge_request.target_chain,
|
|
bridge_request.token, bridge_request.amount, bridge_request.recipient_address, bridge_fee))
|
|
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
# Process bridge in background
|
|
asyncio.create_task(process_bridge_transaction(bridge_id))
|
|
|
|
return {
|
|
"success": True,
|
|
"bridge_id": bridge_id,
|
|
"source_chain": bridge_request.source_chain,
|
|
"target_chain": bridge_request.target_chain,
|
|
"token": bridge_request.token,
|
|
"amount": bridge_request.amount,
|
|
"bridge_fee": bridge_fee,
|
|
"status": "pending"
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=f"Bridge creation failed: {str(e)}")
|
|
|
|
async def process_bridge_transaction(bridge_id: str):
|
|
"""Process bridge transaction"""
|
|
try:
|
|
conn = get_db_connection()
|
|
cursor = conn.cursor()
|
|
|
|
cursor.execute("SELECT * FROM bridge_transactions WHERE bridge_id = ?", (bridge_id,))
|
|
bridge = cursor.fetchone()
|
|
|
|
if not bridge:
|
|
return
|
|
|
|
# Update status
|
|
cursor.execute("UPDATE bridge_transactions SET status = 'locked' WHERE bridge_id = ?", (bridge_id,))
|
|
conn.commit()
|
|
|
|
# Simulate bridge processing
|
|
await asyncio.sleep(2)
|
|
|
|
# Generate mock transaction hashes
|
|
source_tx_hash = f"0x{uuid.uuid4().hex[:64]}"
|
|
target_tx_hash = f"0x{uuid.uuid4().hex[:64]}"
|
|
|
|
# Complete bridge
|
|
cursor.execute('''
|
|
UPDATE bridge_transactions SET status = 'completed',
|
|
source_tx_hash = ?, target_tx_hash = ?, completed_at = CURRENT_TIMESTAMP
|
|
WHERE bridge_id = ?
|
|
''', (source_tx_hash, target_tx_hash, bridge_id))
|
|
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
except Exception as e:
|
|
print(f"Bridge processing error: {e}")
|
|
|
|
@app.get("/api/v1/cross-chain/bridge/{bridge_id}")
|
|
async def get_bridge_transaction(bridge_id: str):
|
|
"""Get bridge transaction details"""
|
|
try:
|
|
conn = get_db_connection()
|
|
cursor = conn.cursor()
|
|
|
|
cursor.execute("SELECT * FROM bridge_transactions WHERE bridge_id = ?", (bridge_id,))
|
|
bridge = cursor.fetchone()
|
|
|
|
conn.close()
|
|
|
|
if not bridge:
|
|
raise HTTPException(status_code=404, detail="Bridge transaction not found")
|
|
|
|
return dict(bridge)
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=f"Failed to get bridge: {str(e)}")
|
|
|
|
@app.get("/api/v1/cross-chain/rates")
|
|
async def get_cross_chain_rates():
|
|
"""Get cross-chain exchange rates"""
|
|
rates = {}
|
|
|
|
for from_chain in SUPPORTED_CHAINS:
|
|
for to_chain in SUPPORTED_CHAINS:
|
|
if from_chain != to_chain:
|
|
pair_key = f"{from_chain}-{to_chain}"
|
|
rate = get_cross_chain_rate(from_chain, to_chain, "AITBC", "AITBC")
|
|
if rate:
|
|
rates[pair_key] = rate
|
|
|
|
return {
|
|
"rates": rates,
|
|
"timestamp": datetime.now().isoformat()
|
|
}
|
|
|
|
@app.get("/api/v1/cross-chain/pools")
|
|
async def get_cross_chain_pools():
|
|
"""Get cross-chain liquidity pools"""
|
|
try:
|
|
conn = get_db_connection()
|
|
cursor = conn.cursor()
|
|
|
|
cursor.execute("SELECT * FROM cross_chain_pools ORDER BY total_liquidity DESC")
|
|
pools = [dict(row) for row in cursor.fetchall()]
|
|
|
|
conn.close()
|
|
|
|
return {
|
|
"pools": pools,
|
|
"total_pools": len(pools)
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=f"Failed to get pools: {str(e)}")
|
|
|
|
@app.get("/api/v1/cross-chain/stats")
|
|
async def get_cross_chain_stats():
|
|
"""Get cross-chain trading statistics"""
|
|
try:
|
|
conn = get_db_connection()
|
|
cursor = conn.cursor()
|
|
|
|
# Swap stats
|
|
cursor.execute('''
|
|
SELECT status, COUNT(*) as count, SUM(amount) as volume
|
|
FROM cross_chain_swaps
|
|
GROUP BY status
|
|
''')
|
|
swap_stats = [dict(row) for row in cursor.fetchall()]
|
|
|
|
# Bridge stats
|
|
cursor.execute('''
|
|
SELECT status, COUNT(*) as count, SUM(amount) as volume
|
|
FROM bridge_transactions
|
|
GROUP BY status
|
|
''')
|
|
bridge_stats = [dict(row) for row in cursor.fetchall()]
|
|
|
|
# Total volume
|
|
cursor.execute("SELECT SUM(amount) FROM cross_chain_swaps WHERE status = 'completed'")
|
|
total_volume = cursor.fetchone()[0] or 0
|
|
|
|
conn.close()
|
|
|
|
return {
|
|
"swap_stats": swap_stats,
|
|
"bridge_stats": bridge_stats,
|
|
"total_volume": total_volume,
|
|
"supported_chains": list(SUPPORTED_CHAINS.keys()),
|
|
"timestamp": datetime.now().isoformat()
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=f"Failed to get stats: {str(e)}")
|
|
|
|
if __name__ == "__main__":
|
|
# Initialize database
|
|
if init_database():
|
|
print("✅ Complete cross-chain database initialized")
|
|
else:
|
|
print("❌ Database initialization failed")
|
|
|
|
# Run the server
|
|
uvicorn.run(app, host="0.0.0.0", port=8001)
|