mirror of
https://github.com/chainstacklabs/pumpfun-bonkfun-bot.git
synced 2026-07-27 15:27:44 +00:00
feat(core): add configurable cu limits
This commit is contained in:
@@ -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,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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -174,7 +174,7 @@ def find_coin_creator_vault(coin_creator: Pubkey) -> Pubkey:
|
||||
|
||||
def find_fee_config() -> Pubkey:
|
||||
"""Derive the Program Derived Address (PDA) for the fee config.
|
||||
|
||||
|
||||
Returns:
|
||||
Pubkey of the derived fee config account
|
||||
"""
|
||||
|
||||
@@ -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()
|
||||
|
||||
+16
-7
@@ -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
|
||||
if priority_fee is not None:
|
||||
fee_instructions = [
|
||||
set_compute_unit_limit(85_000), # Default compute unit limit
|
||||
set_compute_unit_price(priority_fee),
|
||||
]
|
||||
# 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.append(set_compute_unit_price(priority_fee))
|
||||
|
||||
instructions = fee_instructions + instructions
|
||||
|
||||
recent_blockhash = await self.get_cached_blockhash()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user