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

使用web3js无需调用官方API获取Uniswap、SushiSwap代币价格的方法

Uniswap/SushiSwap V3 链上价格查询(web3.js实现)

一、V3_pool_ABI的获取方式

Uniswap V3、SushiSwap V3的所有流动池合约都遵循统一的标准接口,无需针对单个池单独查询ABI,直接使用官方标准ABI即可,你可以根据需求选择以下两种形式:

  • 最小可用ABI片段(仅包含价格查询所需的slot0、代币地址查询方法,体积更小)
    直接将以下JSON赋值给V3_pool_ABI变量即可:
    [
      {"inputs":[],"name":"slot0","outputs":[{"internalType":"uint160","name":"sqrtPriceX96","type":"uint160"},{"internalType":"int24","name":"tick","type":"int24"},{"internalType":"uint16","name":"observationIndex","type":"uint16"},{"internalType":"uint16","name":"observationCardinality","type":"uint16"},{"internalType":"uint16","name":"observationCardinalityNext","type":"uint16"},{"internalType":"uint8","name":"feeProtocol","type":"uint8"},{"internalType":"bool","name":"unlocked","type":"bool"}],"stateMutability":"view","type":"function"},
      {"inputs":[],"name":"token0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},
      {"inputs":[],"name":"token1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}
    ]
    
  • 全量Pool ABI
    如果后续需要查询流动性、tick数据等更多功能,可以直接使用Uniswap官方开源的V3 Pool全量ABI,SushiSwap V3完全兼容该ABI。

二、原有代码的问题修正

你提交的代码存在以下可优化点:

  1. slot0调用多写了一次.call(),正确写法为await pool_1.methods.slot0().call()
  2. 价格计算逻辑错误,sqrtPriceX96是Q64.96格式的定点数,需要遵循Uniswap V3的官方定价公式转换为可读价格
  3. 缺少异常捕获逻辑,RPC调用失败时无法排查问题

三、完整可运行代码

const JSBI = require('jsbi');
const Web3 = require('web3');

// V3 流动池标准ABI(最小可用版)
const V3_pool_ABI = [
  {"inputs":[],"name":"slot0","outputs":[{"internalType":"uint160","name":"sqrtPriceX96","type":"uint160"},{"internalType":"int24","name":"tick","type":"int24"},{"internalType":"uint16","name":"observationIndex","type":"uint16"},{"internalType":"uint16","name":"observationCardinality","type":"uint16"},{"internalType":"uint16","name":"observationCardinalityNext","type":"uint16"},{"internalType":"uint8","name":"feeProtocol","type":"uint8"},{"internalType":"bool","name":"unlocked","type":"bool"}],"stateMutability":"view","type":"function"},
  {"inputs":[],"name":"token0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},
  {"inputs":[],"name":"token1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}
];

// V3 工厂合约ABI
const V3_FACTORY_ABI = [{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"fee","type":"uint24"},{"indexed":true,"internalType":"int24","name":"tickSpacing","type":"int24"}],"name":"FeeAmountEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token0","type":"address"},{"indexed":true,"internalType":"address","name":"token1","type":"address"},{"indexed":true,"internalType":"uint24","name":"fee","type":"uint24"},{"indexed":false,"internalType":"int24","name":"tickSpacing","type":"int24"},{"indexed":false,"internalType":"address","name":"pool","type":"address"}],"name":"PoolCreated","type":"event"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint24","name":"fee","type":"uint24"}],"name":"createPool","outputs":[{"internalType":"address","name":"pool","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"int24","name":"tickSpacing","type":"int24"}],"name":"enableFeeAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint24","name":"","type":"uint24"}],"name":"feeAmountTickSpacing","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint24","name":"","type":"uint24"}],"name":"getPool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"parameters","outputs":[{"internalType":"address","name":"factory","type":"address"},{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"int24","name":"tickSpacing","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"}]

// 以太坊主网V3工厂地址配置
const FACTORY_CONFIG = {
  uniswapV3: '0x1F98431c8aD98523631AE4a59f267346ea31F984',
  sushiswapV3: '0xbACEB8eC6b9355Dfc0269a83b980cb3992bbCf6A'
}

(async () => {
  // 初始化RPC连接,建议替换为你自己的Infura/Alchemy节点地址
  const web3 = new Web3(new Web3.providers.HttpProvider('https://mainnet.infura.io/v3/d5658a9beace4cd98d2c1216cf66b56a'));
  
  try {
    // 示例:查询Uniswap V3 DAI/WETH 0.3%费率池价格
    // 要查询SushiSwap V3价格,将下方FACTORY_CONFIG.uniswapV3替换为FACTORY_CONFIG.sushiswapV3即可
    const factoryContract = new web3.eth.Contract(V3_FACTORY_ABI, FACTORY_CONFIG.uniswapV3);

    // 参数依次为:代币A地址、代币B地址、费率(3000=0.3%,常见值还有500=0.05%、10000=1%)
    const poolAddress = await factoryContract.methods.getPool(
      '0x6b175474e89094c44da98b954eedeac495271d0f', // DAI地址
      '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', // WETH地址
      3000
    ).call();
    console.log('流动池地址:', poolAddress);

    const poolContract = new web3.eth.Contract(V3_pool_ABI, poolAddress);
    const slot0Data = await poolContract.methods.slot0().call();
    const sqrtPriceX96 = JSBI.BigInt(slot0Data.sqrtPriceX96);

    // 价格转换公式,适配精度相同的代币(DAI和WETH精度均为18)
    const Q192 = JSBI.exponentiate(JSBI.BigInt(2), JSBI.BigInt(192));
    const wethToDaiPrice = Number(JSBI.divide(JSBI.multiply(sqrtPriceX96, sqrtPriceX96), Q192));
    console.log('1 WETH = ', wethToDaiPrice.toFixed(2), ' DAI');

  } catch (error) {
    console.error('查询失败:', error.message);
  }
})();

四、使用说明

  • 运行前先安装依赖:npm install jsbi web3
  • 如果查询的两个代币精度不同,将价格转换逻辑中对应的精度值替换即可,比如USDC精度为6,就将对应系数改为1e6
  • 若要查询其他交易对,替换getPool方法中的代币地址和对应费率即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 05:09:00