mirror of
https://github.com/chainstacklabs/pumpfun-bonkfun-bot.git
synced 2026-07-27 15:27:44 +00:00
docs: add rules for cursor, kiro, windsurf
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
---
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# Project Architecture Rules
|
||||
|
||||
## Directory Structure
|
||||
|
||||
### Package Organization
|
||||
Maintain clear separation of concerns:
|
||||
|
||||
```
|
||||
src/
|
||||
├── __init__.py
|
||||
├── bot_runner.py # Main entry point
|
||||
├── config_loader.py # Configuration management
|
||||
├── core/ # Core blockchain functionality
|
||||
│ ├── client.py # Solana RPC client abstraction
|
||||
│ ├── wallet.py # Wallet operations
|
||||
│ └── priority_fee/ # Fee management
|
||||
├── platforms/ # Platform-specific implementations
|
||||
│ ├── pumpfun/ # pump.fun specific code
|
||||
│ └── letsbonk/ # letsbonk.fun specific code
|
||||
├── trading/ # Trading logic
|
||||
│ ├── base.py # Base trading classes
|
||||
│ ├── universal_trader.py # Platform-agnostic trader
|
||||
│ └── position.py # Position management
|
||||
├── monitoring/ # Event listening and monitoring
|
||||
│ ├── base_listener.py # Base listener interface
|
||||
│ └── universal_*_listener.py # Specific listeners
|
||||
├── interfaces/ # Abstract base classes
|
||||
└── utils/ # Utilities and helpers
|
||||
├── logger.py # Logging utilities
|
||||
└── idl_manager.py # IDL management
|
||||
```
|
||||
|
||||
### File Naming Conventions
|
||||
- Use snake_case for all Python files and directories
|
||||
- Prefix abstract base classes with "Base" or put in `interfaces/`
|
||||
- Use "Universal" prefix for platform-agnostic implementations
|
||||
- Group related functionality in subdirectories
|
||||
|
||||
## Design Patterns
|
||||
|
||||
### Platform Abstraction
|
||||
Implement platform-specific functionality using the factory pattern:
|
||||
|
||||
```python
|
||||
# interfaces/core.py - Define abstract interfaces
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
class AddressProvider(ABC):
|
||||
@abstractmethod
|
||||
def get_program_address(self) -> str:
|
||||
pass
|
||||
|
||||
# platforms/pumpfun/address_provider.py - Concrete implementation
|
||||
class PumpFunAddressProvider(AddressProvider):
|
||||
def get_program_address(self) -> str:
|
||||
return "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"
|
||||
```
|
||||
|
||||
### Universal Components
|
||||
Create platform-agnostic wrappers that delegate to platform-specific implementations:
|
||||
|
||||
```python
|
||||
class UniversalTrader:
|
||||
def __init__(self, platform: Platform, **kwargs):
|
||||
self.platform = platform
|
||||
self.platform_trader = self._create_platform_trader()
|
||||
|
||||
def _create_platform_trader(self):
|
||||
# Factory method to create platform-specific trader
|
||||
pass
|
||||
```
|
||||
|
||||
### Configuration Management
|
||||
- Use YAML files for bot configurations in `bots/` directory
|
||||
- Support environment variable interpolation with `${VARIABLE}` syntax
|
||||
- Validate configurations before starting bots
|
||||
- Separate environment-specific settings in `.env` files
|
||||
|
||||
## Module Dependencies
|
||||
|
||||
### Import Rules
|
||||
- Core modules should not import from trading or monitoring
|
||||
- Platform-specific modules should only import from their own package and core/interfaces
|
||||
- Avoid circular imports between packages
|
||||
- Use dependency injection for cross-package dependencies
|
||||
|
||||
### Dependency Layers (from low to high level)
|
||||
1. **utils/** - Utilities and helpers (no business logic dependencies)
|
||||
2. **interfaces/** - Abstract base classes and protocols
|
||||
3. **core/** - Blockchain and infrastructure (depends on utils, interfaces)
|
||||
4. **platforms/** - Platform implementations (depends on core, interfaces)
|
||||
5. **trading/** - Trading logic (depends on core, platforms, interfaces)
|
||||
6. **monitoring/** - Event listening (depends on core, platforms, interfaces)
|
||||
7. **bot_runner.py** - Main orchestrator (depends on all layers)
|
||||
|
||||
## Async Architecture
|
||||
|
||||
### Event Loop Management
|
||||
- Use uvloop for better performance
|
||||
- Set event loop policy at application startup
|
||||
- Use asyncio.create_task() for concurrent operations
|
||||
- Implement proper cleanup on shutdown
|
||||
|
||||
### Connection Management
|
||||
- Use connection pooling for HTTP clients
|
||||
- Implement reconnection logic for WebSocket connections
|
||||
- Cache expensive resources (blockhash, account info)
|
||||
- Use async context managers for resource cleanup
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### Test Organization
|
||||
- Use `learning-examples/` for integration testing and validation
|
||||
- Test platform-specific components independently
|
||||
- Mock external dependencies (RPC calls, WebSocket connections)
|
||||
- Validate configurations with actual bot startup
|
||||
|
||||
### Test Data
|
||||
- Use test networks for development
|
||||
- Never test with real funds or production keys
|
||||
- Create fixtures for common test scenarios
|
||||
- Document test account requirements
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
### Caching Strategy
|
||||
- Cache recent blockhash in background task
|
||||
- Cache account information where appropriate
|
||||
- Use local caching for IDL data
|
||||
- Implement TTL for cached data
|
||||
|
||||
### Resource Management
|
||||
- Limit concurrent operations based on RPC provider limits
|
||||
- Implement backoff strategies for failed requests
|
||||
- Use separate processes for production bot instances
|
||||
- Monitor memory usage in long-running processes
|
||||
@@ -0,0 +1,150 @@
|
||||
---
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# Python Code Style Rules
|
||||
|
||||
## Formatting Standards
|
||||
|
||||
### Ruff Configuration Compliance
|
||||
- Use 88 character line length limit
|
||||
- Use 4 spaces for indentation (never tabs)
|
||||
- Use double quotes for strings consistently
|
||||
- Target Python 3.11+ features and syntax
|
||||
- Enable automatic import sorting and organization
|
||||
|
||||
### Import Organization
|
||||
```python
|
||||
# Standard library imports first
|
||||
import asyncio
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
# Third-party imports second
|
||||
import aiohttp
|
||||
from solana.rpc.async_api import AsyncClient
|
||||
|
||||
# Local imports last
|
||||
from config_loader import load_bot_config
|
||||
from utils.logger import get_logger
|
||||
```
|
||||
|
||||
### Type Annotations
|
||||
- Add type hints to ALL public functions and methods
|
||||
- Use modern typing syntax (Python 3.9+ union syntax where applicable)
|
||||
- Include return type annotations
|
||||
- Use `from typing import Any` for complex types
|
||||
|
||||
```python
|
||||
def process_transaction(tx_data: dict[str, Any]) -> bool:
|
||||
"""Process transaction data and return success status."""
|
||||
pass
|
||||
|
||||
async def fetch_data(endpoint: str) -> dict[str, Any] | None:
|
||||
"""Fetch data from endpoint, return None on failure."""
|
||||
pass
|
||||
```
|
||||
|
||||
## Documentation Standards
|
||||
|
||||
### Docstring Format
|
||||
Use Google-style docstrings for all functions and classes:
|
||||
|
||||
```python
|
||||
def calculate_slippage(amount: float, slippage_percent: float) -> float:
|
||||
"""Calculate slippage amount for a trade.
|
||||
|
||||
Args:
|
||||
amount: The trade amount in SOL
|
||||
slippage_percent: Slippage percentage (0.1 = 10%)
|
||||
|
||||
Returns:
|
||||
The calculated slippage amount
|
||||
|
||||
Raises:
|
||||
ValueError: If slippage_percent is negative
|
||||
"""
|
||||
if slippage_percent < 0:
|
||||
raise ValueError("Slippage percentage cannot be negative")
|
||||
return amount * slippage_percent
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Comprehensive Exception Handling
|
||||
- Use try-catch blocks for all external operations (RPC calls, file I/O)
|
||||
- Log exceptions with context using `logging.exception()`
|
||||
- Provide meaningful error messages
|
||||
- Don't suppress exceptions without good reason
|
||||
|
||||
```python
|
||||
try:
|
||||
result = await client.get_account_info(address)
|
||||
logger.info(f"Successfully fetched account info for {address}")
|
||||
except Exception as e:
|
||||
logger.exception(f"Failed to fetch account info for {address}: {e}")
|
||||
raise
|
||||
```
|
||||
|
||||
## Logging Standards
|
||||
|
||||
### Logger Usage
|
||||
- Use `get_logger(__name__)` pattern consistently
|
||||
- Import from `utils.logger`
|
||||
- Use appropriate log levels (DEBUG, INFO, WARNING, ERROR)
|
||||
- Include context in log messages
|
||||
|
||||
```python
|
||||
from utils.logger import get_logger
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
# Good logging examples
|
||||
logger.info(f"Starting bot '{bot_name}' with platform {platform.value}")
|
||||
logger.warning(f"Transaction failed, attempt {attempt}/{max_attempts}")
|
||||
logger.error(f"Platform {platform.value} is not supported")
|
||||
```
|
||||
|
||||
## Security Rules
|
||||
|
||||
### Sensitive Data
|
||||
- NEVER hardcode private keys, API tokens, or secrets
|
||||
- Use environment variables for all sensitive configuration
|
||||
- Don't log sensitive information
|
||||
- Validate all external inputs
|
||||
|
||||
### Safe Practices
|
||||
```python
|
||||
# Good - using environment variables
|
||||
private_key = os.getenv("SOLANA_PRIVATE_KEY")
|
||||
if not private_key:
|
||||
raise ValueError("SOLANA_PRIVATE_KEY environment variable is required")
|
||||
|
||||
# Bad - hardcoded secrets
|
||||
private_key = "your_secret_key_here" # NEVER DO THIS
|
||||
```
|
||||
|
||||
## Code Quality
|
||||
|
||||
### Linting Compliance
|
||||
Ensure code passes all enabled Ruff rules:
|
||||
- Security best practices (S)
|
||||
- Type annotations (ANN)
|
||||
- Exception handling (BLE, TRY)
|
||||
- Code complexity (C90)
|
||||
- Pylint conventions (PL)
|
||||
- No commented-out code (ERA)
|
||||
|
||||
### Performance Considerations
|
||||
- Use async/await for I/O operations
|
||||
- Implement proper connection pooling for HTTP clients
|
||||
- Cache expensive computations when appropriate
|
||||
- Use uvloop for better async performance
|
||||
|
||||
```python
|
||||
# Set uvloop policy at module level
|
||||
import asyncio
|
||||
import uvloop
|
||||
|
||||
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
|
||||
```
|
||||
@@ -0,0 +1,248 @@
|
||||
---
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# Trading Bot Specific Rules
|
||||
|
||||
## Bot Configuration Standards
|
||||
|
||||
### YAML Configuration Structure
|
||||
Maintain consistent structure across all bot configuration files:
|
||||
|
||||
```yaml
|
||||
# Bot identification
|
||||
name: "bot-sniper-1"
|
||||
platform: "pump_fun" # or "lets_bonk"
|
||||
enabled: true # Allow disabling without removing config
|
||||
separate_process: true # Run in separate process for isolation
|
||||
|
||||
# Environment and connection
|
||||
env_file: ".env"
|
||||
rpc_endpoint: "${SOLANA_NODE_RPC_ENDPOINT}"
|
||||
wss_endpoint: "${SOLANA_NODE_WSS_ENDPOINT}"
|
||||
private_key: "${SOLANA_PRIVATE_KEY}"
|
||||
|
||||
# Platform-specific configurations
|
||||
geyser: # For faster data streams
|
||||
endpoint: "${GEYSER_ENDPOINT}"
|
||||
api_token: "${GEYSER_API_TOKEN}"
|
||||
auth_type: "x-token"
|
||||
|
||||
# Trading parameters
|
||||
trade:
|
||||
buy_amount: 0.0001 # SOL amount
|
||||
buy_slippage: 0.3 # 30%
|
||||
sell_slippage: 0.3
|
||||
exit_strategy: "time_based" # "tp_sl", "manual"
|
||||
extreme_fast_mode: true # Skip validations for speed
|
||||
```
|
||||
|
||||
### Environment Variable Usage
|
||||
- Use `${VARIABLE_NAME}` syntax for environment interpolation
|
||||
- Never hardcode sensitive values in YAML files
|
||||
- Validate all required environment variables on startup
|
||||
- Provide clear error messages for missing variables
|
||||
|
||||
## Trading Logic Rules
|
||||
|
||||
### Transaction Handling
|
||||
- Always use priority fees for competitive transaction inclusion
|
||||
- Implement retry mechanisms with exponential backoff
|
||||
- Cache recent blockhash to avoid repeated RPC calls
|
||||
- Use compute unit limits to prevent transaction failures
|
||||
|
||||
```python
|
||||
# Good transaction building pattern
|
||||
instructions = [
|
||||
set_compute_unit_limit(300_000),
|
||||
set_compute_unit_price(priority_fee),
|
||||
# ... trading instructions
|
||||
]
|
||||
```
|
||||
|
||||
### Risk Management
|
||||
- Implement position size limits
|
||||
- Use slippage protection on all trades
|
||||
- Set maximum hold times to prevent stuck positions
|
||||
- Validate token data before trading
|
||||
|
||||
```python
|
||||
# Risk validation example
|
||||
if token_age > self.max_token_age:
|
||||
logger.warning(f"Token {mint} too old ({token_age}s), skipping")
|
||||
return False
|
||||
|
||||
if buy_amount > self.max_position_size:
|
||||
logger.error(f"Buy amount {buy_amount} exceeds max position size")
|
||||
return False
|
||||
```
|
||||
|
||||
### Exit Strategies
|
||||
Implement multiple exit strategy types:
|
||||
|
||||
1. **Time-based**: Hold for fixed duration
|
||||
2. **Take Profit/Stop Loss**: Price-based exits
|
||||
3. **Manual**: No automatic selling
|
||||
|
||||
```python
|
||||
class ExitStrategy(Enum):
|
||||
TIME_BASED = "time_based"
|
||||
TP_SL = "tp_sl"
|
||||
MANUAL = "manual"
|
||||
```
|
||||
|
||||
## Platform Integration Rules
|
||||
|
||||
### Multi-Platform Support
|
||||
- Use platform enum for type safety
|
||||
- Implement platform-specific address providers
|
||||
- Abstract platform differences in universal components
|
||||
- Validate platform-listener combinations
|
||||
|
||||
```python
|
||||
# Platform validation
|
||||
if not validate_platform_listener_combination(platform, listener_type):
|
||||
supported = get_supported_listeners_for_platform(platform)
|
||||
raise ConfigurationError(
|
||||
f"Listener '{listener_type}' not supported for {platform.value}. "
|
||||
f"Supported: {supported}"
|
||||
)
|
||||
```
|
||||
|
||||
### Listener Types
|
||||
Support multiple data source types:
|
||||
- **geyser**: Fastest, requires special endpoint
|
||||
- **logs**: WebSocket log subscription
|
||||
- **blocks**: Block subscription (not all providers support)
|
||||
- **pumpportal**: Third-party aggregator
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Speed vs Accuracy Tradeoffs
|
||||
- **Extreme Fast Mode**: Skip validations and price checks for speed
|
||||
- **Normal Mode**: Full validation and price checks
|
||||
- **Marry Mode**: Only buy, never sell (accumulation strategy)
|
||||
- **YOLO Mode**: Continuous trading without cooldowns
|
||||
|
||||
### Caching Strategy
|
||||
```python
|
||||
# Cache expensive operations
|
||||
self._cached_blockhash: Hash | None = None
|
||||
self._blockhash_lock = asyncio.Lock()
|
||||
|
||||
# Background blockhash updater
|
||||
async def start_blockhash_updater(self, interval: float = 5.0):
|
||||
while True:
|
||||
try:
|
||||
blockhash = await self.get_latest_blockhash()
|
||||
async with self._blockhash_lock:
|
||||
self._cached_blockhash = blockhash
|
||||
except Exception as e:
|
||||
logger.exception(f"Failed to update blockhash: {e}")
|
||||
await asyncio.sleep(interval)
|
||||
```
|
||||
|
||||
## Monitoring and Logging
|
||||
|
||||
### Log File Management
|
||||
- Create timestamped log files per bot instance
|
||||
- Format: `{bot_name}_{timestamp}.log`
|
||||
- Store in `logs/` directory
|
||||
- Implement log rotation for long-running bots
|
||||
|
||||
### Trading Event Logging
|
||||
Log all significant events with context:
|
||||
|
||||
```python
|
||||
# Good logging examples
|
||||
logger.info(f"New token detected: {mint} by {creator}")
|
||||
logger.info(f"Buy transaction submitted: {signature}")
|
||||
logger.warning(f"Transaction failed, attempt {attempt}/{max_attempts}")
|
||||
logger.error(f"Platform {platform.value} not supported")
|
||||
```
|
||||
|
||||
### Performance Metrics
|
||||
Track key performance indicators:
|
||||
- Token detection latency
|
||||
- Transaction confirmation time
|
||||
- Success/failure rates
|
||||
- Slippage and fill rates
|
||||
|
||||
## Security and Safety Rules
|
||||
|
||||
### Private Key Management
|
||||
- Store private keys only in environment variables
|
||||
- Never log or expose private keys
|
||||
- Use separate wallets for testing vs production
|
||||
- Implement wallet balance checks before trading
|
||||
|
||||
### Input Validation
|
||||
```python
|
||||
# Validate all external inputs
|
||||
def validate_mint_address(mint_str: str) -> bool:
|
||||
try:
|
||||
mint = Pubkey.from_string(mint_str)
|
||||
return len(str(mint)) == 44 # Valid Solana address length
|
||||
except Exception:
|
||||
return False
|
||||
```
|
||||
|
||||
### Error Recovery
|
||||
- Implement graceful shutdown on critical errors
|
||||
- Provide cleanup mechanisms for stuck positions
|
||||
- Support manual intervention modes
|
||||
- Log all errors with sufficient context for debugging
|
||||
|
||||
## Testing and Validation
|
||||
|
||||
### Learning Examples Usage
|
||||
Use learning examples for:
|
||||
- Testing new features before integration
|
||||
- Validating platform-specific functionality
|
||||
- Performance benchmarking
|
||||
- Educational purposes for new developers
|
||||
|
||||
```bash
|
||||
# Test platform connectivity
|
||||
uv run learning-examples/fetch_price.py
|
||||
|
||||
# Validate bonding curve calculations
|
||||
uv run learning-examples/compute_associated_bonding_curve.py
|
||||
|
||||
# Compare listener performance
|
||||
uv run learning-examples/listen-new-tokens/compare_listeners.py
|
||||
```
|
||||
|
||||
### Configuration Testing
|
||||
- Validate YAML syntax and required fields
|
||||
- Test environment variable interpolation
|
||||
- Verify platform-listener compatibility
|
||||
- Check wallet connectivity and balance
|
||||
|
||||
## Deployment Guidelines
|
||||
|
||||
### Production Checklist
|
||||
1. Test configuration with learning examples
|
||||
2. Verify environment variables are set
|
||||
3. Check wallet has sufficient SOL for gas fees
|
||||
4. Enable separate processes for isolation
|
||||
5. Monitor logs for successful startup
|
||||
6. Implement monitoring and alerting
|
||||
|
||||
### Multi-Bot Management
|
||||
- Use descriptive bot names in configurations
|
||||
- Separate log files per bot instance
|
||||
- Monitor resource usage across all bots
|
||||
- Implement centralized configuration management
|
||||
|
||||
```python
|
||||
# Bot process management
|
||||
if cfg.get("separate_process", False):
|
||||
p = multiprocessing.Process(
|
||||
target=run_bot_process,
|
||||
args=(str(file),),
|
||||
name=f"bot-{bot_name}"
|
||||
)
|
||||
p.start()
|
||||
processes.append(p)
|
||||
```
|
||||
@@ -0,0 +1,140 @@
|
||||
---
|
||||
inclusion: always
|
||||
---
|
||||
|
||||
# Project Architecture Rules
|
||||
|
||||
## Directory Structure
|
||||
|
||||
### Package Organization
|
||||
Maintain clear separation of concerns:
|
||||
|
||||
```
|
||||
src/
|
||||
├── __init__.py
|
||||
├── bot_runner.py # Main entry point
|
||||
├── config_loader.py # Configuration management
|
||||
├── core/ # Core blockchain functionality
|
||||
│ ├── client.py # Solana RPC client abstraction
|
||||
│ ├── wallet.py # Wallet operations
|
||||
│ └── priority_fee/ # Fee management
|
||||
├── platforms/ # Platform-specific implementations
|
||||
│ ├── pumpfun/ # pump.fun specific code
|
||||
│ └── letsbonk/ # letsbonk.fun specific code
|
||||
├── trading/ # Trading logic
|
||||
│ ├── base.py # Base trading classes
|
||||
│ ├── universal_trader.py # Platform-agnostic trader
|
||||
│ └── position.py # Position management
|
||||
├── monitoring/ # Event listening and monitoring
|
||||
│ ├── base_listener.py # Base listener interface
|
||||
│ └── universal_*_listener.py # Specific listeners
|
||||
├── interfaces/ # Abstract base classes
|
||||
└── utils/ # Utilities and helpers
|
||||
├── logger.py # Logging utilities
|
||||
└── idl_manager.py # IDL management
|
||||
```
|
||||
|
||||
### File Naming Conventions
|
||||
- Use snake_case for all Python files and directories
|
||||
- Prefix abstract base classes with "Base" or put in `interfaces/`
|
||||
- Use "Universal" prefix for platform-agnostic implementations
|
||||
- Group related functionality in subdirectories
|
||||
|
||||
## Design Patterns
|
||||
|
||||
### Platform Abstraction
|
||||
Implement platform-specific functionality using the factory pattern:
|
||||
|
||||
```python
|
||||
# interfaces/core.py - Define abstract interfaces
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
class AddressProvider(ABC):
|
||||
@abstractmethod
|
||||
def get_program_address(self) -> str:
|
||||
pass
|
||||
|
||||
# platforms/pumpfun/address_provider.py - Concrete implementation
|
||||
class PumpFunAddressProvider(AddressProvider):
|
||||
def get_program_address(self) -> str:
|
||||
return "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"
|
||||
```
|
||||
|
||||
### Universal Components
|
||||
Create platform-agnostic wrappers that delegate to platform-specific implementations:
|
||||
|
||||
```python
|
||||
class UniversalTrader:
|
||||
def __init__(self, platform: Platform, **kwargs):
|
||||
self.platform = platform
|
||||
self.platform_trader = self._create_platform_trader()
|
||||
|
||||
def _create_platform_trader(self):
|
||||
# Factory method to create platform-specific trader
|
||||
pass
|
||||
```
|
||||
|
||||
### Configuration Management
|
||||
- Use YAML files for bot configurations in `bots/` directory
|
||||
- Support environment variable interpolation with `${VARIABLE}` syntax
|
||||
- Validate configurations before starting bots
|
||||
- Separate environment-specific settings in `.env` files
|
||||
|
||||
## Module Dependencies
|
||||
|
||||
### Import Rules
|
||||
- Core modules should not import from trading or monitoring
|
||||
- Platform-specific modules should only import from their own package and core/interfaces
|
||||
- Avoid circular imports between packages
|
||||
- Use dependency injection for cross-package dependencies
|
||||
|
||||
### Dependency Layers (from low to high level)
|
||||
1. **utils/** - Utilities and helpers (no business logic dependencies)
|
||||
2. **interfaces/** - Abstract base classes and protocols
|
||||
3. **core/** - Blockchain and infrastructure (depends on utils, interfaces)
|
||||
4. **platforms/** - Platform implementations (depends on core, interfaces)
|
||||
5. **trading/** - Trading logic (depends on core, platforms, interfaces)
|
||||
6. **monitoring/** - Event listening (depends on core, platforms, interfaces)
|
||||
7. **bot_runner.py** - Main orchestrator (depends on all layers)
|
||||
|
||||
## Async Architecture
|
||||
|
||||
### Event Loop Management
|
||||
- Use uvloop for better performance
|
||||
- Set event loop policy at application startup
|
||||
- Use asyncio.create_task() for concurrent operations
|
||||
- Implement proper cleanup on shutdown
|
||||
|
||||
### Connection Management
|
||||
- Use connection pooling for HTTP clients
|
||||
- Implement reconnection logic for WebSocket connections
|
||||
- Cache expensive resources (blockhash, account info)
|
||||
- Use async context managers for resource cleanup
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### Test Organization
|
||||
- Use `learning-examples/` for integration testing and validation
|
||||
- Test platform-specific components independently
|
||||
- Mock external dependencies (RPC calls, WebSocket connections)
|
||||
- Validate configurations with actual bot startup
|
||||
|
||||
### Test Data
|
||||
- Use test networks for development
|
||||
- Never test with real funds or production keys
|
||||
- Create fixtures for common test scenarios
|
||||
- Document test account requirements
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
### Caching Strategy
|
||||
- Cache recent blockhash in background task
|
||||
- Cache account information where appropriate
|
||||
- Use local caching for IDL data
|
||||
- Implement TTL for cached data
|
||||
|
||||
### Resource Management
|
||||
- Limit concurrent operations based on RPC provider limits
|
||||
- Implement backoff strategies for failed requests
|
||||
- Use separate processes for production bot instances
|
||||
- Monitor memory usage in long-running processes
|
||||
@@ -0,0 +1,150 @@
|
||||
---
|
||||
inclusion: always
|
||||
---
|
||||
|
||||
# Python Code Style Rules
|
||||
|
||||
## Formatting Standards
|
||||
|
||||
### Ruff Configuration Compliance
|
||||
- Use 88 character line length limit
|
||||
- Use 4 spaces for indentation (never tabs)
|
||||
- Use double quotes for strings consistently
|
||||
- Target Python 3.11+ features and syntax
|
||||
- Enable automatic import sorting and organization
|
||||
|
||||
### Import Organization
|
||||
```python
|
||||
# Standard library imports first
|
||||
import asyncio
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
# Third-party imports second
|
||||
import aiohttp
|
||||
from solana.rpc.async_api import AsyncClient
|
||||
|
||||
# Local imports last
|
||||
from config_loader import load_bot_config
|
||||
from utils.logger import get_logger
|
||||
```
|
||||
|
||||
### Type Annotations
|
||||
- Add type hints to ALL public functions and methods
|
||||
- Use modern typing syntax (Python 3.9+ union syntax where applicable)
|
||||
- Include return type annotations
|
||||
- Use `from typing import Any` for complex types
|
||||
|
||||
```python
|
||||
def process_transaction(tx_data: dict[str, Any]) -> bool:
|
||||
"""Process transaction data and return success status."""
|
||||
pass
|
||||
|
||||
async def fetch_data(endpoint: str) -> dict[str, Any] | None:
|
||||
"""Fetch data from endpoint, return None on failure."""
|
||||
pass
|
||||
```
|
||||
|
||||
## Documentation Standards
|
||||
|
||||
### Docstring Format
|
||||
Use Google-style docstrings for all functions and classes:
|
||||
|
||||
```python
|
||||
def calculate_slippage(amount: float, slippage_percent: float) -> float:
|
||||
"""Calculate slippage amount for a trade.
|
||||
|
||||
Args:
|
||||
amount: The trade amount in SOL
|
||||
slippage_percent: Slippage percentage (0.1 = 10%)
|
||||
|
||||
Returns:
|
||||
The calculated slippage amount
|
||||
|
||||
Raises:
|
||||
ValueError: If slippage_percent is negative
|
||||
"""
|
||||
if slippage_percent < 0:
|
||||
raise ValueError("Slippage percentage cannot be negative")
|
||||
return amount * slippage_percent
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Comprehensive Exception Handling
|
||||
- Use try-catch blocks for all external operations (RPC calls, file I/O)
|
||||
- Log exceptions with context using `logging.exception()`
|
||||
- Provide meaningful error messages
|
||||
- Don't suppress exceptions without good reason
|
||||
|
||||
```python
|
||||
try:
|
||||
result = await client.get_account_info(address)
|
||||
logger.info(f"Successfully fetched account info for {address}")
|
||||
except Exception as e:
|
||||
logger.exception(f"Failed to fetch account info for {address}: {e}")
|
||||
raise
|
||||
```
|
||||
|
||||
## Logging Standards
|
||||
|
||||
### Logger Usage
|
||||
- Use `get_logger(__name__)` pattern consistently
|
||||
- Import from `utils.logger`
|
||||
- Use appropriate log levels (DEBUG, INFO, WARNING, ERROR)
|
||||
- Include context in log messages
|
||||
|
||||
```python
|
||||
from utils.logger import get_logger
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
# Good logging examples
|
||||
logger.info(f"Starting bot '{bot_name}' with platform {platform.value}")
|
||||
logger.warning(f"Transaction failed, attempt {attempt}/{max_attempts}")
|
||||
logger.error(f"Platform {platform.value} is not supported")
|
||||
```
|
||||
|
||||
## Security Rules
|
||||
|
||||
### Sensitive Data
|
||||
- NEVER hardcode private keys, API tokens, or secrets
|
||||
- Use environment variables for all sensitive configuration
|
||||
- Don't log sensitive information
|
||||
- Validate all external inputs
|
||||
|
||||
### Safe Practices
|
||||
```python
|
||||
# Good - using environment variables
|
||||
private_key = os.getenv("SOLANA_PRIVATE_KEY")
|
||||
if not private_key:
|
||||
raise ValueError("SOLANA_PRIVATE_KEY environment variable is required")
|
||||
|
||||
# Bad - hardcoded secrets
|
||||
private_key = "your_secret_key_here" # NEVER DO THIS
|
||||
```
|
||||
|
||||
## Code Quality
|
||||
|
||||
### Linting Compliance
|
||||
Ensure code passes all enabled Ruff rules:
|
||||
- Security best practices (S)
|
||||
- Type annotations (ANN)
|
||||
- Exception handling (BLE, TRY)
|
||||
- Code complexity (C90)
|
||||
- Pylint conventions (PL)
|
||||
- No commented-out code (ERA)
|
||||
|
||||
### Performance Considerations
|
||||
- Use async/await for I/O operations
|
||||
- Implement proper connection pooling for HTTP clients
|
||||
- Cache expensive computations when appropriate
|
||||
- Use uvloop for better async performance
|
||||
|
||||
```python
|
||||
# Set uvloop policy at module level
|
||||
import asyncio
|
||||
import uvloop
|
||||
|
||||
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
|
||||
```
|
||||
@@ -0,0 +1,248 @@
|
||||
---
|
||||
inclusion: always
|
||||
---
|
||||
|
||||
# Trading Bot Specific Rules
|
||||
|
||||
## Bot Configuration Standards
|
||||
|
||||
### YAML Configuration Structure
|
||||
Maintain consistent structure across all bot configuration files:
|
||||
|
||||
```yaml
|
||||
# Bot identification
|
||||
name: "bot-sniper-1"
|
||||
platform: "pump_fun" # or "lets_bonk"
|
||||
enabled: true # Allow disabling without removing config
|
||||
separate_process: true # Run in separate process for isolation
|
||||
|
||||
# Environment and connection
|
||||
env_file: ".env"
|
||||
rpc_endpoint: "${SOLANA_NODE_RPC_ENDPOINT}"
|
||||
wss_endpoint: "${SOLANA_NODE_WSS_ENDPOINT}"
|
||||
private_key: "${SOLANA_PRIVATE_KEY}"
|
||||
|
||||
# Platform-specific configurations
|
||||
geyser: # For faster data streams
|
||||
endpoint: "${GEYSER_ENDPOINT}"
|
||||
api_token: "${GEYSER_API_TOKEN}"
|
||||
auth_type: "x-token"
|
||||
|
||||
# Trading parameters
|
||||
trade:
|
||||
buy_amount: 0.0001 # SOL amount
|
||||
buy_slippage: 0.3 # 30%
|
||||
sell_slippage: 0.3
|
||||
exit_strategy: "time_based" # "tp_sl", "manual"
|
||||
extreme_fast_mode: true # Skip validations for speed
|
||||
```
|
||||
|
||||
### Environment Variable Usage
|
||||
- Use `${VARIABLE_NAME}` syntax for environment interpolation
|
||||
- Never hardcode sensitive values in YAML files
|
||||
- Validate all required environment variables on startup
|
||||
- Provide clear error messages for missing variables
|
||||
|
||||
## Trading Logic Rules
|
||||
|
||||
### Transaction Handling
|
||||
- Always use priority fees for competitive transaction inclusion
|
||||
- Implement retry mechanisms with exponential backoff
|
||||
- Cache recent blockhash to avoid repeated RPC calls
|
||||
- Use compute unit limits to prevent transaction failures
|
||||
|
||||
```python
|
||||
# Good transaction building pattern
|
||||
instructions = [
|
||||
set_compute_unit_limit(300_000),
|
||||
set_compute_unit_price(priority_fee),
|
||||
# ... trading instructions
|
||||
]
|
||||
```
|
||||
|
||||
### Risk Management
|
||||
- Implement position size limits
|
||||
- Use slippage protection on all trades
|
||||
- Set maximum hold times to prevent stuck positions
|
||||
- Validate token data before trading
|
||||
|
||||
```python
|
||||
# Risk validation example
|
||||
if token_age > self.max_token_age:
|
||||
logger.warning(f"Token {mint} too old ({token_age}s), skipping")
|
||||
return False
|
||||
|
||||
if buy_amount > self.max_position_size:
|
||||
logger.error(f"Buy amount {buy_amount} exceeds max position size")
|
||||
return False
|
||||
```
|
||||
|
||||
### Exit Strategies
|
||||
Implement multiple exit strategy types:
|
||||
|
||||
1. **Time-based**: Hold for fixed duration
|
||||
2. **Take Profit/Stop Loss**: Price-based exits
|
||||
3. **Manual**: No automatic selling
|
||||
|
||||
```python
|
||||
class ExitStrategy(Enum):
|
||||
TIME_BASED = "time_based"
|
||||
TP_SL = "tp_sl"
|
||||
MANUAL = "manual"
|
||||
```
|
||||
|
||||
## Platform Integration Rules
|
||||
|
||||
### Multi-Platform Support
|
||||
- Use platform enum for type safety
|
||||
- Implement platform-specific address providers
|
||||
- Abstract platform differences in universal components
|
||||
- Validate platform-listener combinations
|
||||
|
||||
```python
|
||||
# Platform validation
|
||||
if not validate_platform_listener_combination(platform, listener_type):
|
||||
supported = get_supported_listeners_for_platform(platform)
|
||||
raise ConfigurationError(
|
||||
f"Listener '{listener_type}' not supported for {platform.value}. "
|
||||
f"Supported: {supported}"
|
||||
)
|
||||
```
|
||||
|
||||
### Listener Types
|
||||
Support multiple data source types:
|
||||
- **geyser**: Fastest, requires special endpoint
|
||||
- **logs**: WebSocket log subscription
|
||||
- **blocks**: Block subscription (not all providers support)
|
||||
- **pumpportal**: Third-party aggregator
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Speed vs Accuracy Tradeoffs
|
||||
- **Extreme Fast Mode**: Skip validations and price checks for speed
|
||||
- **Normal Mode**: Full validation and price checks
|
||||
- **Marry Mode**: Only buy, never sell (accumulation strategy)
|
||||
- **YOLO Mode**: Continuous trading without cooldowns
|
||||
|
||||
### Caching Strategy
|
||||
```python
|
||||
# Cache expensive operations
|
||||
self._cached_blockhash: Hash | None = None
|
||||
self._blockhash_lock = asyncio.Lock()
|
||||
|
||||
# Background blockhash updater
|
||||
async def start_blockhash_updater(self, interval: float = 5.0):
|
||||
while True:
|
||||
try:
|
||||
blockhash = await self.get_latest_blockhash()
|
||||
async with self._blockhash_lock:
|
||||
self._cached_blockhash = blockhash
|
||||
except Exception as e:
|
||||
logger.exception(f"Failed to update blockhash: {e}")
|
||||
await asyncio.sleep(interval)
|
||||
```
|
||||
|
||||
## Monitoring and Logging
|
||||
|
||||
### Log File Management
|
||||
- Create timestamped log files per bot instance
|
||||
- Format: `{bot_name}_{timestamp}.log`
|
||||
- Store in `logs/` directory
|
||||
- Implement log rotation for long-running bots
|
||||
|
||||
### Trading Event Logging
|
||||
Log all significant events with context:
|
||||
|
||||
```python
|
||||
# Good logging examples
|
||||
logger.info(f"New token detected: {mint} by {creator}")
|
||||
logger.info(f"Buy transaction submitted: {signature}")
|
||||
logger.warning(f"Transaction failed, attempt {attempt}/{max_attempts}")
|
||||
logger.error(f"Platform {platform.value} not supported")
|
||||
```
|
||||
|
||||
### Performance Metrics
|
||||
Track key performance indicators:
|
||||
- Token detection latency
|
||||
- Transaction confirmation time
|
||||
- Success/failure rates
|
||||
- Slippage and fill rates
|
||||
|
||||
## Security and Safety Rules
|
||||
|
||||
### Private Key Management
|
||||
- Store private keys only in environment variables
|
||||
- Never log or expose private keys
|
||||
- Use separate wallets for testing vs production
|
||||
- Implement wallet balance checks before trading
|
||||
|
||||
### Input Validation
|
||||
```python
|
||||
# Validate all external inputs
|
||||
def validate_mint_address(mint_str: str) -> bool:
|
||||
try:
|
||||
mint = Pubkey.from_string(mint_str)
|
||||
return len(str(mint)) == 44 # Valid Solana address length
|
||||
except Exception:
|
||||
return False
|
||||
```
|
||||
|
||||
### Error Recovery
|
||||
- Implement graceful shutdown on critical errors
|
||||
- Provide cleanup mechanisms for stuck positions
|
||||
- Support manual intervention modes
|
||||
- Log all errors with sufficient context for debugging
|
||||
|
||||
## Testing and Validation
|
||||
|
||||
### Learning Examples Usage
|
||||
Use learning examples for:
|
||||
- Testing new features before integration
|
||||
- Validating platform-specific functionality
|
||||
- Performance benchmarking
|
||||
- Educational purposes for new developers
|
||||
|
||||
```bash
|
||||
# Test platform connectivity
|
||||
uv run learning-examples/fetch_price.py
|
||||
|
||||
# Validate bonding curve calculations
|
||||
uv run learning-examples/compute_associated_bonding_curve.py
|
||||
|
||||
# Compare listener performance
|
||||
uv run learning-examples/listen-new-tokens/compare_listeners.py
|
||||
```
|
||||
|
||||
### Configuration Testing
|
||||
- Validate YAML syntax and required fields
|
||||
- Test environment variable interpolation
|
||||
- Verify platform-listener compatibility
|
||||
- Check wallet connectivity and balance
|
||||
|
||||
## Deployment Guidelines
|
||||
|
||||
### Production Checklist
|
||||
1. Test configuration with learning examples
|
||||
2. Verify environment variables are set
|
||||
3. Check wallet has sufficient SOL for gas fees
|
||||
4. Enable separate processes for isolation
|
||||
5. Monitor logs for successful startup
|
||||
6. Implement monitoring and alerting
|
||||
|
||||
### Multi-Bot Management
|
||||
- Use descriptive bot names in configurations
|
||||
- Separate log files per bot instance
|
||||
- Monitor resource usage across all bots
|
||||
- Implement centralized configuration management
|
||||
|
||||
```python
|
||||
# Bot process management
|
||||
if cfg.get("separate_process", False):
|
||||
p = multiprocessing.Process(
|
||||
target=run_bot_process,
|
||||
args=(str(file),),
|
||||
name=f"bot-{bot_name}"
|
||||
)
|
||||
p.start()
|
||||
processes.append(p)
|
||||
```
|
||||
@@ -0,0 +1,140 @@
|
||||
---
|
||||
trigger: always_on
|
||||
---
|
||||
|
||||
# Project Architecture Rules
|
||||
|
||||
## Directory Structure
|
||||
|
||||
### Package Organization
|
||||
Maintain clear separation of concerns:
|
||||
|
||||
```
|
||||
src/
|
||||
├── __init__.py
|
||||
├── bot_runner.py # Main entry point
|
||||
├── config_loader.py # Configuration management
|
||||
├── core/ # Core blockchain functionality
|
||||
│ ├── client.py # Solana RPC client abstraction
|
||||
│ ├── wallet.py # Wallet operations
|
||||
│ └── priority_fee/ # Fee management
|
||||
├── platforms/ # Platform-specific implementations
|
||||
│ ├── pumpfun/ # pump.fun specific code
|
||||
│ └── letsbonk/ # letsbonk.fun specific code
|
||||
├── trading/ # Trading logic
|
||||
│ ├── base.py # Base trading classes
|
||||
│ ├── universal_trader.py # Platform-agnostic trader
|
||||
│ └── position.py # Position management
|
||||
├── monitoring/ # Event listening and monitoring
|
||||
│ ├── base_listener.py # Base listener interface
|
||||
│ └── universal_*_listener.py # Specific listeners
|
||||
├── interfaces/ # Abstract base classes
|
||||
└── utils/ # Utilities and helpers
|
||||
├── logger.py # Logging utilities
|
||||
└── idl_manager.py # IDL management
|
||||
```
|
||||
|
||||
### File Naming Conventions
|
||||
- Use snake_case for all Python files and directories
|
||||
- Prefix abstract base classes with "Base" or put in `interfaces/`
|
||||
- Use "Universal" prefix for platform-agnostic implementations
|
||||
- Group related functionality in subdirectories
|
||||
|
||||
## Design Patterns
|
||||
|
||||
### Platform Abstraction
|
||||
Implement platform-specific functionality using the factory pattern:
|
||||
|
||||
```python
|
||||
# interfaces/core.py - Define abstract interfaces
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
class AddressProvider(ABC):
|
||||
@abstractmethod
|
||||
def get_program_address(self) -> str:
|
||||
pass
|
||||
|
||||
# platforms/pumpfun/address_provider.py - Concrete implementation
|
||||
class PumpFunAddressProvider(AddressProvider):
|
||||
def get_program_address(self) -> str:
|
||||
return "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"
|
||||
```
|
||||
|
||||
### Universal Components
|
||||
Create platform-agnostic wrappers that delegate to platform-specific implementations:
|
||||
|
||||
```python
|
||||
class UniversalTrader:
|
||||
def __init__(self, platform: Platform, **kwargs):
|
||||
self.platform = platform
|
||||
self.platform_trader = self._create_platform_trader()
|
||||
|
||||
def _create_platform_trader(self):
|
||||
# Factory method to create platform-specific trader
|
||||
pass
|
||||
```
|
||||
|
||||
### Configuration Management
|
||||
- Use YAML files for bot configurations in `bots/` directory
|
||||
- Support environment variable interpolation with `${VARIABLE}` syntax
|
||||
- Validate configurations before starting bots
|
||||
- Separate environment-specific settings in `.env` files
|
||||
|
||||
## Module Dependencies
|
||||
|
||||
### Import Rules
|
||||
- Core modules should not import from trading or monitoring
|
||||
- Platform-specific modules should only import from their own package and core/interfaces
|
||||
- Avoid circular imports between packages
|
||||
- Use dependency injection for cross-package dependencies
|
||||
|
||||
### Dependency Layers (from low to high level)
|
||||
1. **utils/** - Utilities and helpers (no business logic dependencies)
|
||||
2. **interfaces/** - Abstract base classes and protocols
|
||||
3. **core/** - Blockchain and infrastructure (depends on utils, interfaces)
|
||||
4. **platforms/** - Platform implementations (depends on core, interfaces)
|
||||
5. **trading/** - Trading logic (depends on core, platforms, interfaces)
|
||||
6. **monitoring/** - Event listening (depends on core, platforms, interfaces)
|
||||
7. **bot_runner.py** - Main orchestrator (depends on all layers)
|
||||
|
||||
## Async Architecture
|
||||
|
||||
### Event Loop Management
|
||||
- Use uvloop for better performance
|
||||
- Set event loop policy at application startup
|
||||
- Use asyncio.create_task() for concurrent operations
|
||||
- Implement proper cleanup on shutdown
|
||||
|
||||
### Connection Management
|
||||
- Use connection pooling for HTTP clients
|
||||
- Implement reconnection logic for WebSocket connections
|
||||
- Cache expensive resources (blockhash, account info)
|
||||
- Use async context managers for resource cleanup
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### Test Organization
|
||||
- Use `learning-examples/` for integration testing and validation
|
||||
- Test platform-specific components independently
|
||||
- Mock external dependencies (RPC calls, WebSocket connections)
|
||||
- Validate configurations with actual bot startup
|
||||
|
||||
### Test Data
|
||||
- Use test networks for development
|
||||
- Never test with real funds or production keys
|
||||
- Create fixtures for common test scenarios
|
||||
- Document test account requirements
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
### Caching Strategy
|
||||
- Cache recent blockhash in background task
|
||||
- Cache account information where appropriate
|
||||
- Use local caching for IDL data
|
||||
- Implement TTL for cached data
|
||||
|
||||
### Resource Management
|
||||
- Limit concurrent operations based on RPC provider limits
|
||||
- Implement backoff strategies for failed requests
|
||||
- Use separate processes for production bot instances
|
||||
- Monitor memory usage in long-running processes
|
||||
@@ -0,0 +1,150 @@
|
||||
---
|
||||
trigger: always_on
|
||||
---
|
||||
|
||||
# Python Code Style Rules
|
||||
|
||||
## Formatting Standards
|
||||
|
||||
### Ruff Configuration Compliance
|
||||
- Use 88 character line length limit
|
||||
- Use 4 spaces for indentation (never tabs)
|
||||
- Use double quotes for strings consistently
|
||||
- Target Python 3.11+ features and syntax
|
||||
- Enable automatic import sorting and organization
|
||||
|
||||
### Import Organization
|
||||
```python
|
||||
# Standard library imports first
|
||||
import asyncio
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
# Third-party imports second
|
||||
import aiohttp
|
||||
from solana.rpc.async_api import AsyncClient
|
||||
|
||||
# Local imports last
|
||||
from config_loader import load_bot_config
|
||||
from utils.logger import get_logger
|
||||
```
|
||||
|
||||
### Type Annotations
|
||||
- Add type hints to ALL public functions and methods
|
||||
- Use modern typing syntax (Python 3.9+ union syntax where applicable)
|
||||
- Include return type annotations
|
||||
- Use `from typing import Any` for complex types
|
||||
|
||||
```python
|
||||
def process_transaction(tx_data: dict[str, Any]) -> bool:
|
||||
"""Process transaction data and return success status."""
|
||||
pass
|
||||
|
||||
async def fetch_data(endpoint: str) -> dict[str, Any] | None:
|
||||
"""Fetch data from endpoint, return None on failure."""
|
||||
pass
|
||||
```
|
||||
|
||||
## Documentation Standards
|
||||
|
||||
### Docstring Format
|
||||
Use Google-style docstrings for all functions and classes:
|
||||
|
||||
```python
|
||||
def calculate_slippage(amount: float, slippage_percent: float) -> float:
|
||||
"""Calculate slippage amount for a trade.
|
||||
|
||||
Args:
|
||||
amount: The trade amount in SOL
|
||||
slippage_percent: Slippage percentage (0.1 = 10%)
|
||||
|
||||
Returns:
|
||||
The calculated slippage amount
|
||||
|
||||
Raises:
|
||||
ValueError: If slippage_percent is negative
|
||||
"""
|
||||
if slippage_percent < 0:
|
||||
raise ValueError("Slippage percentage cannot be negative")
|
||||
return amount * slippage_percent
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Comprehensive Exception Handling
|
||||
- Use try-catch blocks for all external operations (RPC calls, file I/O)
|
||||
- Log exceptions with context using `logging.exception()`
|
||||
- Provide meaningful error messages
|
||||
- Don't suppress exceptions without good reason
|
||||
|
||||
```python
|
||||
try:
|
||||
result = await client.get_account_info(address)
|
||||
logger.info(f"Successfully fetched account info for {address}")
|
||||
except Exception as e:
|
||||
logger.exception(f"Failed to fetch account info for {address}: {e}")
|
||||
raise
|
||||
```
|
||||
|
||||
## Logging Standards
|
||||
|
||||
### Logger Usage
|
||||
- Use `get_logger(__name__)` pattern consistently
|
||||
- Import from `utils.logger`
|
||||
- Use appropriate log levels (DEBUG, INFO, WARNING, ERROR)
|
||||
- Include context in log messages
|
||||
|
||||
```python
|
||||
from utils.logger import get_logger
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
# Good logging examples
|
||||
logger.info(f"Starting bot '{bot_name}' with platform {platform.value}")
|
||||
logger.warning(f"Transaction failed, attempt {attempt}/{max_attempts}")
|
||||
logger.error(f"Platform {platform.value} is not supported")
|
||||
```
|
||||
|
||||
## Security Rules
|
||||
|
||||
### Sensitive Data
|
||||
- NEVER hardcode private keys, API tokens, or secrets
|
||||
- Use environment variables for all sensitive configuration
|
||||
- Don't log sensitive information
|
||||
- Validate all external inputs
|
||||
|
||||
### Safe Practices
|
||||
```python
|
||||
# Good - using environment variables
|
||||
private_key = os.getenv("SOLANA_PRIVATE_KEY")
|
||||
if not private_key:
|
||||
raise ValueError("SOLANA_PRIVATE_KEY environment variable is required")
|
||||
|
||||
# Bad - hardcoded secrets
|
||||
private_key = "your_secret_key_here" # NEVER DO THIS
|
||||
```
|
||||
|
||||
## Code Quality
|
||||
|
||||
### Linting Compliance
|
||||
Ensure code passes all enabled Ruff rules:
|
||||
- Security best practices (S)
|
||||
- Type annotations (ANN)
|
||||
- Exception handling (BLE, TRY)
|
||||
- Code complexity (C90)
|
||||
- Pylint conventions (PL)
|
||||
- No commented-out code (ERA)
|
||||
|
||||
### Performance Considerations
|
||||
- Use async/await for I/O operations
|
||||
- Implement proper connection pooling for HTTP clients
|
||||
- Cache expensive computations when appropriate
|
||||
- Use uvloop for better async performance
|
||||
|
||||
```python
|
||||
# Set uvloop policy at module level
|
||||
import asyncio
|
||||
import uvloop
|
||||
|
||||
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
|
||||
```
|
||||
@@ -0,0 +1,248 @@
|
||||
---
|
||||
trigger: always_on
|
||||
---
|
||||
|
||||
# Trading Bot Specific Rules
|
||||
|
||||
## Bot Configuration Standards
|
||||
|
||||
### YAML Configuration Structure
|
||||
Maintain consistent structure across all bot configuration files:
|
||||
|
||||
```yaml
|
||||
# Bot identification
|
||||
name: "bot-sniper-1"
|
||||
platform: "pump_fun" # or "lets_bonk"
|
||||
enabled: true # Allow disabling without removing config
|
||||
separate_process: true # Run in separate process for isolation
|
||||
|
||||
# Environment and connection
|
||||
env_file: ".env"
|
||||
rpc_endpoint: "${SOLANA_NODE_RPC_ENDPOINT}"
|
||||
wss_endpoint: "${SOLANA_NODE_WSS_ENDPOINT}"
|
||||
private_key: "${SOLANA_PRIVATE_KEY}"
|
||||
|
||||
# Platform-specific configurations
|
||||
geyser: # For faster data streams
|
||||
endpoint: "${GEYSER_ENDPOINT}"
|
||||
api_token: "${GEYSER_API_TOKEN}"
|
||||
auth_type: "x-token"
|
||||
|
||||
# Trading parameters
|
||||
trade:
|
||||
buy_amount: 0.0001 # SOL amount
|
||||
buy_slippage: 0.3 # 30%
|
||||
sell_slippage: 0.3
|
||||
exit_strategy: "time_based" # "tp_sl", "manual"
|
||||
extreme_fast_mode: true # Skip validations for speed
|
||||
```
|
||||
|
||||
### Environment Variable Usage
|
||||
- Use `${VARIABLE_NAME}` syntax for environment interpolation
|
||||
- Never hardcode sensitive values in YAML files
|
||||
- Validate all required environment variables on startup
|
||||
- Provide clear error messages for missing variables
|
||||
|
||||
## Trading Logic Rules
|
||||
|
||||
### Transaction Handling
|
||||
- Always use priority fees for competitive transaction inclusion
|
||||
- Implement retry mechanisms with exponential backoff
|
||||
- Cache recent blockhash to avoid repeated RPC calls
|
||||
- Use compute unit limits to prevent transaction failures
|
||||
|
||||
```python
|
||||
# Good transaction building pattern
|
||||
instructions = [
|
||||
set_compute_unit_limit(300_000),
|
||||
set_compute_unit_price(priority_fee),
|
||||
# ... trading instructions
|
||||
]
|
||||
```
|
||||
|
||||
### Risk Management
|
||||
- Implement position size limits
|
||||
- Use slippage protection on all trades
|
||||
- Set maximum hold times to prevent stuck positions
|
||||
- Validate token data before trading
|
||||
|
||||
```python
|
||||
# Risk validation example
|
||||
if token_age > self.max_token_age:
|
||||
logger.warning(f"Token {mint} too old ({token_age}s), skipping")
|
||||
return False
|
||||
|
||||
if buy_amount > self.max_position_size:
|
||||
logger.error(f"Buy amount {buy_amount} exceeds max position size")
|
||||
return False
|
||||
```
|
||||
|
||||
### Exit Strategies
|
||||
Implement multiple exit strategy types:
|
||||
|
||||
1. **Time-based**: Hold for fixed duration
|
||||
2. **Take Profit/Stop Loss**: Price-based exits
|
||||
3. **Manual**: No automatic selling
|
||||
|
||||
```python
|
||||
class ExitStrategy(Enum):
|
||||
TIME_BASED = "time_based"
|
||||
TP_SL = "tp_sl"
|
||||
MANUAL = "manual"
|
||||
```
|
||||
|
||||
## Platform Integration Rules
|
||||
|
||||
### Multi-Platform Support
|
||||
- Use platform enum for type safety
|
||||
- Implement platform-specific address providers
|
||||
- Abstract platform differences in universal components
|
||||
- Validate platform-listener combinations
|
||||
|
||||
```python
|
||||
# Platform validation
|
||||
if not validate_platform_listener_combination(platform, listener_type):
|
||||
supported = get_supported_listeners_for_platform(platform)
|
||||
raise ConfigurationError(
|
||||
f"Listener '{listener_type}' not supported for {platform.value}. "
|
||||
f"Supported: {supported}"
|
||||
)
|
||||
```
|
||||
|
||||
### Listener Types
|
||||
Support multiple data source types:
|
||||
- **geyser**: Fastest, requires special endpoint
|
||||
- **logs**: WebSocket log subscription
|
||||
- **blocks**: Block subscription (not all providers support)
|
||||
- **pumpportal**: Third-party aggregator
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Speed vs Accuracy Tradeoffs
|
||||
- **Extreme Fast Mode**: Skip validations and price checks for speed
|
||||
- **Normal Mode**: Full validation and price checks
|
||||
- **Marry Mode**: Only buy, never sell (accumulation strategy)
|
||||
- **YOLO Mode**: Continuous trading without cooldowns
|
||||
|
||||
### Caching Strategy
|
||||
```python
|
||||
# Cache expensive operations
|
||||
self._cached_blockhash: Hash | None = None
|
||||
self._blockhash_lock = asyncio.Lock()
|
||||
|
||||
# Background blockhash updater
|
||||
async def start_blockhash_updater(self, interval: float = 5.0):
|
||||
while True:
|
||||
try:
|
||||
blockhash = await self.get_latest_blockhash()
|
||||
async with self._blockhash_lock:
|
||||
self._cached_blockhash = blockhash
|
||||
except Exception as e:
|
||||
logger.exception(f"Failed to update blockhash: {e}")
|
||||
await asyncio.sleep(interval)
|
||||
```
|
||||
|
||||
## Monitoring and Logging
|
||||
|
||||
### Log File Management
|
||||
- Create timestamped log files per bot instance
|
||||
- Format: `{bot_name}_{timestamp}.log`
|
||||
- Store in `logs/` directory
|
||||
- Implement log rotation for long-running bots
|
||||
|
||||
### Trading Event Logging
|
||||
Log all significant events with context:
|
||||
|
||||
```python
|
||||
# Good logging examples
|
||||
logger.info(f"New token detected: {mint} by {creator}")
|
||||
logger.info(f"Buy transaction submitted: {signature}")
|
||||
logger.warning(f"Transaction failed, attempt {attempt}/{max_attempts}")
|
||||
logger.error(f"Platform {platform.value} not supported")
|
||||
```
|
||||
|
||||
### Performance Metrics
|
||||
Track key performance indicators:
|
||||
- Token detection latency
|
||||
- Transaction confirmation time
|
||||
- Success/failure rates
|
||||
- Slippage and fill rates
|
||||
|
||||
## Security and Safety Rules
|
||||
|
||||
### Private Key Management
|
||||
- Store private keys only in environment variables
|
||||
- Never log or expose private keys
|
||||
- Use separate wallets for testing vs production
|
||||
- Implement wallet balance checks before trading
|
||||
|
||||
### Input Validation
|
||||
```python
|
||||
# Validate all external inputs
|
||||
def validate_mint_address(mint_str: str) -> bool:
|
||||
try:
|
||||
mint = Pubkey.from_string(mint_str)
|
||||
return len(str(mint)) == 44 # Valid Solana address length
|
||||
except Exception:
|
||||
return False
|
||||
```
|
||||
|
||||
### Error Recovery
|
||||
- Implement graceful shutdown on critical errors
|
||||
- Provide cleanup mechanisms for stuck positions
|
||||
- Support manual intervention modes
|
||||
- Log all errors with sufficient context for debugging
|
||||
|
||||
## Testing and Validation
|
||||
|
||||
### Learning Examples Usage
|
||||
Use learning examples for:
|
||||
- Testing new features before integration
|
||||
- Validating platform-specific functionality
|
||||
- Performance benchmarking
|
||||
- Educational purposes for new developers
|
||||
|
||||
```bash
|
||||
# Test platform connectivity
|
||||
uv run learning-examples/fetch_price.py
|
||||
|
||||
# Validate bonding curve calculations
|
||||
uv run learning-examples/compute_associated_bonding_curve.py
|
||||
|
||||
# Compare listener performance
|
||||
uv run learning-examples/listen-new-tokens/compare_listeners.py
|
||||
```
|
||||
|
||||
### Configuration Testing
|
||||
- Validate YAML syntax and required fields
|
||||
- Test environment variable interpolation
|
||||
- Verify platform-listener compatibility
|
||||
- Check wallet connectivity and balance
|
||||
|
||||
## Deployment Guidelines
|
||||
|
||||
### Production Checklist
|
||||
1. Test configuration with learning examples
|
||||
2. Verify environment variables are set
|
||||
3. Check wallet has sufficient SOL for gas fees
|
||||
4. Enable separate processes for isolation
|
||||
5. Monitor logs for successful startup
|
||||
6. Implement monitoring and alerting
|
||||
|
||||
### Multi-Bot Management
|
||||
- Use descriptive bot names in configurations
|
||||
- Separate log files per bot instance
|
||||
- Monitor resource usage across all bots
|
||||
- Implement centralized configuration management
|
||||
|
||||
```python
|
||||
# Bot process management
|
||||
if cfg.get("separate_process", False):
|
||||
p = multiprocessing.Process(
|
||||
target=run_bot_process,
|
||||
args=(str(file),),
|
||||
name=f"bot-{bot_name}"
|
||||
)
|
||||
p.start()
|
||||
processes.append(p)
|
||||
```
|
||||
Reference in New Issue
Block a user