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

Raydium DEX上Solana代币兑换代码报错:无效公钥问题排查

Solana Raydium 兑换代码 PublicKey 错误排查与修复

问题描述

编写Raydium上Solana代币兑换测试代码时遇到invalid public key错误,代码及错误信息如下:

测试代码

const { Connection, Keypair, PublicKey } = require('@solana/web3.js');
const { Liquidity, TokenAmount, Token, Percent } = require('@raydium-io/raydium-sdk');

const devnetConnection = new Connection('https://api.devnet.solana.com');
const privateKey = []; // PRIVATE KEY HIDDEN
const wallet = Keypair.fromSecretKey(new Uint8Array(privateKey));

const OWNER = '675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8';
const TOKEN = 'EP2ib6dYdEeqD8MfE2ezHCxX3kP3K2eLKkirfPm5eyMx';
const SOL = 'So11111111111111111111111111111111111111112';
const PAIR = 'CQurpF3WS3yEqFEt1Bu8s5zmZqznQG3EJkcYvsyg3sLc';

async function main() {
  const poolKeys = {
    id: new PublicKey(OWNER),
  };

  const tokenA = new Token(devnetConnection, new PublicKey(SOL), 9, wallet.publicKey);
  const tokenB = new Token(devnetConnection, new PublicKey(TOKEN), 6, wallet.publicKey);  

  const rawAmountIn = 1;
  const amountIn = new TokenAmount(tokenA, rawAmountIn * 10**tokenA.decimals, false);

  const slippage = new Percent(50, 10000);
  const poolInfo = await Liquidity.fetchInfo(devnetConnection, poolKeys);
  const { minAmountOut } = Liquidity.computeAmountOut(poolInfo, amountIn, tokenB, slippage);

  const { transaction, signers } = await Liquidity.makeSwapTransaction({
    connection: devnetConnection,
    poolKeys,
    userKeys: {
      owner: wallet.publicKey,
    },
    amountIn,
    amountOut: minAmountOut,
    fixedSide: 'in',
  });

  const signature = await devnetConnection.sendTransaction(transaction, [wallet, ...signers]);
  console.log(`Transaction hash: ${signature}`);

  await devnetConnection.confirmTransaction(signature);
  console.log(`Transaction confirmed: ${signature}`);
}

main().catch(error => {
  console.error(error);
});

错误信息

reason: 'invalid public key',
code: 'INVALID_ARGUMENT',
argument: 'publicKey',

需求:找出代码遗漏点,提供可运行的极简测试代码,同时说明信息获取渠道。


错误原因与修复

  • poolKeys参数不完整:Raydium SDK的Liquidity.fetchInfo和makeSwapTransaction需要完整的池密钥集合(含代币账户、LP账户、授权账户等),仅传入id会导致公钥解析失败,需通过SDK工具函数获取完整池信息。
  • Token类初始化参数错误:Token构造函数第四个参数应为代币的mint地址,而非钱包公钥,错误传入钱包地址会触发公钥验证失败。
  • 缺少用户代币账户信息:userKeys需包含用户的输入/输出代币账户地址,仅传owner无法让交易定位用户的代币余额。

可运行的极简测试代码

const { Connection, Keypair, PublicKey } = require('@solana/web3.js');
const { Liquidity, TokenAmount, Token, Percent, TokenAccount } = require('@raydium-io/raydium-sdk');

// 初始化连接和钱包
const devnetConnection = new Connection('https://api.devnet.solana.com');
const privateKey = []; // 替换为你的devnet钱包私钥数组
const wallet = Keypair.fromSecretKey(new Uint8Array(privateKey));

// 代币和池信息(devnet环境)
const SOL_MINT = new PublicKey('So11111111111111111111111111111111111111112');
const TEST_TOKEN_MINT = new PublicKey('EP2ib6dYdEeqD8MfE2ezHCxX3kP3K2eLKkirfPm5eyMx');
const PAIR_ID = new PublicKey('CQurpF3WS3yEqFEt1Bu8s5zmZqznQG3EJkcYvsyg3sLc');

async function main() {
  // 1. 获取完整的池密钥信息
  const poolKeys = await Liquidity.fetchPoolKeys(devnetConnection, PAIR_ID);
  if (!poolKeys) throw new Error('无法获取池信息');

  // 2. 初始化代币对象(第四个参数是mint地址)
  const solToken = new Token(devnetConnection, SOL_MINT, 9, SOL_MINT);
  const testToken = new Token(devnetConnection, TEST_TOKEN_MINT, 6, TEST_TOKEN_MINT);

  // 3. 获取用户的代币账户
  const userSolAccount = await TokenAccount.getAssociatedTokenAccount(devnetConnection, wallet.publicKey, SOL_MINT);
  const userTestTokenAccount = await TokenAccount.getAssociatedTokenAccount(devnetConnection, wallet.publicKey, TEST_TOKEN_MINT);

  // 4. 定义兑换参数
  const rawAmountIn = 0.01; // 兑换0.01 SOL
  const amountIn = new TokenAmount(solToken, rawAmountIn * 10**solToken.decimals, false);
  const slippage = new Percent(50, 10000); // 0.5%滑点

  // 5. 获取池信息并计算最小输出
  const poolInfo = await Liquidity.fetchInfo(devnetConnection, poolKeys);
  const { minAmountOut } = Liquidity.computeAmountOut(poolInfo, amountIn, testToken, slippage);

  // 6. 构建兑换交易
  const { transaction, signers } = await Liquidity.makeSwapTransaction({
    connection: devnetConnection,
    poolKeys,
    userKeys: {
      owner: wallet.publicKey,
      source: userSolAccount.address,
      destination: userTestTokenAccount.address,
      // SOL兑换需额外传入钱包地址作为SOL源账户
      ...(solToken.isSOL ? { sourceSOL: wallet.publicKey } : {}),
    },
    amountIn,
    amountOut: minAmountOut,
    fixedSide: 'in',
  });

  // 7. 发送并确认交易
  const signature = await devnetConnection.sendTransaction(transaction, [wallet, ...signers], { skipPreflight: false });
  console.log(`交易哈希: ${signature}`);

  await devnetConnection.confirmTransaction(signature, 'confirmed');
  console.log(`交易已确认: ${signature}`);
}

main().catch(error => {
  console.error('错误:', error);
});

信息获取渠道

  • Raydium官方GitHub仓库的examples目录:包含兑换、添加流动性等完整交易示例
  • Solana官方文档:了解PublicKey、TokenAccount等核心概念的验证规则
  • Raydium SDK源码注释:直接查看函数的参数要求和返回值结构

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 04:19:54