mirror of
https://github.com/chainstacklabs/pumpfun-bonkfun-bot.git
synced 2026-08-17 09:18:05 +00:00
feat(core): integrate account data size limit (#144)
* feat(core): integrate account data size limit in buyer and seller transaction * refactor: format code for improved readability and consistency
This commit is contained in:
@@ -57,6 +57,13 @@ compute_units:
|
|||||||
# buy: 100_000 # Buy operations (ATA creation + trading)
|
# buy: 100_000 # Buy operations (ATA creation + trading)
|
||||||
# sell: 60_000 # Sell operations (just trading)
|
# sell: 60_000 # Sell operations (just trading)
|
||||||
|
|
||||||
|
# Account data size optimization (reduces CU cost and improves tx priority)
|
||||||
|
# Reduces CU cost from 16k to ~128 CU by limiting loaded account data.
|
||||||
|
# Default is 64MB (16k CU). Setting to 512KB significantly reduces overhead.
|
||||||
|
# Note: Savings don't show in "consumed CU" but improve tx priority/cost.
|
||||||
|
# Reference: https://www.anza.xyz/blog/cu-optimization-with-setloadedaccountsdatasizelimit
|
||||||
|
account_data_size: 512_000 # 512KB limit
|
||||||
|
|
||||||
# Filters for token selection
|
# Filters for token selection
|
||||||
filters:
|
filters:
|
||||||
match_string: null # Only process tokens with this string in name/symbol
|
match_string: null # Only process tokens with this string in name/symbol
|
||||||
|
|||||||
@@ -57,6 +57,13 @@ compute_units:
|
|||||||
# buy: 100_000 # Buy operations (ATA creation + trading)
|
# buy: 100_000 # Buy operations (ATA creation + trading)
|
||||||
# sell: 60_000 # Sell operations (just trading)
|
# sell: 60_000 # Sell operations (just trading)
|
||||||
|
|
||||||
|
# Account data size optimization (reduces CU cost and improves tx priority)
|
||||||
|
# Reduces CU cost from 16k to ~128 CU by limiting loaded account data.
|
||||||
|
# Default is 64MB (16k CU). Setting to 512KB significantly reduces overhead.
|
||||||
|
# Note: Savings don't show in "consumed CU" but improve tx priority/cost.
|
||||||
|
# Reference: https://www.anza.xyz/blog/cu-optimization-with-setloadedaccountsdatasizelimit
|
||||||
|
account_data_size: 512_000 # 512KB limit
|
||||||
|
|
||||||
# Filters for token selection
|
# Filters for token selection
|
||||||
filters:
|
filters:
|
||||||
match_string: null # Only process tokens with this string in name/symbol
|
match_string: null # Only process tokens with this string in name/symbol
|
||||||
|
|||||||
@@ -57,6 +57,13 @@ compute_units:
|
|||||||
# buy: 100_000 # Buy operations (ATA creation + trading)
|
# buy: 100_000 # Buy operations (ATA creation + trading)
|
||||||
# sell: 60_000 # Sell operations (just trading)
|
# sell: 60_000 # Sell operations (just trading)
|
||||||
|
|
||||||
|
# Account data size optimization (reduces CU cost and improves tx priority)
|
||||||
|
# Reduces CU cost from 16k to ~128 CU by limiting loaded account data.
|
||||||
|
# Default is 64MB (16k CU). Setting to 512KB significantly reduces overhead.
|
||||||
|
# Note: Savings don't show in "consumed CU" but improve tx priority/cost.
|
||||||
|
# Reference: https://www.anza.xyz/blog/cu-optimization-with-setloadedaccountsdatasizelimit
|
||||||
|
account_data_size: 512_000 # 512KB limit
|
||||||
|
|
||||||
# Filters for token selection
|
# Filters for token selection
|
||||||
filters:
|
filters:
|
||||||
match_string: null # Only process tokens with this string in name/symbol
|
match_string: null # Only process tokens with this string in name/symbol
|
||||||
|
|||||||
@@ -55,6 +55,13 @@ compute_units:
|
|||||||
# buy: 100_000 # Buy operations (ATA creation + trading)
|
# buy: 100_000 # Buy operations (ATA creation + trading)
|
||||||
# sell: 60_000 # Sell operations (just trading)
|
# sell: 60_000 # Sell operations (just trading)
|
||||||
|
|
||||||
|
# Account data size optimization (reduces CU cost and improves tx priority)
|
||||||
|
# Reduces CU cost from 16k to ~128 CU by limiting loaded account data.
|
||||||
|
# Default is 64MB (16k CU). Setting to 512KB significantly reduces overhead.
|
||||||
|
# Note: Savings don't show in "consumed CU" but improve tx priority/cost.
|
||||||
|
# Reference: https://www.anza.xyz/blog/cu-optimization-with-setloadedaccountsdatasizelimit
|
||||||
|
account_data_size: 512_000 # 512KB limit
|
||||||
|
|
||||||
# Filters for token selection
|
# Filters for token selection
|
||||||
filters:
|
filters:
|
||||||
match_string: null # Only process tokens with this string in name/symbol
|
match_string: null # Only process tokens with this string in name/symbol
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ load_dotenv()
|
|||||||
|
|
||||||
# Constants
|
# Constants
|
||||||
RPC_URL: Final[str] = os.getenv("SOLANA_NODE_RPC_ENDPOINT")
|
RPC_URL: Final[str] = os.getenv("SOLANA_NODE_RPC_ENDPOINT")
|
||||||
TOKEN_MINT: Final[str] = "YOUR_TOKEN_MINT_ADDRESS_HERE" # Replace with actual token mint address
|
TOKEN_MINT: Final[str] = (
|
||||||
|
"YOUR_TOKEN_MINT_ADDRESS_HERE" # Replace with actual token mint address
|
||||||
|
)
|
||||||
PUMP_PROGRAM_ID: Final[Pubkey] = Pubkey.from_string(
|
PUMP_PROGRAM_ID: Final[Pubkey] = Pubkey.from_string(
|
||||||
"6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"
|
"6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
|||||||
|
|
||||||
LAMPORTS_PER_SOL: Final[int] = 1_000_000_000
|
LAMPORTS_PER_SOL: Final[int] = 1_000_000_000
|
||||||
TOKEN_DECIMALS: Final[int] = 6
|
TOKEN_DECIMALS: Final[int] = 6
|
||||||
CURVE_ADDRESS: Final[str] = "YOUR_BONDING_CURVE_ADDRESS_HERE" # Replace with actual bonding curve address
|
CURVE_ADDRESS: Final[str] = (
|
||||||
|
"YOUR_BONDING_CURVE_ADDRESS_HERE" # Replace with actual bonding curve address
|
||||||
|
)
|
||||||
|
|
||||||
# Here and later all the discriminators are precalculated. See learning-examples/calculate_discriminator.py
|
# Here and later all the discriminators are precalculated. See learning-examples/calculate_discriminator.py
|
||||||
EXPECTED_DISCRIMINATOR: Final[bytes] = struct.pack("<Q", 6966180631402821399)
|
EXPECTED_DISCRIMINATOR: Final[bytes] = struct.pack("<Q", 6966180631402821399)
|
||||||
|
|||||||
+44
-1
@@ -4,6 +4,7 @@ Solana client abstraction for blockchain operations.
|
|||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import json
|
import json
|
||||||
|
import struct
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
@@ -23,6 +24,35 @@ from utils.logger import get_logger
|
|||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def set_loaded_accounts_data_size_limit(bytes_limit: int) -> Instruction:
|
||||||
|
"""
|
||||||
|
Create SetLoadedAccountsDataSizeLimit instruction to reduce CU consumption.
|
||||||
|
|
||||||
|
By default, Solana transactions can load up to 64MB of account data,
|
||||||
|
costing 16k CU (8 CU per 32KB). Setting a lower limit reduces CU
|
||||||
|
consumption and improves transaction priority.
|
||||||
|
|
||||||
|
NOTE: CU savings are NOT visible in "consumed CU" metrics, which only
|
||||||
|
show execution CU. The 16k CU loaded accounts overhead is counted
|
||||||
|
separately for transaction priority/cost calculation.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
bytes_limit: Max account data size in bytes (e.g., 512_000 = 512KB)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Compute Budget instruction with discriminator 4
|
||||||
|
|
||||||
|
Reference:
|
||||||
|
https://www.anza.xyz/blog/cu-optimization-with-setloadedaccountsdatasizelimit
|
||||||
|
"""
|
||||||
|
COMPUTE_BUDGET_PROGRAM = Pubkey.from_string(
|
||||||
|
"ComputeBudget111111111111111111111111111111"
|
||||||
|
)
|
||||||
|
|
||||||
|
data = struct.pack("<BI", 4, bytes_limit)
|
||||||
|
return Instruction(COMPUTE_BUDGET_PROGRAM, data, [])
|
||||||
|
|
||||||
|
|
||||||
class SolanaClient:
|
class SolanaClient:
|
||||||
"""Abstraction for Solana RPC client operations."""
|
"""Abstraction for Solana RPC client operations."""
|
||||||
|
|
||||||
@@ -146,6 +176,7 @@ class SolanaClient:
|
|||||||
max_retries: int = 3,
|
max_retries: int = 3,
|
||||||
priority_fee: int | None = None,
|
priority_fee: int | None = None,
|
||||||
compute_unit_limit: int | None = None,
|
compute_unit_limit: int | None = None,
|
||||||
|
account_data_size_limit: int | None = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Send a transaction with optional priority fee and compute unit limit.
|
Send a transaction with optional priority fee and compute unit limit.
|
||||||
@@ -157,6 +188,8 @@ class SolanaClient:
|
|||||||
max_retries: Maximum number of retry attempts.
|
max_retries: Maximum number of retry attempts.
|
||||||
priority_fee: Optional priority fee in microlamports.
|
priority_fee: Optional priority fee in microlamports.
|
||||||
compute_unit_limit: Optional compute unit limit. Defaults to 85,000 if not provided.
|
compute_unit_limit: Optional compute unit limit. Defaults to 85,000 if not provided.
|
||||||
|
account_data_size_limit: Optional account data size limit in bytes (e.g., 512_000).
|
||||||
|
Reduces CU cost from 16k to ~128 CU. Must be first instruction.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Transaction signature.
|
Transaction signature.
|
||||||
@@ -168,9 +201,19 @@ class SolanaClient:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Add compute budget instructions if applicable
|
# Add compute budget instructions if applicable
|
||||||
if priority_fee is not None or compute_unit_limit is not None:
|
if (
|
||||||
|
priority_fee is not None
|
||||||
|
or compute_unit_limit is not None
|
||||||
|
or account_data_size_limit is not None
|
||||||
|
):
|
||||||
fee_instructions = []
|
fee_instructions = []
|
||||||
|
|
||||||
|
if account_data_size_limit is not None:
|
||||||
|
fee_instructions.append(
|
||||||
|
set_loaded_accounts_data_size_limit(account_data_size_limit)
|
||||||
|
)
|
||||||
|
logger.info(f"Account data size limit: {account_data_size_limit} bytes")
|
||||||
|
|
||||||
# Set compute unit limit (use provided value or default to 85,000)
|
# 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
|
cu_limit = compute_unit_limit if compute_unit_limit is not None else 85_000
|
||||||
fee_instructions.append(set_compute_unit_limit(cu_limit))
|
fee_instructions.append(set_compute_unit_limit(cu_limit))
|
||||||
|
|||||||
@@ -186,7 +186,9 @@ class LetsBonkCurveManager(CurveManager):
|
|||||||
"real_quote": decoded_pool_state.get("real_quote", 0),
|
"real_quote": decoded_pool_state.get("real_quote", 0),
|
||||||
"status": decoded_pool_state.get("status", 0),
|
"status": decoded_pool_state.get("status", 0),
|
||||||
"supply": decoded_pool_state.get("supply", 0),
|
"supply": decoded_pool_state.get("supply", 0),
|
||||||
"creator": decoded_pool_state.get("creator"), # Creator pubkey (as base58 string)
|
"creator": decoded_pool_state.get(
|
||||||
|
"creator"
|
||||||
|
), # Creator pubkey (as base58 string)
|
||||||
"base_vault": decoded_pool_state.get("base_vault"), # Base vault pubkey
|
"base_vault": decoded_pool_state.get("base_vault"), # Base vault pubkey
|
||||||
"quote_vault": decoded_pool_state.get("quote_vault"), # Quote vault pubkey
|
"quote_vault": decoded_pool_state.get("quote_vault"), # Quote vault pubkey
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,7 +143,17 @@ class LetsBonkEventParser(EventParser):
|
|||||||
base_vault = get_account_key(8) # base_vault account
|
base_vault = get_account_key(8) # base_vault account
|
||||||
quote_vault = get_account_key(9) # quote_vault account
|
quote_vault = get_account_key(9) # quote_vault account
|
||||||
|
|
||||||
if not all([creator, global_config, platform_config, pool_state, base_mint, base_vault, quote_vault]):
|
if not all(
|
||||||
|
[
|
||||||
|
creator,
|
||||||
|
global_config,
|
||||||
|
platform_config,
|
||||||
|
pool_state,
|
||||||
|
base_mint,
|
||||||
|
base_vault,
|
||||||
|
quote_vault,
|
||||||
|
]
|
||||||
|
):
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f"Missing required accounts: creator={creator}, global_config={global_config}, "
|
f"Missing required accounts: creator={creator}, global_config={global_config}, "
|
||||||
f"platform_config={platform_config}, pool_state={pool_state}, base_mint={base_mint}, "
|
f"platform_config={platform_config}, pool_state={pool_state}, base_mint={base_mint}, "
|
||||||
|
|||||||
@@ -111,6 +111,9 @@ class PlatformAwareBuyer(Trader):
|
|||||||
compute_unit_limit=instruction_builder.get_buy_compute_unit_limit(
|
compute_unit_limit=instruction_builder.get_buy_compute_unit_limit(
|
||||||
self._get_cu_override("buy", token_info.platform)
|
self._get_cu_override("buy", token_info.platform)
|
||||||
),
|
),
|
||||||
|
account_data_size_limit=self._get_cu_override(
|
||||||
|
"account_data_size", token_info.platform
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
success = await self.client.confirm_transaction(tx_signature)
|
success = await self.client.confirm_transaction(tx_signature)
|
||||||
@@ -234,7 +237,9 @@ class PlatformAwareSeller(Trader):
|
|||||||
(expected_sol_output * (1 - self.slippage)) * LAMPORTS_PER_SOL
|
(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"Expected SOL output: {expected_sol_output:.8f} SOL")
|
||||||
logger.info(
|
logger.info(
|
||||||
f"Minimum SOL output (with {self.slippage * 100:.1f}% 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"
|
||||||
@@ -266,6 +271,9 @@ class PlatformAwareSeller(Trader):
|
|||||||
compute_unit_limit=instruction_builder.get_sell_compute_unit_limit(
|
compute_unit_limit=instruction_builder.get_sell_compute_unit_limit(
|
||||||
self._get_cu_override("sell", token_info.platform)
|
self._get_cu_override("sell", token_info.platform)
|
||||||
),
|
),
|
||||||
|
account_data_size_limit=self._get_cu_override(
|
||||||
|
"account_data_size", token_info.platform
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
success = await self.client.confirm_transaction(tx_signature)
|
success = await self.client.confirm_transaction(tx_signature)
|
||||||
|
|||||||
Reference in New Issue
Block a user