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

Phantom钱包签名交易后调用web3.sendRawTransaction()报错

报错核心原因

这个报错本质是RPC节点收到广播的交易后签名校验不通过,常见诱发场景有四类:

  • 序列化逻辑不兼容:Transaction.serialize()方法默认强制校验所有签名位都存在有效签名,若交易包含Phantom之外的其他签名方(如PDA签名、服务端签名、多签账户未完成全部签名),无参调用序列化会生成格式非法的交易数据;另外本地@solana/web3.js版本和Phantom内置依赖的web3.js大版本不兼容时,会出现签名字段偏移,序列化后签名和交易内容不匹配。
  • 交易基础参数无效:构造交易时未显式指定feePayer为当前Phantom钱包地址,或签名用的recentBlockhash超过150个区块的有效期(约1分钟),或获取区块哈希的RPC节点和广播交易的RPC节点不属于同一个集群(如拿开发网哈希往主网节点广播)。
  • 交易版本不匹配:构造的是V0版本化交易,却用传统Legacy交易的序列化、签名逻辑处理,或反之,会直接触发签名校验失败。
  • 签名后交易被篡改:Phantom完成签名后,代码又修改了交易的指令列表、费支付者、区块哈希等字段,导致签名覆盖的交易内容和实际广播的内容不一致,签名直接失效。
排查步骤

按优先级从高到低排查:

  1. 校验交易基础配置:打印交易对象,确认feePayer为当前已连接的Phantom钱包地址,recentBlockhash是发起签名前30秒内、从广播用的同一个RPC实例获取的,钱包和RPC连接的集群(主网/测试网/开发网)完全一致。
  2. 检查依赖版本:本地项目安装的@solana/web3.js版本尽量使用1.9x稳定版,避免跨大版本(如使用0.x旧版本或2.x测试版)和Phantom出现兼容问题。
  3. 校验签名完整性:打印签名后交易的signatures字段,确认Phantom钱包公钥对应的签名位不存在null、undefined空值。
  4. 确认交易类型:区分Legacy交易和V0版本化交易,两类交易的签名、序列化逻辑不能混用。
修复方案

根据业务场景调整代码:

  • 单签名者(仅Phantom签名)Legacy交易场景,调整序列化和广播参数,兼容钱包返回的格式差异:
const signedTransaction = await window.solana.signTransaction(transaction);
// 序列化时跳过强制全签名校验,同时开启本地签名合法性校验
const rawTransaction = signedTransaction.serialize({
  requireAllSignatures: false,
  verifySignatures: true
});
const signature = await connection.sendRawTransaction(rawTransaction, {
  preflightCommitment: 'confirmed',
  maxRetries: 3
});
await connection.confirmTransaction(signature, 'confirmed');
  • V0版本化交易场景,使用版本交易对应的签名、序列化逻辑,不要复用Legacy交易的处理代码:
// 签名前再获取最新区块哈希,避免哈希过期
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
// 构造V0交易消息
const txMessage = new TransactionMessage({
  payerKey: wallet.publicKey,
  recentBlockhash: blockhash,
  instructions: [/* 你的交易指令数组 */]
}).compileToV0Message();
const transaction = new VersionedTransaction(txMessage);
// 调Phantom签名
const signedTransaction = await window.solana.signTransaction(transaction);
const signature = await connection.sendRawTransaction(signedTransaction.serialize(), {
  preflightCommitment: 'confirmed'
});
// 带区块高度确认交易,避免超时
await connection.confirmTransaction({
  signature,
  blockhash,
  lastValidBlockHeight
}, 'confirmed');
  • 多签名者场景,提前把所有签名公钥加入交易签名位数组占位,按业务顺序完成所有签名后再广播,所有序列化步骤都传入requireAllSignatures: false直到全部签名完成。
  • 通用优化:签名前10秒内再获取最新区块哈希,不要提前缓存哈希重复使用;获取区块哈希和广播交易复用同一个connection实例,不要混用多个集群的RPC节点。

快速验证技巧:可以把序列化后的原始交易转成base64字符串,粘贴到Solana区块浏览器的广播页测试,如果浏览器广播也报签名错误,说明交易构造/签名本身有问题;如果浏览器广播成功,说明本地RPC连接配置存在问题。

内容的提问来源于stack exchange,提问作者Dhruvil Patel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 15:09:21