Files
aitbc/scripts/testing/generate_staking_test_data.py
aitbc 7c51f3490b Remove outdated GPU marketplace endpoint and fix staking service logic
- Remove duplicate `/marketplace/gpu/{gpu_id}` endpoint from marketplace_gpu.py
- Remove marketplace_gpu router inclusion from main.py (already included elsewhere)
- Fix staking service staker_count logic to check existing stakes before increment/decrement
- Add minimum stake amount validation (100 AITBC)
- Add proper error handling for stake not found cases
- Fix staking pool update to commit and refresh after modifications
- Update CLI send_transaction to use chain
2026-04-13 22:07:51 +02:00

427 lines
14 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Staking Test Data Generator
Generates realistic test data scenarios for staking tests
"""
import json
import random
from datetime import datetime, timedelta
from typing import Dict, List, Any
# Performance tiers and their properties
PERFORMANCE_TIERS = {
"BRONZE": {
"multiplier": 1.0,
"min_accuracy": 70.0,
"max_accuracy": 79.9,
"min_submissions": 5,
"success_rate_range": (0.70, 0.80)
},
"SILVER": {
"multiplier": 1.25,
"min_accuracy": 80.0,
"max_accuracy": 89.9,
"min_submissions": 10,
"success_rate_range": (0.80, 0.90)
},
"GOLD": {
"multiplier": 1.5,
"min_accuracy": 90.0,
"max_accuracy": 94.9,
"min_submissions": 20,
"success_rate_range": (0.90, 0.95)
},
"PLATINUM": {
"multiplier": 2.0,
"min_accuracy": 95.0,
"max_accuracy": 97.9,
"min_submissions": 50,
"success_rate_range": (0.95, 0.98)
},
"DIAMOND": {
"multiplier": 3.0,
"min_accuracy": 98.0,
"max_accuracy": 100.0,
"min_submissions": 100,
"success_rate_range": (0.98, 1.00)
}
}
# Lock period multipliers
LOCK_PERIOD_MULTIPLIERS = {
"short": {"days": 7, "multiplier": 1.0},
"medium": {"days": 30, "multiplier": 1.1},
"long": {"days": 90, "multiplier": 1.5},
"extended": {"days": 365, "multiplier": 2.0}
}
# Stake amount ranges
STAKE_AMOUNTS = {
"minimum": 100.0,
"small": 1000.0,
"medium": 10000.0,
"large": 50000.0,
"maximum": 100000.0
}
def generate_agent_wallet() -> str:
"""Generate a random agent wallet address"""
return f"0x{''.join(random.choices('0123456789abcdef', k=40))}"
def generate_staker_address() -> str:
"""Generate a random staker address"""
return f"ait1{''.join(random.choices('0123456789abcdef', k=40))}"
def generate_agent_metrics(tier: str = "GOLD") -> Dict[str, Any]:
"""Generate realistic agent metrics for a given tier"""
tier_config = PERFORMANCE_TIERS[tier]
total_submissions = random.randint(tier_config["min_submissions"], tier_config["min_submissions"] * 3)
success_rate = random.uniform(*tier_config["success_rate_range"])
successful_submissions = int(total_submissions * success_rate)
return {
"agent_wallet": generate_agent_wallet(),
"total_submissions": total_submissions,
"successful_submissions": successful_submissions,
"average_accuracy": random.uniform(tier_config["min_accuracy"], tier_config["max_accuracy"]),
"current_tier": tier,
"tier_score": random.uniform(60.0, 95.0),
"total_staked": 0.0,
"staker_count": 0,
"total_rewards_distributed": 0.0,
"last_update_time": datetime.utcnow().isoformat()
}
def calculate_expected_apy(tier: str, lock_period_days: int, base_apy: float = 5.0) -> float:
"""Calculate expected APY based on tier and lock period"""
tier_multiplier = PERFORMANCE_TIERS[tier]["multiplier"]
if lock_period_days >= 365:
lock_multiplier = 2.0
elif lock_period_days >= 90:
lock_multiplier = 1.5
elif lock_period_days >= 30:
lock_multiplier = 1.1
else:
lock_multiplier = 1.0
apy = base_apy * tier_multiplier * lock_multiplier
return min(apy, 20.0) # Cap at 20%
def generate_stake_data(
agent_wallet: str,
staker_address: str,
tier: str = "GOLD",
amount_category: str = "medium",
lock_period_category: str = "medium",
auto_compound: bool = False
) -> Dict[str, Any]:
"""Generate realistic stake data"""
amount = STAKE_AMOUNTS[amount_category]
lock_period_days = LOCK_PERIOD_MULTIPLIERS[lock_period_category]["days"]
expected_apy = calculate_expected_apy(tier, lock_period_days)
start_time = datetime.utcnow()
end_time = start_time + timedelta(days=lock_period_days)
return {
"stake_id": f"stake_{random.randint(100000, 999999)}",
"staker_address": staker_address,
"agent_wallet": agent_wallet,
"amount": amount,
"lock_period": lock_period_days,
"start_time": start_time.isoformat(),
"end_time": end_time.isoformat(),
"status": "ACTIVE",
"accumulated_rewards": 0.0,
"last_reward_time": start_time.isoformat(),
"current_apy": expected_apy,
"agent_tier": tier,
"performance_multiplier": PERFORMANCE_TIERS[tier]["multiplier"],
"auto_compound": auto_compound
}
def generate_staking_pool(agent_wallet: str, total_staked: float) -> Dict[str, Any]:
"""Generate staking pool data"""
return {
"agent_wallet": agent_wallet,
"total_staked": total_staked,
"total_rewards": 0.0,
"pool_apy": 5.0,
"staker_count": 0,
"active_stakers": [],
"last_distribution_time": datetime.utcnow().isoformat(),
"distribution_frequency": 1
}
def generate_test_scenario(num_agents: int = 5, num_stakes_per_agent: int = 3) -> Dict[str, Any]:
"""Generate a complete test scenario with multiple agents and stakes"""
scenario = {
"scenario_id": f"scenario_{random.randint(1000, 9999)}",
"generated_at": datetime.utcnow().isoformat(),
"agents": [],
"stakes": [],
"pools": []
}
# Generate agents with different tiers
tier_distribution = ["BRONZE", "SILVER", "GOLD", "GOLD", "PLATINUM"]
for i in range(num_agents):
tier = tier_distribution[i % len(tier_distribution)]
agent_metrics = generate_agent_metrics(tier)
scenario["agents"].append(agent_metrics)
# Generate staking pool
pool = generate_staking_pool(agent_metrics["agent_wallet"], 0.0)
scenario["pools"].append(pool)
# Generate stakes for this agent
for j in range(num_stakes_per_agent):
staker_address = generate_staker_address()
amount_category = random.choice(["small", "medium", "large"])
lock_period_category = random.choice(["short", "medium", "long", "extended"])
auto_compound = random.choice([True, False])
stake = generate_stake_data(
agent_wallet=agent_metrics["agent_wallet"],
staker_address=staker_address,
tier=tier,
amount_category=amount_category,
lock_period_category=lock_period_category,
auto_compound=auto_compound
)
scenario["stakes"].append(stake)
# Update pool totals
pool["total_staked"] += stake["amount"]
pool["staker_count"] += 1
if staker_address not in pool["active_stakers"]:
pool["active_stakers"].append(staker_address)
return scenario
def generate_edge_case_scenarios() -> List[Dict[str, Any]]:
"""Generate edge case test scenarios"""
scenarios = []
# Scenario 1: Minimum stake amount
scenarios.append({
"name": "Minimum Stake Amount",
"description": "Test with minimum valid stake amount (100 AIT)",
"stake": generate_stake_data(
generate_agent_wallet(),
generate_staker_address(),
amount_category="minimum",
lock_period_category="medium"
)
})
# Scenario 2: Maximum stake amount
scenarios.append({
"name": "Maximum Stake Amount",
"description": "Test with maximum valid stake amount (100,000 AIT)",
"stake": generate_stake_data(
generate_agent_wallet(),
generate_staker_address(),
amount_category="maximum",
lock_period_category="medium"
)
})
# Scenario 3: Short lock period
scenarios.append({
"name": "Short Lock Period",
"description": "Test with minimum lock period (7 days)",
"stake": generate_stake_data(
generate_agent_wallet(),
generate_staker_address(),
lock_period_category="short"
)
})
# Scenario 4: Extended lock period
scenarios.append({
"name": "Extended Lock Period",
"description": "Test with maximum lock period (365 days)",
"stake": generate_stake_data(
generate_agent_wallet(),
generate_staker_address(),
lock_period_category="extended"
)
})
# Scenario 5: Diamond tier with extended lock
scenarios.append({
"name": "Diamond Tier Extended Lock",
"description": "Test maximum APY scenario (Diamond tier + 365 days)",
"stake": generate_stake_data(
generate_agent_wallet(),
generate_staker_address(),
tier="DIAMOND",
lock_period_category="extended"
)
})
# Scenario 6: Auto-compound enabled
scenarios.append({
"name": "Auto-Compound Enabled",
"description": "Test stake with auto-compound enabled",
"stake": generate_stake_data(
generate_agent_wallet(),
generate_staker_address(),
auto_compound=True
)
})
return scenarios
def generate_unbonding_scenarios() -> List[Dict[str, Any]]:
"""Generate unbonding test scenarios"""
scenarios = []
# Scenario 1: Unbonding before lock period (should fail)
scenarios.append({
"name": "Unbond Before Lock Period",
"description": "Test unbonding before lock period ends (should fail)",
"stake": generate_stake_data(
generate_agent_wallet(),
generate_staker_address(),
lock_period_category="medium"
),
"action": "unbond",
"expected_result": "failure",
"expected_error": "Lock period has not ended"
})
# Scenario 2: Unbonding after lock period (should succeed)
stake = generate_stake_data(
generate_agent_wallet(),
generate_staker_address(),
lock_period_category="medium"
)
stake["end_time"] = (datetime.utcnow() - timedelta(days=1)).isoformat()
scenarios.append({
"name": "Unbond After Lock Period",
"description": "Test unbonding after lock period ends (should succeed)",
"stake": stake,
"action": "unbond",
"expected_result": "success",
"expected_status": "UNBONDING"
})
# Scenario 3: Complete unbonding with penalty
stake = generate_stake_data(
generate_agent_wallet(),
generate_staker_address(),
lock_period_category="medium"
)
stake["end_time"] = (datetime.utcnow() - timedelta(days=1)).isoformat()
stake["status"] = "UNBONDING"
stake["unbonding_time"] = (datetime.utcnow() - timedelta(days=10)).isoformat()
scenarios.append({
"name": "Complete Unbonding With Penalty",
"description": "Test completing unbonding within 30 days (10% penalty)",
"stake": stake,
"action": "complete_unbonding",
"expected_result": "success",
"expected_penalty": 0.10
})
# Scenario 4: Complete unbonding without penalty
stake = generate_stake_data(
generate_agent_wallet(),
generate_staker_address(),
lock_period_category="medium"
)
stake["end_time"] = (datetime.utcnow() - timedelta(days=1)).isoformat()
stake["status"] = "UNBONDING"
stake["unbonding_time"] = (datetime.utcnow() - timedelta(days=35)).isoformat()
scenarios.append({
"name": "Complete Unbonding No Penalty",
"description": "Test completing unbonding after 30 days (no penalty)",
"stake": stake,
"action": "complete_unbonding",
"expected_result": "success",
"expected_penalty": 0.0
})
return scenarios
def save_test_data(data: Dict[str, Any], output_file: str):
"""Save test data to JSON file"""
with open(output_file, 'w') as f:
json.dump(data, f, indent=2, default=str)
print(f"Test data saved to: {output_file}")
def main():
"""Main function to generate test data"""
print("🔧 Generating Staking Test Data")
print("=" * 50)
# Generate comprehensive test scenario
print("\nGenerating comprehensive test scenario...")
scenario = generate_test_scenario(num_agents=5, num_stakes_per_agent=3)
save_test_data(scenario, "/var/lib/aitbc/data/test_staking_scenario.json")
# Generate edge case scenarios
print("\nGenerating edge case scenarios...")
edge_cases = generate_edge_case_scenarios()
save_test_data(edge_cases, "/var/lib/aitbc/data/test_staking_edge_cases.json")
# Generate unbonding scenarios
print("\nGenerating unbonding scenarios...")
unbonding_scenarios = generate_unbonding_scenarios()
save_test_data(unbonding_scenarios, "/var/lib/aitbc/data/test_staking_unbonding.json")
# Generate individual test data files
print("\nGenerating individual test data files...")
# Agent metrics for each tier
for tier in PERFORMANCE_TIERS.keys():
metrics = generate_agent_metrics(tier)
save_test_data(metrics, f"/var/lib/aitbc/data/test_agent_metrics_{tier.lower()}.json")
# Stake data for each amount category
for amount_cat in STAKE_AMOUNTS.keys():
stake = generate_stake_data(
generate_agent_wallet(),
generate_staker_address(),
amount_category=amount_cat
)
save_test_data(stake, f"/var/lib/aitbc/data/test_stake_{amount_cat}.json")
# Stake data for each lock period
for lock_cat in LOCK_PERIOD_MULTIPLIERS.keys():
stake = generate_stake_data(
generate_agent_wallet(),
generate_staker_address(),
lock_period_category=lock_cat
)
save_test_data(stake, f"/var/lib/aitbc/data/test_stake_lock_{lock_cat}.json")
print("\n✅ Test data generation complete!")
print("\nGenerated files:")
print(" - /var/lib/aitbc/data/test_staking_scenario.json")
print(" - /var/lib/aitbc/data/test_staking_edge_cases.json")
print(" - /var/lib/aitbc/data/test_staking_unbonding.json")
print(" - Agent metrics for each tier")
print(" - Stake data for each amount category")
print(" - Stake data for each lock period")
if __name__ == "__main__":
main()