feat(coordinator-api): integrate dynamic pricing engine with GPU marketplace and add agent identity router

- Add DynamicPricingEngine and MarketDataCollector dependencies to GPU marketplace endpoints
- Implement dynamic pricing calculation for GPU registration with market_balance strategy
- Calculate real-time dynamic prices at booking time with confidence scores and pricing factors
- Enhance /marketplace/pricing/{model} endpoint with comprehensive dynamic pricing analysis
  - Add static vs dynamic price
This commit is contained in:
oib
2026-02-28 22:57:10 +01:00
parent 85ae21a568
commit 0e6c9eda72
83 changed files with 30189 additions and 134 deletions

View File

@@ -0,0 +1,498 @@
"""
Tests for Agent Identity SDK
Unit tests for the Agent Identity client and models
"""
import pytest
import asyncio
from unittest.mock import AsyncMock, patch
from datetime import datetime
from app.agent_identity.sdk.client import AgentIdentityClient
from app.agent_identity.sdk.models import (
AgentIdentity, CrossChainMapping, AgentWallet,
IdentityStatus, VerificationType, ChainType,
CreateIdentityRequest, TransactionRequest
)
from app.agent_identity.sdk.exceptions import (
AgentIdentityError, ValidationError, NetworkError,
AuthenticationError, RateLimitError
)
class TestAgentIdentityClient:
"""Test cases for AgentIdentityClient"""
@pytest.fixture
def client(self):
"""Create a test client"""
return AgentIdentityClient(
base_url="http://test:8000/v1",
api_key="test_key",
timeout=10
)
@pytest.fixture
def mock_session(self):
"""Create a mock HTTP session"""
session = AsyncMock()
session.closed = False
return session
@pytest.mark.asyncio
async def test_client_initialization(self, client):
"""Test client initialization"""
assert client.base_url == "http://test:8000/v1"
assert client.api_key == "test_key"
assert client.timeout.total == 10
assert client.max_retries == 3
assert client.session is None
@pytest.mark.asyncio
async def test_context_manager(self, client):
"""Test async context manager"""
async with client as c:
assert c is client
assert c.session is not None
assert not c.session.closed
# Session should be closed after context
assert client.session.closed
@pytest.mark.asyncio
async def test_create_identity_success(self, client, mock_session):
"""Test successful identity creation"""
# Mock the session
with patch.object(client, 'session', mock_session):
# Mock response
mock_response = AsyncMock()
mock_response.status = 201
mock_response.json = AsyncMock(return_value={
'identity_id': 'identity_123',
'agent_id': 'agent_456',
'owner_address': '0x123...',
'display_name': 'Test Agent',
'supported_chains': [1, 137],
'primary_chain': 1,
'registration_result': {'total_mappings': 2},
'wallet_results': [{'chain_id': 1, 'success': True}],
'created_at': '2024-01-01T00:00:00'
})
mock_session.request.return_value.__aenter__.return_value = mock_response
# Create identity
result = await client.create_identity(
owner_address='0x123...',
chains=[1, 137],
display_name='Test Agent',
description='Test description'
)
# Verify result
assert result.identity_id == 'identity_123'
assert result.agent_id == 'agent_456'
assert result.display_name == 'Test Agent'
assert result.supported_chains == [1, 137]
assert result.created_at == '2024-01-01T00:00:00'
# Verify request was made correctly
mock_session.request.assert_called_once()
call_args = mock_session.request.call_args
assert call_args[0][0] == 'POST'
assert '/agent-identity/identities' in call_args[0][1]
@pytest.mark.asyncio
async def test_create_identity_validation_error(self, client, mock_session):
"""Test identity creation with validation error"""
with patch.object(client, 'session', mock_session):
# Mock 400 response
mock_response = AsyncMock()
mock_response.status = 400
mock_response.json = AsyncMock(return_value={'detail': 'Invalid owner address'})
mock_session.request.return_value.__aenter__.return_value = mock_response
# Should raise ValidationError
with pytest.raises(ValidationError) as exc_info:
await client.create_identity(
owner_address='invalid',
chains=[1]
)
assert 'Invalid owner address' in str(exc_info.value)
@pytest.mark.asyncio
async def test_get_identity_success(self, client, mock_session):
"""Test successful identity retrieval"""
with patch.object(client, 'session', mock_session):
# Mock response
mock_response = AsyncMock()
mock_response.status = 200
mock_response.json = AsyncMock(return_value={
'identity': {
'id': 'identity_123',
'agent_id': 'agent_456',
'owner_address': '0x123...',
'display_name': 'Test Agent',
'status': 'active',
'reputation_score': 85.5
},
'cross_chain': {
'total_mappings': 2,
'verified_mappings': 2
},
'wallets': {
'total_wallets': 2,
'total_balance': 1.5
}
})
mock_session.request.return_value.__aenter__.return_value = mock_response
# Get identity
result = await client.get_identity('agent_456')
# Verify result
assert result['identity']['agent_id'] == 'agent_456'
assert result['identity']['display_name'] == 'Test Agent'
assert result['cross_chain']['total_mappings'] == 2
assert result['wallets']['total_balance'] == 1.5
@pytest.mark.asyncio
async def test_verify_identity_success(self, client, mock_session):
"""Test successful identity verification"""
with patch.object(client, 'session', mock_session):
# Mock response
mock_response = AsyncMock()
mock_response.status = 200
mock_response.json = AsyncMock(return_value={
'verification_id': 'verify_123',
'agent_id': 'agent_456',
'chain_id': 1,
'verification_type': 'basic',
'verified': True,
'timestamp': '2024-01-01T00:00:00'
})
mock_session.request.return_value.__aenter__.return_value = mock_response
# Verify identity
result = await client.verify_identity(
agent_id='agent_456',
chain_id=1,
verifier_address='0x789...',
proof_hash='abc123',
proof_data={'test': 'data'}
)
# Verify result
assert result.verification_id == 'verify_123'
assert result.agent_id == 'agent_456'
assert result.verified == True
assert result.verification_type == VerificationType.BASIC
@pytest.mark.asyncio
async def test_execute_transaction_success(self, client, mock_session):
"""Test successful transaction execution"""
with patch.object(client, 'session', mock_session):
# Mock response
mock_response = AsyncMock()
mock_response.status = 200
mock_response.json = AsyncMock(return_value={
'transaction_hash': '0xabc...',
'from_address': '0x123...',
'to_address': '0x456...',
'amount': '0.1',
'gas_used': '21000',
'gas_price': '20000000000',
'status': 'success',
'block_number': 12345,
'timestamp': '2024-01-01T00:00:00'
})
mock_session.request.return_value.__aenter__.return_value = mock_response
# Execute transaction
result = await client.execute_transaction(
agent_id='agent_456',
chain_id=1,
to_address='0x456...',
amount=0.1
)
# Verify result
assert result.transaction_hash == '0xabc...'
assert result.from_address == '0x123...'
assert result.to_address == '0x456...'
assert result.amount == '0.1'
assert result.status == 'success'
@pytest.mark.asyncio
async def test_search_identities_success(self, client, mock_session):
"""Test successful identity search"""
with patch.object(client, 'session', mock_session):
# Mock response
mock_response = AsyncMock()
mock_response.status = 200
mock_response.json = AsyncMock(return_value={
'results': [
{
'identity_id': 'identity_123',
'agent_id': 'agent_456',
'display_name': 'Test Agent',
'reputation_score': 85.5
}
],
'total_count': 1,
'query': 'test',
'filters': {},
'pagination': {'limit': 50, 'offset': 0}
})
mock_session.request.return_value.__aenter__.return_value = mock_response
# Search identities
result = await client.search_identities(
query='test',
limit=50,
offset=0
)
# Verify result
assert result.total_count == 1
assert len(result.results) == 1
assert result.results[0]['display_name'] == 'Test Agent'
assert result.query == 'test'
@pytest.mark.asyncio
async def test_network_error_retry(self, client, mock_session):
"""Test retry logic for network errors"""
with patch.object(client, 'session', mock_session):
# Mock network error first two times, then success
mock_session.request.side_effect = [
aiohttp.ClientError("Network error"),
aiohttp.ClientError("Network error"),
AsyncMock(status=200, json=AsyncMock(return_value={'test': 'success'}).__aenter__.return_value)
]
# Should succeed after retries
result = await client._request('GET', '/test')
assert result['test'] == 'success'
# Should have retried 3 times total
assert mock_session.request.call_count == 3
@pytest.mark.asyncio
async def test_authentication_error(self, client, mock_session):
"""Test authentication error handling"""
with patch.object(client, 'session', mock_session):
# Mock 401 response
mock_response = AsyncMock()
mock_response.status = 401
mock_session.request.return_value.__aenter__.return_value = mock_response
# Should raise AuthenticationError
with pytest.raises(AuthenticationError):
await client._request('GET', '/test')
@pytest.mark.asyncio
async def test_rate_limit_error(self, client, mock_session):
"""Test rate limit error handling"""
with patch.object(client, 'session', mock_session):
# Mock 429 response
mock_response = AsyncMock()
mock_response.status = 429
mock_session.request.return_value.__aenter__.return_value = mock_response
# Should raise RateLimitError
with pytest.raises(RateLimitError):
await client._request('GET', '/test')
class TestModels:
"""Test cases for SDK models"""
def test_agent_identity_model(self):
"""Test AgentIdentity model"""
identity = AgentIdentity(
id='identity_123',
agent_id='agent_456',
owner_address='0x123...',
display_name='Test Agent',
description='Test description',
avatar_url='https://example.com/avatar.png',
status=IdentityStatus.ACTIVE,
verification_level=VerificationType.BASIC,
is_verified=True,
verified_at=datetime.utcnow(),
supported_chains=['1', '137'],
primary_chain=1,
reputation_score=85.5,
total_transactions=100,
successful_transactions=95,
success_rate=0.95,
created_at=datetime.utcnow(),
updated_at=datetime.utcnow(),
last_activity=datetime.utcnow(),
metadata={'key': 'value'},
tags=['test', 'agent']
)
assert identity.id == 'identity_123'
assert identity.agent_id == 'agent_456'
assert identity.status == IdentityStatus.ACTIVE
assert identity.verification_level == VerificationType.BASIC
assert identity.success_rate == 0.95
assert 'test' in identity.tags
def test_cross_chain_mapping_model(self):
"""Test CrossChainMapping model"""
mapping = CrossChainMapping(
id='mapping_123',
agent_id='agent_456',
chain_id=1,
chain_type=ChainType.ETHEREUM,
chain_address='0x123...',
is_verified=True,
verified_at=datetime.utcnow(),
wallet_address='0x456...',
wallet_type='agent-wallet',
chain_metadata={'test': 'data'},
last_transaction=datetime.utcnow(),
transaction_count=10,
created_at=datetime.utcnow(),
updated_at=datetime.utcnow()
)
assert mapping.id == 'mapping_123'
assert mapping.chain_id == 1
assert mapping.chain_type == ChainType.ETHEREUM
assert mapping.is_verified is True
assert mapping.transaction_count == 10
def test_agent_wallet_model(self):
"""Test AgentWallet model"""
wallet = AgentWallet(
id='wallet_123',
agent_id='agent_456',
chain_id=1,
chain_address='0x123...',
wallet_type='agent-wallet',
contract_address='0x789...',
balance=1.5,
spending_limit=10.0,
total_spent=0.5,
is_active=True,
permissions=['send', 'receive'],
requires_multisig=False,
multisig_threshold=1,
multisig_signers=['0x123...'],
last_transaction=datetime.utcnow(),
transaction_count=5,
created_at=datetime.utcnow(),
updated_at=datetime.utcnow()
)
assert wallet.id == 'wallet_123'
assert wallet.balance == 1.5
assert wallet.spending_limit == 10.0
assert wallet.is_active is True
assert 'send' in wallet.permissions
assert wallet.requires_multisig is False
class TestConvenienceFunctions:
"""Test cases for convenience functions"""
@pytest.mark.asyncio
async def test_create_identity_with_wallets_success(self):
"""Test create_identity_with_wallets convenience function"""
from app.agent_identity.sdk.client import create_identity_with_wallets
# Mock client
client = AsyncMock(spec=AgentIdentityClient)
# Mock successful response
client.create_identity.return_value = AsyncMock(
identity_id='identity_123',
agent_id='agent_456',
wallet_results=[
{'chain_id': 1, 'success': True},
{'chain_id': 137, 'success': True}
]
)
# Call function
result = await create_identity_with_wallets(
client=client,
owner_address='0x123...',
chains=[1, 137],
display_name='Test Agent'
)
# Verify result
assert result.identity_id == 'identity_123'
assert len(result.wallet_results) == 2
assert all(w['success'] for w in result.wallet_results)
@pytest.mark.asyncio
async def test_verify_identity_on_all_chains_success(self):
"""Test verify_identity_on_all_chains convenience function"""
from app.agent_identity.sdk.client import verify_identity_on_all_chains
# Mock client
client = AsyncMock(spec=AgentIdentityClient)
# Mock mappings
mappings = [
AsyncMock(chain_id=1, chain_type=ChainType.ETHEREUM, chain_address='0x123...'),
AsyncMock(chain_id=137, chain_type=ChainType.POLYGON, chain_address='0x456...')
]
client.get_cross_chain_mappings.return_value = mappings
client.verify_identity.return_value = AsyncMock(
verification_id='verify_123',
verified=True
)
# Call function
results = await verify_identity_on_all_chains(
client=client,
agent_id='agent_456',
verifier_address='0x789...',
proof_data_template={'test': 'data'}
)
# Verify results
assert len(results) == 2
assert all(r.verified for r in results)
assert client.verify_identity.call_count == 2
# Integration tests would go here in a real implementation
# These would test the actual API endpoints
class TestIntegration:
"""Integration tests for the SDK"""
@pytest.mark.asyncio
async def test_full_identity_workflow(self):
"""Test complete identity creation and management workflow"""
# This would be an integration test that:
# 1. Creates an identity
# 2. Registers cross-chain mappings
# 3. Creates wallets
# 4. Verifies identities
# 5. Executes transactions
# 6. Searches for identities
# 7. Exports/imports identity data
# Skip for now as it requires a running API
pytest.skip("Integration test requires running API")
if __name__ == '__main__':
pytest.main([__file__])

