mcpField
S
solana-tx-building

solana-tx-building

github.com/agiprolabs开发456446 次安装8 周前更新
代码仓库

关于 solana-tx-building

solana-tx-building 是面向开发者的 Solana 交易构建、模拟与检查技能,涵盖指令格式、版本化交易、计算预算、费用和解码。其脚本不会签署或提交真实交易。

主要功能

  1. 01构建交易指令
  2. 02使用版本化交易和 ALT
  3. 03设置计算限制与优先费用
  4. 04模拟交易但不提交
  5. 05获取并解码链上交易

适用场景

  1. 01构建涉及多个账户的 Solana 交易
  2. 02通过模拟测试交易行为
  3. 03检查已确认交易的内容

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/agiprolabs/claude-trading-skills --skill solana-tx-building

安装后在 Claude Code 中输入/solana-tx-building确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
common_instructions.md
transaction_anatomy.md
scripts/
build_transfer.py
decode_transaction.py

详细介绍

Solana 交易构建

本技能介绍如何以编程方式构建、模拟和检查 Solana 交易,涵盖 Solana 交易的完整结构——从原始指令编码到版本化交易格式、计算预算管理、优先费和地址查找表。

安全:本技能仅用于交易的构建和分析。本技能中的脚本绝不会签署或提交真实交易。发送前务必先模拟。切勿自动签署。

交易结构

Solana 交易由以下部分组成:

  1. 签名:一个或多个 Ed25519 签名(每个 64 字节)
  2. 消息:可序列化的载荷,包含:
    • 标头:所需签名者、只读签名者、只读非签名者的数量
    • 账户密钥:指令引用的所有公钥数组
    • 近期区块哈希:用于防重放的 32 字节哈希(约 60-90 秒后过期)
    • 指令:程序调用数组
交易大小限制

整个序列化交易的硬性限制为 1232 字节。这限制了可包含的指令和账户数量。以下策略有助于控制在限制范围内:

  • 使用带有地址查找表(ALTs)的版本化交易
  • 尽量减少每条指令的账户数量
  • 在支持的情况下,将相关操作合并到单条指令中
  • 将复杂操作拆分到多个交易中
指令格式

每条指令包含三个字段:

Instruction {
    program_id_index: u8,      // Index into the account keys array
    accounts: [u8],            // Indices into account keys array
    data: [u8],                // Opaque byte array interpreted by the program
}
账户元数据

指令中引用的每个账户都有元数据:

AccountMeta {
    pubkey: Pubkey,            // 32-byte public key
    is_signer: bool,           // Must sign the transaction
    is_writable: bool,         // Will be written to by this instruction
}

这四种组合决定了账户的角色:

is_signeris_writable角色
truetrue费用支付者、执行转账的代币所有者
truefalse多签共同签名者、只读权限方
falsetrue目标账户、正在写入的 PDA
falsefalse程序 ID、系统变量、时钟

传统交易与版本化交易

传统交易

原始格式。所有账户都必须列在账户密钥数组中。在 1232 字节的限制下,根据指令数据大小,通常可容纳约 20-35 个账户。

版本化交易(v0)

此格式的引入是为了支持地址查找表(ALTs)。v0 交易包含:

  • 版本前缀字节(v0 为 0x80)
  • 与传统交易相同的消息结构
  • 额外的 address_table_lookups 数组

ALTs 让你可以通过链上表中的紧凑索引引用账户,而不必包含完整的 32 字节公钥。这大幅增加了交易可引用的账户数量。

AddressTableLookup {
    account_key: Pubkey,           // The ALT account address
    writable_indexes: [u8],        // Indices for writable accounts
    readonly_indexes: [u8],        // Indices for read-only accounts
}

何时使用 v0:任何引用超过约 20 个账户的交易、带有多跳路径的 Jupiter 兑换、复杂的 DeFi 交互。

计算预算

每笔交易都有一个计算预算,用于确定可消耗的计算单元(CUs)数量以及需要支付的优先费。

计算预算指令

来自计算预算程序(ComputeBudget111111111111111111111111111111)的两条关键指令:

