React应用中Solana SPL交易打包多指令模拟失败排查
Solana多指令打包交易(多NFT+同质化代币转账)问题记录
- 运行环境:React + @solana/web3.js + @solana/spl-token 技术栈,发送方钱包通过钱包适配器配合
useAnchorWallet钩子获取,接收方地址为手动指定的PublicKey实例 - 阶段目标:先实现单笔交易内完成2个NFT转账,最终支持单笔交易打包3个NFT转账+指定数量同质化代币转账
- 前置验证:单笔同质化代币转账(已知接收方代币账户)、单笔NFT转账(自行派生接收方关联代币账户ATA)均可独立正常执行,仅多指令合并到同一交易时触发模拟失败错误
单NFT转账可运行参考代码
const transaction = new Transaction().add( spltoken.createAssociatedTokenAccountInstruction( fromWallet.publicKey, // payer ataNft1, // ata toWallet, // owner nft1, // mint spltoken.TOKEN_PROGRAM_ID, spltoken.ASSOCIATED_TOKEN_PROGRAM_ID ), spltoken.createTransferInstruction( nftAccount1.value[0].pubkey, ataNft1, fromWallet.publicKey, 1, [], spltoken.TOKEN_PROGRAM_ID ), )
多指令合并的失败尝试
尝试1:按NFT顺序依次追加创建ATA、转账指令
对应实现代码:
const transaction = new Transaction().add( spltoken.createAssociatedTokenAccountInstruction( fromWallet.publicKey, // payer ataNft1, // ata toWallet, // owner nft1, // mint spltoken.TOKEN_PROGRAM_ID, spltoken.ASSOCIATED_TOKEN_PROGRAM_ID ), spltoken.createTransferInstruction( nftAccount1.value[0].pubkey, ataNft1, fromWallet.publicKey, 1, [], spltoken.TOKEN_PROGRAM_ID ), spltoken.createAssociatedTokenAccountInstruction( fromWallet.publicKey, // payer ataNft2, // ata toWallet, // owner nft2, // mint spltoken.TOKEN_PROGRAM_ID, spltoken.ASSOCIATED_TOKEN_PROGRAM_ID ), spltoken.createTransferInstruction( nftAccount2.value[0].pubkey, ataNft2, fromWallet.publicKey, 1, [], spltoken.TOKEN_PROGRAM_ID ), )
执行结果:交易模拟失败。
尝试2:先批量添加所有ATA创建指令,再批量添加转账指令
对应实现代码:
const transaction = new Transaction().add( spltoken.createAssociatedTokenAccountInstruction( fromWallet.publicKey, // payer ataNft1, // ata toWallet, // owner nft1, // mint spltoken.TOKEN_PROGRAM_ID, spltoken.ASSOCIATED_TOKEN_PROGRAM_ID ), spltoken.createAssociatedTokenAccountInstruction( fromWallet.publicKey, // payer ataNft2, // ata toWallet, // owner nft2, // mint spltoken.TOKEN_PROGRAM_ID, spltoken.ASSOCIATED_TOKEN_PROGRAM_ID ), spltoken.createTransferInstruction( nftAccount1.value[0].pubkey, ataNft1, fromWallet.publicKey, 1, [], spltoken.TOKEN_PROGRAM_ID ), spltoken.createTransferInstruction( nftAccount2.value[0].pubkey, ataNft2, fromWallet.publicKey, 1, [], spltoken.TOKEN_PROGRAM_ID ), );
执行结果:依然触发交易模拟失败。
问题根因与修复方案
问题更新:已完成问题定位与修复
- 根因:派生接收方关联代币账户(ATA)时,未传入
allowOffCurve参数,导致多ATA派生时地址计算不符合规则,交易执行时账户校验不通过 - 修复:调用ATA派生方法时补充
allowOffCurve = true配置,重新计算所有接收方代币账户地址后,多指令打包交易可正常上链执行。
内容的提问来源于stack exchange,提问作者Tyler Davis
相关产品推荐
相关产品推荐

