44
55import asyncio
66import json
7+ import struct
78from typing import Any
89
910import aiohttp
2324logger = get_logger (__name__ )
2425
2526
27+ def set_loaded_accounts_data_size_limit (bytes_limit : int ) -> Instruction :
28+ """
29+ Create SetLoadedAccountsDataSizeLimit instruction to reduce CU consumption.
30+
31+ By default, Solana transactions can load up to 64MB of account data,
32+ costing 16k CU (8 CU per 32KB). Setting a lower limit reduces CU
33+ consumption and improves transaction priority.
34+
35+ NOTE: CU savings are NOT visible in "consumed CU" metrics, which only
36+ show execution CU. The 16k CU loaded accounts overhead is counted
37+ separately for transaction priority/cost calculation.
38+
39+ Args:
40+ bytes_limit: Max account data size in bytes (e.g., 512_000 = 512KB)
41+
42+ Returns:
43+ Compute Budget instruction with discriminator 4
44+
45+ Reference:
46+ https://www.anza.xyz/blog/cu-optimization-with-setloadedaccountsdatasizelimit
47+ """
48+ COMPUTE_BUDGET_PROGRAM = Pubkey .from_string (
49+ "ComputeBudget111111111111111111111111111111"
50+ )
51+
52+ data = struct .pack ("<BI" , 4 , bytes_limit )
53+ return Instruction (COMPUTE_BUDGET_PROGRAM , data , [])
54+
55+
2656class SolanaClient :
2757 """Abstraction for Solana RPC client operations."""
2858
@@ -146,6 +176,7 @@ async def build_and_send_transaction(
146176 max_retries : int = 3 ,
147177 priority_fee : int | None = None ,
148178 compute_unit_limit : int | None = None ,
179+ account_data_size_limit : int | None = None ,
149180 ) -> str :
150181 """
151182 Send a transaction with optional priority fee and compute unit limit.
@@ -157,6 +188,8 @@ async def build_and_send_transaction(
157188 max_retries: Maximum number of retry attempts.
158189 priority_fee: Optional priority fee in microlamports.
159190 compute_unit_limit: Optional compute unit limit. Defaults to 85,000 if not provided.
191+ account_data_size_limit: Optional account data size limit in bytes (e.g., 512_000).
192+ Reduces CU cost from 16k to ~128 CU. Must be first instruction.
160193
161194 Returns:
162195 Transaction signature.
@@ -168,9 +201,19 @@ async def build_and_send_transaction(
168201 )
169202
170203 # Add compute budget instructions if applicable
171- if priority_fee is not None or compute_unit_limit is not None :
204+ if (
205+ priority_fee is not None
206+ or compute_unit_limit is not None
207+ or account_data_size_limit is not None
208+ ):
172209 fee_instructions = []
173210
211+ if account_data_size_limit is not None :
212+ fee_instructions .append (
213+ set_loaded_accounts_data_size_limit (account_data_size_limit )
214+ )
215+ logger .info (f"Account data size limit: { account_data_size_limit } bytes" )
216+
174217 # Set compute unit limit (use provided value or default to 85,000)
175218 cu_limit = compute_unit_limit if compute_unit_limit is not None else 85_000
176219 fee_instructions .append (set_compute_unit_limit (cu_limit ))
0 commit comments