refactor: consolidate blockchain explorer into single app and update backup ignore patterns
- 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
This commit is contained in:
614
apps/exchange/cross_chain_exchange.py
Executable file
614
apps/exchange/cross_chain_exchange.py
Executable file
@@ -0,0 +1,614 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Cross-Chain Trading Extension for Multi-Chain Exchange
|
||||
Adds cross-chain trading, bridging, and swap functionality
|
||||
"""
|
||||
|
||||
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 uuid
|
||||
import hashlib
|
||||
|
||||
# Import the base multi-chain exchange
|
||||
from multichain_exchange_api import app, get_db_connection, SUPPORTED_CHAINS
|
||||
|
||||
# Cross-Chain Models
|
||||
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)
|
||||
|
||||
class CrossChainOrder(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)$")
|
||||
cross_chain: bool = Field(default=True)
|
||||
target_chain: Optional[str] = None
|
||||
user_address: str = Field(..., min_length=1)
|
||||
|
||||
# Cross-Chain Database Functions
|
||||
def init_cross_chain_tables():
|
||||
"""Initialize cross-chain trading tables"""
|
||||
try:
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 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
|
||||
)
|
||||
''')
|
||||
|
||||
# Create indexes
|
||||
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_swaps_chains ON cross_chain_swaps(from_chain, to_chain)')
|
||||
cursor.execute('CREATE INDEX IF NOT EXISTS idx_bridge_status ON bridge_transactions(status)')
|
||||
cursor.execute('CREATE INDEX IF NOT EXISTS idx_bridge_chains ON bridge_transactions(source_chain, target_chain)')
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Cross-chain database initialization error: {e}")
|
||||
return False
|
||||
|
||||
# Cross-Chain Liquidity Management
|
||||
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 if there's a liquidity pool for this pair
|
||||
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:
|
||||
reserve_a, reserve_b = pool
|
||||
if from_chain == SUPPORTED_CHAINS[from_chain] and reserve_a > 0 and reserve_b > 0:
|
||||
return reserve_b / reserve_a
|
||||
|
||||
# Fallback to 1:1 rate for same tokens
|
||||
if from_token == to_token:
|
||||
return 1.0
|
||||
|
||||
# Get rates from individual chains
|
||||
rate_a = get_chain_token_price(from_chain, from_token)
|
||||
rate_b = get_chain_token_price(to_chain, to_token)
|
||||
|
||||
if rate_a and rate_b:
|
||||
return rate_b / rate_a
|
||||
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f"Rate calculation error: {e}")
|
||||
return None
|
||||
|
||||
def get_chain_token_price(chain_id: str, token: str) -> Optional[float]:
|
||||
"""Get token price on specific chain"""
|
||||
try:
|
||||
chain_info = SUPPORTED_CHAINS.get(chain_id)
|
||||
if not chain_info or chain_info["status"] != "active":
|
||||
return None
|
||||
|
||||
# Mock price for now - in production, this would call the chain's price oracle
|
||||
if token == "AITBC":
|
||||
return 1.0
|
||||
elif token == "USDC":
|
||||
return 1.0
|
||||
else:
|
||||
return 0.5 # Default fallback
|
||||
except:
|
||||
return None
|
||||
|
||||
# Cross-Chain Swap Functions
|
||||
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")
|
||||
|
||||
if swap_request.from_chain not in SUPPORTED_CHAINS or swap_request.to_chain not in SUPPORTED_CHAINS:
|
||||
raise HTTPException(status_code=400, detail="Unsupported 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
|
||||
expected_amount = swap_request.amount * rate * (1 - 0.003) # 0.3% fee
|
||||
|
||||
# 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)
|
||||
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))
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
# Execute 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,
|
||||
"amount": swap_request.amount,
|
||||
"expected_amount": expected_amount,
|
||||
"rate": rate,
|
||||
"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 in background"""
|
||||
try:
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Get swap details
|
||||
cursor.execute("SELECT * FROM cross_chain_swaps WHERE swap_id = ?", (swap_id,))
|
||||
swap = cursor.fetchone()
|
||||
|
||||
if not swap:
|
||||
return
|
||||
|
||||
# Update status to executing
|
||||
cursor.execute("UPDATE cross_chain_swaps SET status = 'executing' WHERE swap_id = ?", (swap_id,))
|
||||
conn.commit()
|
||||
|
||||
# Step 1: Lock funds on source chain
|
||||
from_tx_hash = await lock_funds_on_chain(swap["from_chain"], swap["from_token"],
|
||||
swap["amount"], swap["user_address"])
|
||||
|
||||
if not from_tx_hash:
|
||||
cursor.execute('''
|
||||
UPDATE cross_chain_swaps SET status = 'failed', error_message = ?
|
||||
WHERE swap_id = ?
|
||||
''', ("Failed to lock source funds", swap_id))
|
||||
conn.commit()
|
||||
return
|
||||
|
||||
# Step 2: Transfer to target chain
|
||||
to_tx_hash = await transfer_to_target_chain(swap["to_chain"], swap["to_token"],
|
||||
swap["expected_amount"], swap["user_address"])
|
||||
|
||||
if not to_tx_hash:
|
||||
# Refund source chain
|
||||
await refund_source_chain(swap["from_chain"], from_tx_hash, swap["user_address"])
|
||||
cursor.execute('''
|
||||
UPDATE cross_chain_swaps SET status = 'refunded', error_message = ?,
|
||||
from_tx_hash = ? WHERE swap_id = ?
|
||||
''', ("Target transfer failed, refunded", from_tx_hash, swap_id))
|
||||
conn.commit()
|
||||
return
|
||||
|
||||
# Step 3: Complete swap
|
||||
actual_amount = await verify_target_transfer(swap["to_chain"], to_tx_hash)
|
||||
|
||||
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}")
|
||||
|
||||
async def lock_funds_on_chain(chain_id: str, token: str, amount: float, user_address: str) -> Optional[str]:
|
||||
"""Lock funds on source chain"""
|
||||
try:
|
||||
chain_info = SUPPORTED_CHAINS[chain_id]
|
||||
if chain_info["status"] != "active":
|
||||
return None
|
||||
|
||||
# Mock implementation - in production, this would call the chain's lock function
|
||||
lock_tx_hash = f"lock_{uuid.uuid4().hex[:8]}"
|
||||
|
||||
# Simulate blockchain call
|
||||
await asyncio.sleep(1)
|
||||
|
||||
return lock_tx_hash
|
||||
except:
|
||||
return None
|
||||
|
||||
async def transfer_to_target_chain(chain_id: str, token: str, amount: float, user_address: str) -> Optional[str]:
|
||||
"""Transfer tokens to target chain"""
|
||||
try:
|
||||
chain_info = SUPPORTED_CHAINS[chain_id]
|
||||
if chain_info["status"] != "active":
|
||||
return None
|
||||
|
||||
# Mock implementation - in production, this would call the chain's mint/transfer function
|
||||
transfer_tx_hash = f"transfer_{uuid.uuid4().hex[:8]}"
|
||||
|
||||
# Simulate blockchain call
|
||||
await asyncio.sleep(2)
|
||||
|
||||
return transfer_tx_hash
|
||||
except:
|
||||
return None
|
||||
|
||||
async def refund_source_chain(chain_id: str, lock_tx_hash: str, user_address: str) -> bool:
|
||||
"""Refund locked funds on source chain"""
|
||||
try:
|
||||
chain_info = SUPPORTED_CHAINS[chain_id]
|
||||
if chain_info["status"] != "active":
|
||||
return False
|
||||
|
||||
# Mock implementation - in production, this would call the chain's refund function
|
||||
await asyncio.sleep(1)
|
||||
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
async def verify_target_transfer(chain_id: str, tx_hash: str) -> Optional[float]:
|
||||
"""Verify transfer on target chain"""
|
||||
try:
|
||||
chain_info = SUPPORTED_CHAINS[chain_id]
|
||||
if chain_info["status"] != "active":
|
||||
return None
|
||||
|
||||
# Mock implementation - in production, this would verify the actual transaction
|
||||
await asyncio.sleep(1)
|
||||
|
||||
return 100.0 # Mock amount
|
||||
except:
|
||||
return None
|
||||
|
||||
# Cross-Chain API Endpoints
|
||||
@app.post("/api/v1/cross-chain/swap")
|
||||
async def create_cross_chain_swap(swap_request: CrossChainSwapRequest, background_tasks: BackgroundTasks):
|
||||
"""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, background_tasks: BackgroundTasks):
|
||||
"""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,
|
||||
"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 in background"""
|
||||
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()
|
||||
|
||||
# Lock on source chain
|
||||
source_tx_hash = await lock_funds_on_chain(bridge["source_chain"], bridge["token"],
|
||||
bridge["amount"], bridge["recipient_address"])
|
||||
|
||||
if source_tx_hash:
|
||||
# Transfer to target chain
|
||||
target_tx_hash = await transfer_to_target_chain(bridge["target_chain"], bridge["token"],
|
||||
bridge["amount"], bridge["recipient_address"])
|
||||
|
||||
if target_tx_hash:
|
||||
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))
|
||||
else:
|
||||
cursor.execute('''
|
||||
UPDATE bridge_transactions SET status = 'failed', error_message = ?
|
||||
WHERE bridge_id = ?
|
||||
''', ("Target transfer failed", bridge_id))
|
||||
else:
|
||||
cursor.execute('''
|
||||
UPDATE bridge_transactions SET status = 'failed', error_message = ?
|
||||
WHERE bridge_id = ?
|
||||
''', ("Source lock failed", 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)}")
|
||||
|
||||
# Initialize cross-chain tables
|
||||
if __name__ == "__main__":
|
||||
init_cross_chain_tables()
|
||||
print("✅ Cross-chain trading extensions initialized")
|
||||
Reference in New Issue
Block a user