Solana Raydium SDK V2代币兑换报错:InvalidSplTokenProgram 0x26
问题解答:Solana Raydium兑换报错InvalidSplTokenProgram(0x26)
错误含义
InvalidSplTokenProgram(自定义错误码0x26)表示Raydium路由程序检测到交易中使用的SPL代币程序ID不符合预期——通常是代币账户(ATA)关联的代币程序与交易要求不匹配,或是混用了不同版本的SPL代币程序(原始Token程序 vs Token 2022程序)导致的兼容性问题。
核心问题分析
从你的代码和操作来看,有两个关键问题:
- SOL的ATA使用了错误的代币程序:SOL的
NATIVE_MINT绑定的是原始SPL代币程序(TOKEN_PROGRAM_ID),但你调用getATAAddress时传入了TOKEN_2022_PROGRAM_ID,生成的ATA账户基于Token 2022程序,和SOL本身的代币程序不兼容。 - 未明确指定输出代币的程序ID:手动创建的输出ATA如果基于原始Token程序,但交易中未明确声明,Raydium无法正确识别对应的代币程序,触发校验失败。
解决方案
1. 修正输入ATA的代币程序
将获取SOL ATA时的代币程序改为原始TOKEN_PROGRAM_ID:
import { NATIVE_MINT, TOKEN_PROGRAM_ID } from '@solana/spl-token'; // 替换原inputAccount生成代码 const inputAccount = (await getATAAddress(owner.publicKey, new PublicKey(inputMint), TOKEN_PROGRAM_ID)).publicKey;
2. 明确指定输出代币的程序ID并验证ATA
首先通过Solana浏览器查询目标代币BfuPnXM7Qs46ZLuptSAHhmnoZ7sa8cpnfJnhTj81fKTg的关联程序:
- 若为原始Token程序(
TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA),确保手动创建的输出ATA用的是原始程序,并在swapBaseInAutoAccount中补充tokenProgram参数:const ins = swapBaseInAutoAccount({ programId: ALL_PROGRAM_ID.Router, wallet: owner.publicKey, amount: new BN(amount), inputAccount, outputAccount, routeInfo: swapResponse, poolKeys: res.data.data, tokenProgram: TOKEN_PROGRAM_ID, // 明确指定原始代币程序 }); - 若为Token 2022程序(
TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb),则创建ATA时需添加--program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb参数,同时代码中传入TOKEN_2022_PROGRAM_ID。
3. 额外检查点
- 用
spl-token accounts命令验证输入输出ATA的正确性:确保地址与代码中一致,且关联的代币程序匹配。 - 升级
@raydium-io/raydium-sdk-v2到最新稳定版,避免SDK内部程序ID不匹配问题。 - 确认代码中导入了
BN库(import BN from 'bn.js'),否则new BN(amount)会报错。
修正后的核心代码片段
import { ALL_PROGRAM_ID, API_URLS, ApiSwapV1Out, getATAAddress, swapBaseInAutoAccount } from '@raydium-io/raydium-sdk-v2'; import { NATIVE_MINT, TOKEN_PROGRAM_ID } from '@solana/spl-token'; import { PublicKey, Transaction } from '@solana/web3.js'; import axios from 'axios'; import BN from 'bn.js'; import { connection, owner } from '../config'; const TOKEN_MINT_ADDRESS = "BfuPnXM7Qs46ZLuptSAHhmnoZ7sa8cpnfJnhTj81fKTg"; export const apiSwap = async () => { try { const inputMint = NATIVE_MINT.toBase58(); const outputMint = TOKEN_MINT_ADDRESS; const amount = 10000000; const slippage = 0.5; const txVersion: 'LEGACY' | 'VO' = 'LEGACY'; const { data: swapResponse } = await axios.get<ApiSwapV1Out>(`${API_URLS.SWAP_HOST}/compute/swap-base-out?inputMint=${inputMint}&outputMint=${outputMint}&amount=${amount}&slippageBps=${slippage * 100}&txVersion=${txVersion}`); const res = await axios.get(API_URLS.BASE_HOST + API_URLS.POOL_KEY_BY_ID + `?ids=${swapResponse.data.routePlan.map((r) => r.poolId).join(',')}`); // 修正SOL ATA的代币程序 const inputAccount = (await getATAAddress(owner.publicKey, new PublicKey(inputMint), TOKEN_PROGRAM_ID)).publicKey; const outputAccount = new PublicKey("7TMMYtCcT4qSrfFZWfC2G7CQZ9Q5a1XxZNsvuNk7TESD"); const tx = new Transaction(); const ins = swapBaseInAutoAccount({ programId: ALL_PROGRAM_ID.Router, wallet: owner.publicKey, amount: new BN(amount), inputAccount, outputAccount, routeInfo: swapResponse, poolKeys: res.data.data, tokenProgram: TOKEN_PROGRAM_ID, // 明确指定代币程序 }); let { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('finalized'); tx.add(ins); tx.feePayer = owner.publicKey; tx.recentBlockhash = blockhash; tx.sign(owner); const signature = await connection.sendTransaction(tx, [owner], { skipPreflight: false, preflightCommitment: 'finalized' }); await connection.confirmTransaction({ signature, blockhash, lastValidBlockHeight }, 'finalized'); } catch (error) { console.error('Error executing the swap:', error); } }; apiSwap();
内容的提问来源于stack exchange,提问作者B89
相关产品推荐
相关产品推荐

