feat(core): add configurable cu limits

This commit is contained in:
smypmsa
2025-09-03 15:05:12 +00:00
parent e1e15dd539
commit 9731b179cc
12 changed files with 185 additions and 17 deletions
+7
View File
@@ -50,6 +50,13 @@ priority_fees:
extra_percentage: 0.0 # Percentage increase on riority fee regardless of the calculation method (0.1 = 10%)
hard_cap: 1_000_000 # Maximum allowable fee in microlamports to prevent excessive spending
# Compute unit limits for transaction processing
# Operation-specific defaults are used if not specified: buy=100K, sell=60K
compute_units:
# Override default CU limits for this platform
# buy: 100_000 # Buy operations (ATA creation + trading)
# sell: 60_000 # Sell operations (just trading)
# Filters for token selection
filters:
match_string: null # Only process tokens with this string in name/symbol
+8 -1
View File
@@ -8,7 +8,7 @@ rpc_endpoint: "${SOLANA_NODE_RPC_ENDPOINT}"
wss_endpoint: "${SOLANA_NODE_WSS_ENDPOINT}"
private_key: "${SOLANA_PRIVATE_KEY}"
enabled: true # You can turn off the bot w/o removing its config
enabled: false # You can turn off the bot w/o removing its config
separate_process: true
# Options: "pump_fun" (default), "lets_bonk"
@@ -50,6 +50,13 @@ priority_fees:
extra_percentage: 0.0 # Percentage increase on riority fee regardless of the calculation method (0.1 = 10%)
hard_cap: 200_000 # Maximum allowable fee in microlamports to prevent excessive spending
# Compute unit limits for transaction processing
# Operation-specific defaults are used if not specified: buy=100K, sell=60K
compute_units:
# Override default CU limits for this platform
# buy: 100_000 # Buy operations (ATA creation + trading)
# sell: 60_000 # Sell operations (just trading)
# Filters for token selection
filters:
match_string: null # Only process tokens with this string in name/symbol
+9 -2
View File
@@ -8,11 +8,11 @@ rpc_endpoint: "${SOLANA_NODE_RPC_ENDPOINT}"
wss_endpoint: "${SOLANA_NODE_WSS_ENDPOINT}"
private_key: "${SOLANA_PRIVATE_KEY}"
enabled: false # You can turn off the bot w/o removing its config
enabled: true # You can turn off the bot w/o removing its config
separate_process: true
# Options: "pump_fun" (default), "lets_bonk"
platform: "lets_bonk"
platform: "pump_fun"
# Geyser configuration (fastest method for getting updates)
geyser:
@@ -50,6 +50,13 @@ priority_fees:
extra_percentage: 0.0 # Percentage increase on riority fee regardless of the calculation method (0.1 = 10%)
hard_cap: 200_000 # Maximum allowable fee in microlamports to prevent excessive spending
# Compute unit limits for transaction processing
# Operation-specific defaults are used if not specified: buy=100K, sell=60K
compute_units:
# Override default CU limits for this platform
# buy: 100_000 # Buy operations (ATA creation + trading)
# sell: 60_000 # Sell operations (just trading)
# Filters for token selection
filters:
match_string: null # Only process tokens with this string in name/symbol
+7
View File
@@ -48,6 +48,13 @@ priority_fees:
extra_percentage: 0.0 # Percentage increase on riority fee regardless of the calculation method (0.1 = 10%)
hard_cap: 200_000 # Maximum allowable fee in microlamports to prevent excessive spending
# Compute unit limits for transaction processing
# Operation-specific defaults are used if not specified: buy=100K, sell=60K
compute_units:
# Override default CU limits for this platform
# buy: 100_000 # Buy operations (ATA creation + trading)
# sell: 60_000 # Sell operations (just trading)
# Filters for token selection
filters:
match_string: null # Only process tokens with this string in name/symbol
+2
View File
@@ -135,6 +135,8 @@ async def start_bot(config_path: str):
bro_address=cfg["filters"].get("bro_address"),
marry_mode=cfg["filters"].get("marry_mode", False),
yolo_mode=cfg["filters"].get("yolo_mode", False),
# Compute unit configuration
compute_units=cfg.get("compute_units", {}),
)
await trader.start()
+15 -6
View File
@@ -145,15 +145,18 @@ class SolanaClient:
skip_preflight: bool = True,
max_retries: int = 3,
priority_fee: int | None = None,
compute_unit_limit: int | None = None,
) -> str:
"""
Send a transaction with optional priority fee.
Send a transaction with optional priority fee and compute unit limit.
Args:
instructions: List of instructions to include in the transaction.
signer_keypair: Keypair to sign the transaction.
skip_preflight: Whether to skip preflight checks.
max_retries: Maximum number of retry attempts.
priority_fee: Optional priority fee in microlamports.
compute_unit_limit: Optional compute unit limit. Defaults to 85,000 if not provided.
Returns:
Transaction signature.
@@ -164,12 +167,18 @@ class SolanaClient:
f"Priority fee in microlamports: {priority_fee if priority_fee else 0}"
)
# Add priority fee instructions if applicable
# Add compute budget instructions if applicable
if priority_fee is not None or compute_unit_limit is not None:
fee_instructions = []
# Set compute unit limit (use provided value or default to 85,000)
cu_limit = compute_unit_limit if compute_unit_limit is not None else 85_000
fee_instructions.append(set_compute_unit_limit(cu_limit))
# Set priority fee if provided
if priority_fee is not None:
fee_instructions = [
set_compute_unit_limit(85_000), # Default compute unit limit
set_compute_unit_price(priority_fee),
]
fee_instructions.append(set_compute_unit_price(priority_fee))
instructions = fee_instructions + instructions
recent_blockhash = await self.get_cached_blockhash()
+24
View File
@@ -201,6 +201,30 @@ class InstructionBuilder(ABC):
"""
pass
@abstractmethod
def get_buy_compute_unit_limit(self, config_override: int | None = None) -> int:
"""Get the recommended compute unit limit for buy operations.
Args:
config_override: Optional override from configuration
Returns:
Compute unit limit appropriate for buy operations
"""
pass
@abstractmethod
def get_sell_compute_unit_limit(self, config_override: int | None = None) -> int:
"""Get the recommended compute unit limit for sell operations.
Args:
config_override: Optional override from configuration
Returns:
Compute unit limit appropriate for sell operations
"""
pass
class CurveManager(ABC):
"""Abstract interface for platform-specific price calculations and pool state management."""
@@ -460,3 +460,31 @@ class LetsBonkInstructionBuilder(InstructionBuilder):
Token amount in decimal form
"""
return token_amount_raw / 10**TOKEN_DECIMALS
def get_buy_compute_unit_limit(self, config_override: int | None = None) -> int:
"""Get the recommended compute unit limit for LetsBonk buy operations.
Args:
config_override: Optional override from configuration
Returns:
Compute unit limit appropriate for buy operations
"""
if config_override is not None:
return config_override
# Buy operations: ATA creation + WSOL creation/init/close + buy instruction
return 100_000
def get_sell_compute_unit_limit(self, config_override: int | None = None) -> int:
"""Get the recommended compute unit limit for LetsBonk sell operations.
Args:
config_override: Optional override from configuration
Returns:
Compute unit limit appropriate for sell operations
"""
if config_override is not None:
return config_override
# Sell operations: WSOL creation/init/close + sell instruction
return 60_000
@@ -336,3 +336,31 @@ class PumpFunInstructionBuilder(InstructionBuilder):
Token amount in decimal form
"""
return token_amount_raw / 10**TOKEN_DECIMALS
def get_buy_compute_unit_limit(self, config_override: int | None = None) -> int:
"""Get the recommended compute unit limit for pump.fun buy operations.
Args:
config_override: Optional override from configuration
Returns:
Compute unit limit appropriate for buy operations
"""
if config_override is not None:
return config_override
# Buy operations: ATA creation + buy instruction
return 100_000
def get_sell_compute_unit_limit(self, config_override: int | None = None) -> int:
"""Get the recommended compute unit limit for pump.fun sell operations.
Args:
config_override: Optional override from configuration
Returns:
Compute unit limit appropriate for sell operations
"""
if config_override is not None:
return config_override
# Sell operations: typically just sell instruction (ATA exists)
return 60_000
+48 -6
View File
@@ -30,6 +30,7 @@ class PlatformAwareBuyer(Trader):
max_retries: int = 5,
extreme_fast_token_amount: int = 0,
extreme_fast_mode: bool = False,
compute_units: dict | None = None,
):
"""Initialize platform-aware token buyer."""
self.client = client
@@ -40,6 +41,7 @@ class PlatformAwareBuyer(Trader):
self.max_retries = max_retries
self.extreme_fast_mode = extreme_fast_mode
self.extreme_fast_token_amount = extreme_fast_token_amount
self.compute_units = compute_units or {}
async def execute(self, token_info: TokenInfo) -> TradeResult:
"""Execute buy operation using platform-specific implementations."""
@@ -106,6 +108,9 @@ class PlatformAwareBuyer(Trader):
priority_fee=await self.priority_fee_manager.calculate_priority_fee(
priority_accounts
),
compute_unit_limit=instruction_builder.get_buy_compute_unit_limit(
self._get_cu_override("buy", token_info.platform)
),
)
success = await self.client.confirm_transaction(tx_signature)
@@ -147,6 +152,22 @@ class PlatformAwareBuyer(Trader):
# Fallback to deriving the address using platform provider
return address_provider.derive_pool_address(token_info.mint)
def _get_cu_override(self, operation: str, platform: Platform) -> int | None:
"""Get compute unit override from configuration.
Args:
operation: "buy" or "sell"
platform: Trading platform (unused - each config is platform-specific)
Returns:
CU override value if configured, None otherwise
"""
if not self.compute_units:
return None
# Just check for operation override (buy/sell)
return self.compute_units.get(operation)
class PlatformAwareSeller(Trader):
"""Platform-aware token seller that works with any supported platform."""
@@ -158,6 +179,7 @@ class PlatformAwareSeller(Trader):
priority_fee_manager: PriorityFeeManager,
slippage: float = 0.25,
max_retries: int = 5,
compute_units: dict | None = None,
):
"""Initialize platform-aware token seller."""
self.client = client
@@ -165,6 +187,7 @@ class PlatformAwareSeller(Trader):
self.priority_fee_manager = priority_fee_manager
self.slippage = slippage
self.max_retries = max_retries
self.compute_units = compute_units or {}
async def execute(self, token_info: TokenInfo) -> TradeResult:
"""Execute sell operation using platform-specific implementations."""
@@ -203,18 +226,18 @@ class PlatformAwareSeller(Trader):
logger.info(f"Price per Token: {token_price_sol:.8f} SOL")
# Calculate minimum SOL output with slippage
expected_sol_output = float(token_balance_decimal) * float(token_price_sol)
# Calculate expected SOL output
expected_sol_output = token_balance_decimal * token_price_sol
# Calculate minimum SOL output with slippage protection
min_sol_output = int(
(expected_sol_output * (1 - self.slippage)) * LAMPORTS_PER_SOL
)
logger.info(
f"Selling {token_balance_decimal} tokens on {token_info.platform.value}"
)
logger.info(f"Selling {token_balance_decimal} tokens on {token_info.platform.value}")
logger.info(f"Expected SOL output: {expected_sol_output:.8f} SOL")
logger.info(
f"Minimum SOL output (with {self.slippage * 100}% slippage): {min_sol_output / LAMPORTS_PER_SOL:.8f} SOL"
f"Minimum SOL output (with {self.slippage * 100:.1f}% slippage): {min_sol_output / LAMPORTS_PER_SOL:.8f} SOL"
)
# Build sell instructions using platform-specific builder
@@ -240,6 +263,9 @@ class PlatformAwareSeller(Trader):
priority_fee=await self.priority_fee_manager.calculate_priority_fee(
priority_accounts
),
compute_unit_limit=instruction_builder.get_sell_compute_unit_limit(
self._get_cu_override("sell", token_info.platform)
),
)
success = await self.client.confirm_transaction(tx_signature)
@@ -280,3 +306,19 @@ class PlatformAwareSeller(Trader):
# Fallback to deriving the address using platform provider
return address_provider.derive_pool_address(token_info.mint)
def _get_cu_override(self, operation: str, platform: Platform) -> int | None:
"""Get compute unit override from configuration.
Args:
operation: "buy" or "sell"
platform: Trading platform (unused - each config is platform-specific)
Returns:
CU override value if configured, None otherwise
"""
if not self.compute_units:
return None
# Just check for operation override (buy/sell)
return self.compute_units.get(operation)
+7
View File
@@ -83,6 +83,8 @@ class UniversalTrader:
bro_address: str | None = None,
marry_mode: bool = False,
yolo_mode: bool = False,
# Compute unit configuration
compute_units: dict | None = None,
):
"""Initialize the universal trader."""
# Core components
@@ -120,6 +122,9 @@ class UniversalTrader:
self.platform, self.solana_client
)
# Store compute unit configuration
self.compute_units = compute_units or {}
# Create platform-aware traders
self.buyer = PlatformAwareBuyer(
self.solana_client,
@@ -130,6 +135,7 @@ class UniversalTrader:
max_retries,
extreme_fast_token_amount,
extreme_fast_mode,
compute_units=self.compute_units,
)
self.seller = PlatformAwareSeller(
@@ -138,6 +144,7 @@ class UniversalTrader:
self.priority_fee_manager,
sell_slippage,
max_retries,
compute_units=self.compute_units,
)
# Initialize the appropriate listener with platform filtering