docs(claude): add claude code rules

This commit is contained in:
smypmsa
2025-08-11 05:35:25 +00:00
parent f2efd56f81
commit 8ab8932168
56 changed files with 4193 additions and 2605 deletions
+120 -57
View File
@@ -25,14 +25,50 @@ REQUIRED_FIELDS = [
]
CONFIG_VALIDATION_RULES = [
("trade.buy_amount", (int, float), 0, float("inf"), "trade.buy_amount must be a positive number"),
(
"trade.buy_amount",
(int, float),
0,
float("inf"),
"trade.buy_amount must be a positive number",
),
("trade.buy_slippage", float, 0, 1, "trade.buy_slippage must be between 0 and 1"),
("trade.sell_slippage", float, 0, 1, "trade.sell_slippage must be between 0 and 1"),
("priority_fees.fixed_amount", int, 0, float("inf"), "priority_fees.fixed_amount must be a non-negative integer"),
("priority_fees.extra_percentage", float, 0, 1, "priority_fees.extra_percentage must be between 0 and 1"),
("priority_fees.hard_cap", int, 0, float("inf"), "priority_fees.hard_cap must be a non-negative integer"),
("retries.max_attempts", int, 0, 100, "retries.max_attempts must be between 0 and 100"),
("filters.max_token_age", (int, float), 0, float("inf"), "filters.max_token_age must be a non-negative number"),
(
"priority_fees.fixed_amount",
int,
0,
float("inf"),
"priority_fees.fixed_amount must be a non-negative integer",
),
(
"priority_fees.extra_percentage",
float,
0,
1,
"priority_fees.extra_percentage must be between 0 and 1",
),
(
"priority_fees.hard_cap",
int,
0,
float("inf"),
"priority_fees.hard_cap must be a non-negative integer",
),
(
"retries.max_attempts",
int,
0,
100,
"retries.max_attempts must be between 0 and 100",
),
(
"filters.max_token_age",
(int, float),
0,
float("inf"),
"filters.max_token_age must be a non-negative number",
),
]
# Valid values for enum-like fields
@@ -66,17 +102,18 @@ def load_bot_config(path: str) -> dict:
load_dotenv(env_file, override=True)
resolve_env_vars(config)
# Set default platform if not specified (backward compatibility)
if "platform" not in config:
config["platform"] = "pump_fun"
validate_config(config)
return config
def resolve_env_vars(config: dict) -> None:
"""Recursively resolve environment variables in the configuration."""
def resolve_env(value):
if isinstance(value, str) and value.startswith("${") and value.endswith("}"):
env_var = value[2:-1]
@@ -144,7 +181,9 @@ def validate_config(config: dict) -> None:
dynamic = get_nested_value(config, "priority_fees.enable_dynamic")
fixed = get_nested_value(config, "priority_fees.enable_fixed")
if dynamic and fixed:
raise ValueError("Cannot enable both dynamic and fixed priority fees simultaneously")
raise ValueError(
"Cannot enable both dynamic and fixed priority fees simultaneously"
)
except ValueError as e:
if "Missing required config key" not in str(e):
raise
@@ -156,7 +195,9 @@ def validate_config(config: dict) -> None:
validate_platform_config(config, platform)
except ValueError as e:
if "is not a valid" in str(e):
raise ValueError(f"Invalid platform '{platform_str}'. Must be one of: {[p.value for p in Platform]}")
raise ValueError(
f"Invalid platform '{platform_str}'. Must be one of: {[p.value for p in Platform]}"
)
raise
@@ -165,8 +206,11 @@ def validate_platform_config(config: dict, platform: Platform) -> None:
# Check if platform is supported
try:
from platforms import platform_factory
if not platform_factory.registry.is_platform_supported(platform):
raise ValueError(f"Platform {platform.value} is not supported. Available platforms: {[p.value for p in platform_factory.get_supported_platforms()]}")
raise ValueError(
f"Platform {platform.value} is not supported. Available platforms: {[p.value for p in platform_factory.get_supported_platforms()]}"
)
except ImportError:
# If platform factory not available, just validate enum
pass
@@ -175,7 +219,7 @@ def validate_platform_config(config: dict, platform: Platform) -> None:
try:
listener_type = get_nested_value(config, "filters.listener_type")
compatible_listeners = PLATFORM_LISTENER_COMPATIBILITY.get(platform, [])
if listener_type not in compatible_listeners:
raise ValueError(
f"Listener type '{listener_type}' is not compatible with platform '{platform.value}'. "
@@ -189,7 +233,7 @@ def validate_platform_config(config: dict, platform: Platform) -> None:
if platform == Platform.PUMP_FUN:
# pump.fun doesn't require additional config beyond base requirements
pass
elif platform == Platform.LETS_BONK:
# LetsBonk may require additional configuration in the future
# For now, it uses the same base configuration as pump.fun
@@ -202,16 +246,20 @@ def get_platform_from_config(config: dict) -> Platform:
try:
return Platform(platform_str)
except ValueError:
raise ValueError(f"Invalid platform '{platform_str}'. Must be one of: {[p.value for p in Platform]}")
raise ValueError(
f"Invalid platform '{platform_str}'. Must be one of: {[p.value for p in Platform]}"
)
def validate_platform_listener_combination(platform: Platform, listener_type: str) -> bool:
def validate_platform_listener_combination(
platform: Platform, listener_type: str
) -> bool:
"""Check if a platform and listener type are compatible.
Args:
platform: Platform enum
listener_type: Listener type string
Returns:
True if combination is valid
"""
@@ -221,10 +269,10 @@ def validate_platform_listener_combination(platform: Platform, listener_type: st
def get_supported_listeners_for_platform(platform: Platform) -> list[str]:
"""Get list of supported listener types for a platform.
Args:
platform: Platform enum
Returns:
List of supported listener types
"""
@@ -233,10 +281,10 @@ def get_supported_listeners_for_platform(platform: Platform) -> list[str]:
def get_platform_specific_required_config(platform: Platform) -> list[str]:
"""Get platform-specific required configuration paths.
Args:
platform: Platform enum
Returns:
List of additional required config paths for the platform
"""
@@ -251,17 +299,23 @@ def get_platform_specific_required_config(platform: Platform) -> list[str]:
def print_config_summary(config: dict) -> None:
"""Print a summary of the loaded configuration with platform info."""
platform_str = config.get("platform", "pump_fun")
print(f"Bot name: {config.get('name', 'unnamed')}")
print(f"Platform: {platform_str}")
print(f"Listener type: {config.get('filters', {}).get('listener_type', 'not configured')}")
print(
f"Listener type: {config.get('filters', {}).get('listener_type', 'not configured')}"
)
# Validate platform-listener combination
try:
platform = Platform(platform_str)
listener_type = config.get('filters', {}).get('listener_type')
if listener_type and not validate_platform_listener_combination(platform, listener_type):
print(f"WARNING: Listener '{listener_type}' may not be compatible with platform '{platform_str}'")
listener_type = config.get("filters", {}).get("listener_type")
if listener_type and not validate_platform_listener_combination(
platform, listener_type
):
print(
f"WARNING: Listener '{listener_type}' may not be compatible with platform '{platform_str}'"
)
except ValueError:
print(f"WARNING: Invalid platform '{platform_str}'")
@@ -269,24 +323,28 @@ def print_config_summary(config: dict) -> None:
print("Trade settings:")
print(f" - Buy amount: {trade.get('buy_amount', 'not configured')} SOL")
print(f" - Buy slippage: {trade.get('buy_slippage', 'not configured') * 100}%")
print(f" - Extreme fast mode: {'enabled' if trade.get('extreme_fast_mode') else 'disabled'}")
print(
f" - Extreme fast mode: {'enabled' if trade.get('extreme_fast_mode') else 'disabled'}"
)
fees = config.get("priority_fees", {})
print("Priority fees:")
if fees.get("enable_dynamic"):
print(" - Dynamic fees enabled")
elif fees.get("enable_fixed"):
print(f" - Fixed fee: {fees.get('fixed_amount', 'not configured')} microlamports")
print(
f" - Fixed fee: {fees.get('fixed_amount', 'not configured')} microlamports"
)
print("Configuration loaded successfully!")
def validate_all_platform_configs(config_dir: str = "bots") -> dict[str, Any]:
"""Validate all bot configurations in a directory.
Args:
config_dir: Directory containing bot config files
Returns:
Dictionary with validation results
"""
@@ -296,50 +354,55 @@ def validate_all_platform_configs(config_dir: str = "bots") -> dict[str, Any]:
"platform_distribution": {},
"listener_distribution": {},
}
config_files = list(Path(config_dir).glob("*.yaml"))
for config_file in config_files:
try:
config = load_bot_config(config_file)
platform = get_platform_from_config(config)
listener_type = config.get('filters', {}).get('listener_type', 'unknown')
results["valid_configs"].append({
"file": config_file,
"name": config.get("name"),
"platform": platform.value,
"listener": listener_type,
"enabled": config.get("enabled", True)
})
listener_type = config.get("filters", {}).get("listener_type", "unknown")
results["valid_configs"].append(
{
"file": config_file,
"name": config.get("name"),
"platform": platform.value,
"listener": listener_type,
"enabled": config.get("enabled", True),
}
)
# Track distributions
platform_key = platform.value
results["platform_distribution"][platform_key] = results["platform_distribution"].get(platform_key, 0) + 1
results["listener_distribution"][listener_type] = results["listener_distribution"].get(listener_type, 0) + 1
results["platform_distribution"][platform_key] = (
results["platform_distribution"].get(platform_key, 0) + 1
)
results["listener_distribution"][listener_type] = (
results["listener_distribution"].get(listener_type, 0) + 1
)
except Exception as e:
results["invalid_configs"].append({
"file": config_file,
"error": str(e)
})
results["invalid_configs"].append({"file": config_file, "error": str(e)})
return results
if __name__ == "__main__":
# Example usage with platform configuration validation
import sys
if len(sys.argv) > 1:
config_path = sys.argv[1]
try:
config = load_bot_config(config_path)
print_config_summary(config)
platform = get_platform_from_config(config)
print(f"Detected platform: {platform}")
print(f"Supported listeners for this platform: {get_supported_listeners_for_platform(platform)}")
print(
f"Supported listeners for this platform: {get_supported_listeners_for_platform(platform)}"
)
except Exception as e:
print(f"Configuration error: {e}")
else:
@@ -350,8 +413,8 @@ if __name__ == "__main__":
print(f"Invalid configs: {len(results['invalid_configs'])}")
print(f"Platform distribution: {results['platform_distribution']}")
print(f"Listener distribution: {results['listener_distribution']}")
if results['invalid_configs']:
if results["invalid_configs"]:
print("\nInvalid configurations:")
for invalid in results['invalid_configs']:
print(f" {invalid['file']}: {invalid['error']}")
for invalid in results["invalid_configs"]:
print(f" {invalid['file']}: {invalid['error']}")