1. 设置计算单元上限

Instruction data: [0x02, <units as u32 LE>]

设置此交易可消耗的最大 CU 数量。默认值为每条指令 200,000(每笔交易最多 1,400,000)。设置得低于所需值会导致交易失败。设置得更高会浪费预算,但不会增加费用(你只需为申请的数量付费,而非实际消耗的数量)。

2. 设置计算单元价格

Instruction data: [0x03, <micro_lamports as u64 LE>]

设置每 CU 的价格,单位为微 lamport。这是优先费机制。优先费总额为:

priority_fee = compute_unit_limit * compute_unit_price / 1_000_000
优先费估算

估算合适的优先费:

  1. 调用 getRecentPrioritizationFees RPC 方法,并传入交易涉及的账户
  2. 查看近期 slot 的费用中位数或第 75 百分位数
  3. 网络拥堵期间,费用会激增——请监控并动态调整
import httpx

def get_priority_fees(rpc_url: str, accounts: list[str]) -> list[dict]:
    """Fetch recent prioritization fees for given accounts."""
    resp = httpx.post(rpc_url, json={
        "jsonrpc": "2.0",
        "id": 1,
        "method": "getRecentPrioritizationFees",
        "params": [accounts]
    })
    return resp.json()["result"]

常见交易模式

1. SOL 转账

最简单的交易:System Program 转账。

# System Program transfer instruction data layout:
# [2, 0, 0, 0]  (u32 LE = instruction index 2 = Transfer)
# + amount as u64 LE (lamports)
import struct

def build_sol_transfer_data(lamports: int) -> bytes:
    """Build instruction data for a SOL transfer."""
    return struct.pack("<I", 2) + struct.pack("<Q", lamports)

所需账户:

  1. 发送方(签名者,可写)
  2. 接收方(可写)
2. SPL Token 转账

转移 SPL Token 需要 Token Program。

# Token Program transfer instruction:
# [3]  (instruction index 3 = Transfer)
# + amount as u64 LE
def build_token_transfer_data(amount: int) -> bytes:
    """Build instruction data for an SPL token transfer."""
    return bytes([3]) + struct.pack("<Q", amount)

所需账户:

  1. 源 Token 账户(可写)
  2. 目标 Token 账户(可写)
  3. 所有者/代理(签名者)
3. 创建关联 Token 账户(ATA)

转移 Token 前,接收方必须拥有一个关联 Token 账户。

# ATA Program: instruction index 0 = Create
# No instruction data needed (empty bytes)
ATA_PROGRAM_ID = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"

所需账户(按顺序):

  1. 付款方(签名者,可写)— 支付租金
  2. 关联 Token 账户(可写)— 要创建的 ATA
  3. 钱包地址 — 新 ATA 的所有者
  4. Token mint
  5. System Program
  6. Token Program
4. Jupiter 兑换

Jupiter 提供 /swap-instructions 端点,可返回预构建的指令。完整详情请参阅 jupiter-api 技能。

一般流程:

  1. 从 /quote 获取报价
  2. 从 /swap-instructions 获取兑换指令
  3. 使用设置指令 + 兑换指令 + 清理指令构建交易
  4. 添加计算预算指令
  5. 模拟,然后签名并发送

模拟

发送前务必进行模拟。使用 simulateTransaction RPC 方法:

def simulate_transaction(rpc_url: str, tx_base64: str) -> dict:
    """Simulate a transaction without submitting it.

    Args:
        rpc_url: Solana RPC endpoint URL.
        tx_base64: Base64-encoded serialized transaction.

    Returns:
        Simulation result with logs and compute units consumed.
    """
    resp = httpx.post(rpc_url, json={
        "jsonrpc": "2.0",
        "id": 1,
        "method": "simulateTransaction",
        "params": [
            tx_base64,
            {"encoding": "base64", "replaceRecentBlockhash": True}
        ]
    })
    result = resp.json()["result"]
    if result["value"]["err"]:
        print(f"Simulation failed: {result['value']['err']}")
        for log in result["value"].get("logs", []):
            print(f"  {log}")
    else:
        cu = result["value"].get("unitsConsumed", 0)
        print(f"Simulation OK — {cu} compute units consumed")
    return result

