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

如何用Uniswap SDK获取代币对历史汇率及当前汇率?

Uniswap SDK 相关问题解答

一、通过SDK获取当前兑换汇率(x和y的当前储备量)

Uniswap SDK(V2/V3逻辑类似)可直接从链上拉取资金池的实时储备数据,进而计算当前汇率。

V2版本示例代码

import { ChainId, Token, Pair, Fetcher } from '@uniswap/sdk';

// 定义目标代币与链ID
const tokenX = new Token(ChainId.MAINNET, '0x...', 18); // 替换为X代币地址
const tokenY = new Token(ChainId.MAINNET, '0x...', 18); // 替换为Y代币地址

// 获取资金池实例
const pair = await Fetcher.fetchPairData(tokenX, tokenY);

// 提取当前储备量
const reserveX = pair.reserve0;
const reserveY = pair.reserve1;

// 计算1枚X代币可兑换的Y代币数量
const rateXtoY = reserveY.divide(reserveX).toSignificant(6);
console.log(`当前1 X = ${rateXtoY} Y`);

说明:Fetcher会自动从链上获取最新储备数据,reserve0/reserve1对应排序后的两种代币储备,可根据代币地址匹配x/y对应关系。

V3版本示例代码

import { ChainId, Token, Pool, FeeAmount } from '@uniswap/v3-sdk';
import { ethers } from 'ethers';

// 初始化以太坊Provider
const provider = new ethers.providers.JsonRpcProvider('https://mainnet.infura.io/v3/your-api-key');

// 定义代币与手续费层级
const tokenX = new Token(ChainId.MAINNET, '0x...', 18);
const tokenY = new Token(ChainId.MAINNET, '0x...', 18);
const feeAmount = FeeAmount.MEDIUM; // 0.3%手续费层级

// 获取资金池合约并调用slot0接口
const poolAddress = Pool.getAddress(tokenX, tokenY, feeAmount);
const poolContract = new ethers.Contract(
  poolAddress,
  ['function slot0() view returns (uint160 sqrtPriceX96, int24 tick, uint16 observationIndex, uint16 observationCardinality, uint16 observationCardinalityNext, uint8 feeProtocol, bool unlocked)'],
  provider
);
const slot0 = await poolContract.slot0();

// 从sqrtPriceX96转换为实际汇率(考虑代币精度)
const sqrtPriceX96 = slot0.sqrtPriceX96;
const rawPriceXtoY = (sqrtPriceX96 ** 2) / (2 ** 192);
const formattedPrice = ethers.utils.formatUnits(rawPriceXtoY.toString(), tokenY.decimals - tokenX.decimals);
console.log(`当前1 X = ${formattedPrice} Y`);

说明:V3用sqrtPriceX96存储价格,需通过公式转换为可读汇率,同时要兼容两种代币的精度差异。

二、获取xy=k曲线的历史数据(SDK原生方案限制)

Uniswap SDK本身没有内置历史数据查询接口,核心聚焦实时链上交互。若要基于SDK实现历史数据获取,有两种可行思路:

  • 思路1:结合历史区块查询
    利用以太坊Provider的历史区块调用能力,指定目标区块号,调用资金池合约的getReserves(V2)或slot0(V3)接口,手动提取对应区块的储备/价格数据,再计算历史k值。
    示例(V2 + ethers):

    const targetBlock = 17000000; // 目标历史区块号
    const historicalReserves = await pair.contract.getReserves({ blockTag: targetBlock });
    const historicalReserveX = historicalReserves[0];
    const historicalReserveY = historicalReserves[1];
    const historicalK = historicalReserveX.mul(historicalReserveY);
    console.log(`区块${targetBlock}的k值:${historicalK.toString()}`);
    

    注意:该方式适合少量历史区块查询,批量查询易触发节点限制,效率较低。

  • 思路2:基于SDK兼容的社区工具
    部分Uniswap社区工具(如@uniswap/v3-staker衍生工具)会封装历史数据查询逻辑,但本质仍是调用链上历史区块接口,未脱离链上查询范畴。

若需批量获取历史数据,GraphQL(如Uniswap Subgraph)仍是更高效的方案;若坚持纯SDK路线,只能通过上述历史区块调用方式实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 15:30:10