如何用Solana Py从交易中提取账户数据长度?
提取Solana交易中创建账户的空间大小
要从交易中提取创建账户的空间大小,分两种场景处理,取决于账户创建的方式:
场景1:交易包含系统程序的CreateAccount指令
如果前端生成的交易里直接包含系统程序的CreateAccount指令(比如非Anchor场景或早期Anchor版本),你可以遍历交易指令,筛选出系统程序指令并解析其数据:
- 遍历交易的所有指令,找到
program_id等于系统程序ID(SystemProgram.programId)的条目; - 系统
CreateAccount指令的数据是Borsh序列化格式,结构包含lamports、space、owner三个字段; - 用Borsh解析工具提取
space字段。
Solana Py实现示例:
import base64 from borsh_construct import CStruct, U64, Pubkey from solana.rpc.types import Tx from solana.system_program import ID as SYSTEM_PROGRAM_ID # 定义CreateAccount指令的Borsh结构 create_account_schema = CStruct( "lamports" / U64, "space" / U64, "owner" / Pubkey ) def get_create_account_space(tx: Tx) -> int | None: for instr in tx.instructions: if instr.program_id == SYSTEM_PROGRAM_ID: try: data_bytes = base64.b64decode(instr.data) parsed_data = create_account_schema.parse(data_bytes) return parsed_data.space except: # 跳过Transfer等非CreateAccount的系统指令 continue return None
场景2:通过合约CPI创建账户(你的Anchor场景)
你使用的Anchor框架中,#[account(init)]宏是在合约内部通过CPI调用系统程序创建账户的,因此用户提交的交易中不会包含系统程序指令,指令数据里也不会直接携带空间大小——这个值是在合约代码中定义的。
这种场景下,你需要借助程序的IDL(接口定义语言)来获取预定义的空间大小:
- 每个Anchor程序都会生成对应的IDL文件,其中包含所有指令、账户的定义,包括你在
#[account(init, space=1372)]中指定的固定空间值; - 服务预先加载对接程序的IDL,通过交易中的程序ID匹配对应IDL;
- 解析交易指令的前8字节(方法判别式),找到对应的指令定义;
- 从指令的账户列表中筛选出标记为
init的账户,提取其space值。
Solana Py结合AnchorPy的实现示例:
from anchorpy import Program, IDL from solana.publickey import PublicKey from solana.rpc.types import Tx # 预先加载目标程序的IDL(可从文件读取或通过RPC获取) idl = IDL.load("./your_program_idl.json") target_program_id = PublicKey("YOUR_PROGRAM_PUBKEY") program = Program(idl, target_program_id) def get_init_account_space_from_idl(tx: Tx) -> int | None: first_instr = tx.instructions[0] if first_instr.program_id != target_program_id: return None # 提取指令的方法判别式(前8字节) method_disc = first_instr.data[:8] for method in program.idl.methods: if method.discriminator == method_disc: # 遍历指令的账户,找到需要初始化的账户 for acc in method.accounts: if acc.is_init: return acc.space return None
注意事项
- 如果合约中的空间大小是动态计算的(而非硬编码),IDL中不会包含固定的
space值,这种情况下无法从交易或IDL中提前获取,只能依赖合约执行时的计算结果; - 确保服务能获取到所有对接程序的最新IDL,避免因程序更新导致定义不匹配。
内容的提问来源于stack exchange,提问作者alessandro buffoli
相关产品推荐
相关产品推荐