replaceRecentBlockhash: True 标志允许你在区块哈希过期时仍进行模拟,这对于不受时间限制地测试交易构建很有用。

错误处理

常见交易错误及其原因:

错误原因解决方法
BlockhashNotFound区块哈希已过期(约 60-90 秒)获取新的区块哈希并重新构建
InsufficientFundsSOL 不足以支付费用和转账构建前检查余额
AccountNotFoundToken 账户不存在先创建 ATA
ProgramFailedToComplete超出计算预算增加计算单元限制
TransactionTooLarge超过 1232 字节使用 ALT 或拆分为多个交易
InvalidAccountData传给指令的账户有误验证账户派生结果
SignatureVerificationFailed缺少签名者或签名者有误检查所有 is_signer 账户是否都已签名
重试策略
import time

def send_with_retry(
    rpc_url: str,
    build_fn,
    max_retries: int = 3,
    base_delay: float = 0.5
) -> dict:
    """Build and send a transaction with blockhash refresh on expiry.

    Args:
        rpc_url: Solana RPC endpoint.
        build_fn: Callable that takes a blockhash and returns a signed tx.
        max_retries: Maximum retry attempts.
        base_delay: Base delay between retries in seconds.

    Returns:
        Send result from RPC.
    """
    for attempt in range(max_retries):
        blockhash = get_latest_blockhash(rpc_url)
        tx = build_fn(blockhash)
        result = send_transaction(rpc_url, tx)
        if "error" not in result:
            return result
        err = result["error"]
        if "BlockhashNotFound" in str(err):
            time.sleep(base_delay * (attempt + 1))
            continue
        raise RuntimeError(f"Transaction failed: {err}")
    raise RuntimeError("Max retries exceeded")

交易解码

要解码链上的现有交易:

def decode_transaction(rpc_url: str, signature: str) -> dict:
    """Fetch and return a parsed transaction.

    Args:
        rpc_url: Solana RPC endpoint.
        signature: Transaction signature (base58).

    Returns:
        Parsed transaction data.
    """
    resp = httpx.post(rpc_url, json={
        "jsonrpc": "2.0",
        "id": 1,
        "method": "getTransaction",
        "params": [
            signature,
            {"encoding": "jsonParsed", "maxSupportedTransactionVersion": 0}
        ]
    })
    return resp.json()["result"]

与其他技能集成

  • solana-rpc:提供用于提交和查询交易的 RPC 连接层
  • jupiter-api:提供本技能用于组装交易的兑换指令
  • dex-execution:使用本技能构建的交易编排完整执行流程
  • mev-analysis:提交前评估已构建交易的 MEV 风险
  • helius-api:增强交易解析,并通过 webhook 跟踪确认状态

安全检查清单

向主网提交任何交易前:

  1. 先模拟 — 在调用 sendTransaction 前务必调用 simulateTransaction
  2. 验证账户 — 确认所有账户地址正确(尤其是 Token 转账)
  3. 检查余额 — 确保有足够的 SOL 支付费用和任何转账
  4. 检查计算预算 — 根据模拟结果设置适当的 CU 限制
  5. 确认优先费 — 检查当前网络费用,避免多付
  6. 切勿自动签名 — 签名前必须获得用户明确确认
  7. 使用 devnet 测试 — 在主网操作前,先在 devnet 上构建并测试
  8. 记录所有信息 — 记录交易签名、模拟结果和错误

文件

参考资料
  • references/transaction_anatomy.md — 消息格式、版本化交易、计算预算、区块哈希管理
  • references/common_instructions.md — System、Token、ATA、Compute Budget、Memo 和 Jupiter 程序的指令布局
脚本
  • scripts/build_transfer.py — 构建并模拟 SOL 转账交易(演示模式,绝不签名)
  • scripts/decode_transaction.py — 获取并解码链上交易,并识别程序

评论

支持 Markdown