View File

@@ -0,0 +1,603 @@
"""
Trading Protocols Test Suite
Comprehensive tests for agent portfolio management, AMM, and cross-chain bridge services.
"""
import pytest
from datetime import datetime, timedelta
from decimal import Decimal
from unittest.mock import AsyncMock, MagicMock, patch
from sqlmodel import Session, create_engine, SQLModel
from sqlmodel.pool import StaticPool
from ..services.agent_portfolio_manager import AgentPortfolioManager
from ..services.amm_service import AMMService
from ..services.cross_chain_bridge import CrossChainBridgeService
from ..domain.agent_portfolio import (
AgentPortfolio, PortfolioStrategy, StrategyType, TradeStatus
)
from ..domain.amm import (
LiquidityPool, SwapTransaction, PoolStatus, SwapStatus
)
from ..domain.cross_chain_bridge import (
BridgeRequest, BridgeRequestStatus, ChainType
)
from ..schemas.portfolio import PortfolioCreate, TradeRequest
from ..schemas.amm import PoolCreate, SwapRequest
from ..schemas.cross_chain_bridge import BridgeCreateRequest
@pytest.fixture
def test_db():
"""Create test database"""
engine = create_engine(
"sqlite:///:memory:",
connect_args={"check_same_thread": False},
poolclass=StaticPool,
)
SQLModel.metadata.create_all(engine)
session = Session(engine)
yield session
session.close()
@pytest.fixture
def mock_contract_service():
"""Mock contract service"""
service = AsyncMock()
service.create_portfolio.return_value = "12345"
service.execute_portfolio_trade.return_value = MagicMock(
buy_amount=100.0,
price=1.0,
transaction_hash="0x123"
)
service.create_amm_pool.return_value = 67890
service.add_liquidity.return_value = MagicMock(
liquidity_received=1000.0
)
service.execute_swap.return_value = MagicMock(
amount_out=95.0,
price=1.05,
fee_amount=0.5,
transaction_hash="0x456"
)
service.initiate_bridge.return_value = 11111
service.get_bridge_status.return_value = MagicMock(
status="pending"
)
return service
@pytest.fixture
def mock_price_service():
"""Mock price service"""
service = AsyncMock()
service.get_price.side_effect = lambda token: {
"AITBC": 1.0,
"USDC": 1.0,
"ETH": 2000.0,
"WBTC": 50000.0
}.get(token, 1.0)
service.get_market_conditions.return_value = MagicMock(
volatility=0.15,
trend="bullish"
)
return service
@pytest.fixture
def mock_risk_calculator():
"""Mock risk calculator"""
calculator = AsyncMock()
calculator.calculate_portfolio_risk.return_value = MagicMock(
volatility=0.12,
max_drawdown=0.08,
sharpe_ratio=1.5,
var_95=0.05,
overall_risk_score=35.0,
risk_level="medium"
)
calculator.calculate_trade_risk.return_value = 25.0
return calculator
@pytest.fixture
def mock_strategy_optimizer():
"""Mock strategy optimizer"""
optimizer = AsyncMock()
optimizer.calculate_optimal_allocations.return_value = {
"AITBC": 40.0,
"USDC": 30.0,
"ETH": 20.0,
"WBTC": 10.0
}
return optimizer
@pytest.fixture
def mock_volatility_calculator():
"""Mock volatility calculator"""
calculator = AsyncMock()
calculator.calculate_volatility.return_value = 0.15
return calculator
@pytest.fixture
def mock_zk_proof_service():
"""Mock ZK proof service"""
service = AsyncMock()
service.generate_proof.return_value = MagicMock(
proof="zk_proof_123"
)
return service
@pytest.fixture
def mock_merkle_tree_service():
"""Mock Merkle tree service"""
service = AsyncMock()
service.generate_proof.return_value = MagicMock(
proof_hash="merkle_hash_456"
)
service.verify_proof.return_value = True
return service
@pytest.fixture
def mock_bridge_monitor():
"""Mock bridge monitor"""
monitor = AsyncMock()
monitor.start_monitoring.return_value = None
monitor.stop_monitoring.return_value = None
return monitor
@pytest.fixture
def agent_portfolio_manager(
test_db, mock_contract_service, mock_price_service,
mock_risk_calculator, mock_strategy_optimizer
):
"""Create agent portfolio manager instance"""
return AgentPortfolioManager(
session=test_db,
contract_service=mock_contract_service,
price_service=mock_price_service,
risk_calculator=mock_risk_calculator,
strategy_optimizer=mock_strategy_optimizer
)
@pytest.fixture
def amm_service(
test_db, mock_contract_service, mock_price_service,
mock_volatility_calculator
):
"""Create AMM service instance"""
return AMMService(
session=test_db,
contract_service=mock_contract_service,
price_service=mock_price_service,
volatility_calculator=mock_volatility_calculator
)
@pytest.fixture
def cross_chain_bridge_service(
test_db, mock_contract_service, mock_zk_proof_service,
mock_merkle_tree_service, mock_bridge_monitor
):
"""Create cross-chain bridge service instance"""
return CrossChainBridgeService(
session=test_db,
contract_service=mock_contract_service,
zk_proof_service=mock_zk_proof_service,
merkle_tree_service=mock_merkle_tree_service,
bridge_monitor=mock_bridge_monitor
)
@pytest.fixture
def sample_strategy(test_db):
"""Create sample portfolio strategy"""
strategy = PortfolioStrategy(
name="Balanced Strategy",
strategy_type=StrategyType.BALANCED,
target_allocations={
"AITBC": 40.0,
"USDC": 30.0,
"ETH": 20.0,
"WBTC": 10.0
},
max_drawdown=15.0,
rebalance_frequency=86400,
is_active=True
)
test_db.add(strategy)
test_db.commit()
test_db.refresh(strategy)
return strategy
class TestAgentPortfolioManager:
"""Test cases for Agent Portfolio Manager"""
def test_create_portfolio_success(
self, agent_portfolio_manager, test_db, sample_strategy
):
"""Test successful portfolio creation"""
portfolio_data = PortfolioCreate(
strategy_id=sample_strategy.id,
initial_capital=10000.0,
risk_tolerance=50.0
)
agent_address = "0x1234567890123456789012345678901234567890"
result = agent_portfolio_manager.create_portfolio(portfolio_data, agent_address)
assert result.strategy_id == sample_strategy.id
assert result.initial_capital == 10000.0
assert result.risk_tolerance == 50.0
assert result.is_active is True
assert result.agent_address == agent_address
def test_create_portfolio_invalid_address(self, agent_portfolio_manager, sample_strategy):
"""Test portfolio creation with invalid address"""
portfolio_data = PortfolioCreate(
strategy_id=sample_strategy.id,
initial_capital=10000.0,
risk_tolerance=50.0
)
invalid_address = "invalid_address"
with pytest.raises(Exception) as exc_info:
agent_portfolio_manager.create_portfolio(portfolio_data, invalid_address)
assert "Invalid agent address" in str(exc_info.value)
def test_create_portfolio_already_exists(
self, agent_portfolio_manager, test_db, sample_strategy
):
"""Test portfolio creation when portfolio already exists"""
portfolio_data = PortfolioCreate(
strategy_id=sample_strategy.id,
initial_capital=10000.0,
risk_tolerance=50.0
)
agent_address = "0x1234567890123456789012345678901234567890"
# Create first portfolio
agent_portfolio_manager.create_portfolio(portfolio_data, agent_address)
# Try to create second portfolio
with pytest.raises(Exception) as exc_info:
agent_portfolio_manager.create_portfolio(portfolio_data, agent_address)
assert "Portfolio already exists" in str(exc_info.value)
def test_execute_trade_success(self, agent_portfolio_manager, test_db, sample_strategy):
"""Test successful trade execution"""
# Create portfolio first
portfolio_data = PortfolioCreate(
strategy_id=sample_strategy.id,
initial_capital=10000.0,
risk_tolerance=50.0
)
agent_address = "0x1234567890123456789012345678901234567890"
portfolio = agent_portfolio_manager.create_portfolio(portfolio_data, agent_address)
# Add some assets to portfolio
from ..domain.agent_portfolio import PortfolioAsset
asset = PortfolioAsset(
portfolio_id=portfolio.id,
token_symbol="AITBC",
token_address="0xaitbc",
balance=1000.0,
target_allocation=40.0,
current_allocation=40.0
)
test_db.add(asset)
test_db.commit()
# Execute trade
trade_request = TradeRequest(
sell_token="AITBC",
buy_token="USDC",
sell_amount=100.0,
min_buy_amount=95.0
)
result = agent_portfolio_manager.execute_trade(trade_request, agent_address)
assert result.sell_token == "AITBC"
assert result.buy_token == "USDC"
assert result.sell_amount == 100.0
assert result.status == TradeStatus.EXECUTED
def test_risk_assessment(self, agent_portfolio_manager, test_db, sample_strategy):
"""Test risk assessment"""
# Create portfolio first
portfolio_data = PortfolioCreate(
strategy_id=sample_strategy.id,
initial_capital=10000.0,
risk_tolerance=50.0
)
agent_address = "0x1234567890123456789012345678901234567890"
portfolio = agent_portfolio_manager.create_portfolio(portfolio_data, agent_address)
# Perform risk assessment
result = agent_portfolio_manager.risk_assessment(agent_address)
assert result.volatility == 0.12
assert result.max_drawdown == 0.08
assert result.sharpe_ratio == 1.5
assert result.var_95 == 0.05
assert result.overall_risk_score == 35.0
class TestAMMService:
"""Test cases for AMM Service"""
def test_create_pool_success(self, amm_service):
"""Test successful pool creation"""
pool_data = PoolCreate(
token_a="0xaitbc",
token_b="0xusdc",
fee_percentage=0.3
)
creator_address = "0x1234567890123456789012345678901234567890"
result = amm_service.create_service_pool(pool_data, creator_address)
assert result.token_a == "0xaitbc"
assert result.token_b == "0xusdc"
assert result.fee_percentage == 0.3
assert result.is_active is True
def test_create_pool_same_tokens(self, amm_service):
"""Test pool creation with same tokens"""
pool_data = PoolCreate(
token_a="0xaitbc",
token_b="0xaitbc",
fee_percentage=0.3
)
creator_address = "0x1234567890123456789012345678901234567890"
with pytest.raises(Exception) as exc_info:
amm_service.create_service_pool(pool_data, creator_address)
assert "Token addresses must be different" in str(exc_info.value)
def test_add_liquidity_success(self, amm_service):
"""Test successful liquidity addition"""
# Create pool first
pool_data = PoolCreate(
token_a="0xaitbc",
token_b="0xusdc",
fee_percentage=0.3
)
creator_address = "0x1234567890123456789012345678901234567890"
pool = amm_service.create_service_pool(pool_data, creator_address)
# Add liquidity
from ..schemas.amm import LiquidityAddRequest
liquidity_request = LiquidityAddRequest(
pool_id=pool.id,
amount_a=1000.0,
amount_b=1000.0,
min_amount_a=950.0,
min_amount_b=950.0
)
result = amm_service.add_liquidity(liquidity_request, creator_address)
assert result.pool_id == pool.id
assert result.liquidity_amount > 0
def test_execute_swap_success(self, amm_service):
"""Test successful swap execution"""
# Create pool first
pool_data = PoolCreate(
token_a="0xaitbc",
token_b="0xusdc",
fee_percentage=0.3
)
creator_address = "0x1234567890123456789012345678901234567890"
pool = amm_service.create_service_pool(pool_data, creator_address)
# Add liquidity first
from ..schemas.amm import LiquidityAddRequest
liquidity_request = LiquidityAddRequest(
pool_id=pool.id,
amount_a=10000.0,
amount_b=10000.0,
min_amount_a=9500.0,
min_amount_b=9500.0
)
amm_service.add_liquidity(liquidity_request, creator_address)
# Execute swap
swap_request = SwapRequest(
pool_id=pool.id,
token_in="0xaitbc",
token_out="0xusdc",
amount_in=100.0,
min_amount_out=95.0,
deadline=datetime.utcnow() + timedelta(minutes=20)
)
result = amm_service.execute_swap(swap_request, creator_address)
assert result.token_in == "0xaitbc"
assert result.token_out == "0xusdc"
assert result.amount_in == 100.0
assert result.status == SwapStatus.EXECUTED
def test_dynamic_fee_adjustment(self, amm_service):
"""Test dynamic fee adjustment"""
# Create pool first
pool_data = PoolCreate(
token_a="0xaitbc",
token_b="0xusdc",
fee_percentage=0.3
)
creator_address = "0x1234567890123456789012345678901234567890"
pool = amm_service.create_service_pool(pool_data, creator_address)
# Adjust fee based on volatility
volatility = 0.25 # High volatility
result = amm_service.dynamic_fee_adjustment(pool.id, volatility)
assert result.pool_id == pool.id
assert result.current_fee_percentage > result.base_fee_percentage
class TestCrossChainBridgeService:
"""Test cases for Cross-Chain Bridge Service"""
def test_initiate_transfer_success(self, cross_chain_bridge_service):
"""Test successful bridge transfer initiation"""
transfer_request = BridgeCreateRequest(
source_token="0xaitbc",
target_token="0xaitbc_polygon",
amount=1000.0,
source_chain_id=1, # Ethereum
target_chain_id=137, # Polygon
recipient_address="0x9876543210987654321098765432109876543210"
)
sender_address = "0x1234567890123456789012345678901234567890"
result = cross_chain_bridge_service.initiate_transfer(transfer_request, sender_address)
assert result.sender_address == sender_address
assert result.amount == 1000.0
assert result.source_chain_id == 1
assert result.target_chain_id == 137
assert result.status == BridgeRequestStatus.PENDING
def test_initiate_transfer_invalid_amount(self, cross_chain_bridge_service):
"""Test bridge transfer with invalid amount"""
transfer_request = BridgeCreateRequest(
source_token="0xaitbc",
target_token="0xaitbc_polygon",
amount=0.0, # Invalid amount
source_chain_id=1,
target_chain_id=137,
recipient_address="0x9876543210987654321098765432109876543210"
)
sender_address = "0x1234567890123456789012345678901234567890"
with pytest.raises(Exception) as exc_info:
cross_chain_bridge_service.initiate_transfer(transfer_request, sender_address)
assert "Amount must be greater than 0" in str(exc_info.value)
def test_monitor_bridge_status(self, cross_chain_bridge_service):
"""Test bridge status monitoring"""
# Initiate transfer first
transfer_request = BridgeCreateRequest(
source_token="0xaitbc",
target_token="0xaitbc_polygon",
amount=1000.0,
source_chain_id=1,
target_chain_id=137,
recipient_address="0x9876543210987654321098765432109876543210"
)
sender_address = "0x1234567890123456789012345678901234567890"
bridge = cross_chain_bridge_service.initiate_transfer(transfer_request, sender_address)
# Monitor status
result = cross_chain_bridge_service.monitor_bridge_status(bridge.id)
assert result.request_id == bridge.id
assert result.status == BridgeRequestStatus.PENDING
assert result.source_chain_id == 1
assert result.target_chain_id == 137
class TestIntegration:
"""Integration tests for trading protocols"""
def test_portfolio_to_amm_integration(
self, agent_portfolio_manager, amm_service, test_db, sample_strategy
):
"""Test integration between portfolio management and AMM"""
# Create portfolio
portfolio_data = PortfolioCreate(
strategy_id=sample_strategy.id,
initial_capital=10000.0,
risk_tolerance=50.0
)
agent_address = "0x1234567890123456789012345678901234567890"
portfolio = agent_portfolio_manager.create_portfolio(portfolio_data, agent_address)
# Create AMM pool
from ..schemas.amm import PoolCreate
pool_data = PoolCreate(
token_a="0xaitbc",
token_b="0xusdc",
fee_percentage=0.3
)
pool = amm_service.create_service_pool(pool_data, agent_address)
# Add liquidity to pool
from ..schemas.amm import LiquidityAddRequest
liquidity_request = LiquidityAddRequest(
pool_id=pool.id,
amount_a=5000.0,
amount_b=5000.0,
min_amount_a=4750.0,
min_amount_b=4750.0
)
amm_service.add_liquidity(liquidity_request, agent_address)
# Execute trade through portfolio
from ..schemas.portfolio import TradeRequest
trade_request = TradeRequest(
sell_token="AITBC",
buy_token="USDC",
sell_amount=100.0,
min_buy_amount=95.0
)
result = agent_portfolio_manager.execute_trade(trade_request, agent_address)
assert result.status == TradeStatus.EXECUTED
assert result.sell_amount == 100.0
def test_bridge_to_portfolio_integration(
self, agent_portfolio_manager, cross_chain_bridge_service, test_db, sample_strategy
):
"""Test integration between bridge and portfolio management"""
# Create portfolio
portfolio_data = PortfolioCreate(
strategy_id=sample_strategy.id,
initial_capital=10000.0,
risk_tolerance=50.0
)
agent_address = "0x1234567890123456789012345678901234567890"
portfolio = agent_portfolio_manager.create_portfolio(portfolio_data, agent_address)
# Initiate bridge transfer
from ..schemas.cross_chain_bridge import BridgeCreateRequest
transfer_request = BridgeCreateRequest(
source_token="0xeth",
target_token="0xeth_polygon",
amount=2000.0,
source_chain_id=1,
target_chain_id=137,
recipient_address=agent_address
)
bridge = cross_chain_bridge_service.initiate_transfer(transfer_request, agent_address)
# Monitor bridge status
status = cross_chain_bridge_service.monitor_bridge_status(bridge.id)
assert status.request_id == bridge.id
assert status.status == BridgeRequestStatus.PENDING
if __name__ == "__main__":
pytest.main([__file__, "-v"])