You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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(接口定义语言)来获取预定义的空间大小:

  1. 每个Anchor程序都会生成对应的IDL文件,其中包含所有指令、账户的定义,包括你在#[account(init, space=1372)]中指定的固定空间值;
  2. 服务预先加载对接程序的IDL,通过交易中的程序ID匹配对应IDL;
  3. 解析交易指令的前8字节(方法判别式),找到对应的指令定义;
  4. 从指令的账户列表中筛选出标记为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 02:40:17