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

Solana web3中通过Message构造交易发送SOL如何指定转账金额

解决方案

SYSTEM_INSTRUCTION_LAYOUTS.Transfer 是Solana Web3.js里定义的指令序列化布局Schema,不是可直接传参调用的指令构造方法,直接调用必然报错。
使用Message构造交易时,转账金额不存在于Message的顶层配置项中,而是编码在系统转账指令的data字段内,正确配置方式如下:


标准实现(推荐)

直接用官方封装的SystemProgram.transfer方法生成转账指令,金额在该方法中传入即可,不需要手动处理序列化:

const {
  Connection,
  Keypair,
  PublicKey,
  TransactionMessage,
  VersionedTransaction,
  SystemProgram,
  LAMPORTS_PER_SOL
} = require('@solana/web3.js');

// 初始化配置
const connection = new Connection('你的RPC节点地址');
const payer = Keypair.fromSecretKey(/* 付款方私钥Uint8Array */);
const receiver = new PublicKey('接收方钱包地址');
// 👇 转账金额配置位置,单位为lamports,1 SOL = 1e9 lamports
const transferLamports = 0.05 * LAMPORTS_PER_SOL; // 示例为转0.05 SOL

async function sendTransferTx() {
  // 1. 生成带金额的转账指令
  const transferInstruction = SystemProgram.transfer({
    fromPubkey: payer.publicKey,
    toPubkey: receiver,
    lamports: BigInt(transferLamports) // 金额参数传入位置
  });

  // 2. 获取最新区块哈希
  const latestBlock = await connection.getLatestBlockhash('confirmed');

  // 3. 编译Message
  const txMessage = new TransactionMessage({
    payerKey: payer.publicKey,
    recentBlockhash: latestBlock.blockhash,
    instructions: [transferInstruction] // 传入组装好的转账指令
  }).compileToV0Message();

  // 4. 构造交易、签名、上链
  const versionedTx = new VersionedTransaction(txMessage);
  versionedTx.sign([payer]);
  const txSignature = await connection.sendTransaction(versionedTx);
  console.log('交易发送成功,签名:', txSignature);
}

手动序列化实现(不推荐,仅做原理说明)

如果要手动通过SYSTEM_INSTRUCTION_LAYOUTS构造指令,需要先按布局定义把金额编码到Buffer中,再组装成完整指令:

const { struct, u32, u64 } = require('@solana/buffer-layout');
const {
  SystemProgram,
  SystemInstruction,
  TransactionInstruction,
  PublicKey
} = require('@solana/web3.js');

// 定义转账指令布局
const transferDataLayout = struct([
  u32('instructionType'),
  u64('lamports')
]);
const dataBuffer = Buffer.alloc(transferDataLayout.span);
// 写入指令类型和转账金额
transferDataLayout.encode({
  instructionType: SystemInstruction.Transfer,
  lamports: BigInt(transferLamports) // 金额写入位置
}, dataBuffer);

// 组装完整指令
const manualTransferIx = new TransactionInstruction({
  keys: [
    { pubkey: payer.publicKey, isSigner: true, isWritable: true },
    { pubkey: receiver, isSigner: false, isWritable: true }
  ],
  programId: SystemProgram.programId,
  data: dataBuffer
});
// 后续把manualTransferIx传入Message的instructions数组即可

注意事项

  • 所有SOL原生转账的金额单位均为lamports,禁止直接传入SOL的浮点数值,必须通过LAMPORTS_PER_SOL做单位换算,否则会出现金额错误
  • TransactionMessage本身只负责打包指令列表、付费方信息、最近区块哈希,不单独提供转账金额配置参数,所有业务参数都绑定在传入的具体指令中
  • 不要直接调用SYSTEM_INSTRUCTION_LAYOUTS下的属性作为构造函数,该对象仅存储指令的内存布局描述,无执行逻辑

内容的提问来源于stack exchange,提问作者psyfi-eth

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 06:06:31