如何通过Uniswap获取一种加密货币对另一种的兑换价值?
在Uniswap上获取代币兑换价格的可行方案
不管用Uniswap SDK还是直接调用智能合约,都能轻松获取类似1 ETH = X 1INCH的兑换价格,以下是具体实现步骤:
一、使用Uniswap SDK(以V3为例,V2逻辑类似)
首先安装必要依赖:
npm install @uniswap/sdk-core @uniswap/v3-sdk ethers
核心是通过流动性池的储备数据计算价格,示例代码如下:
import { ChainId, Token } from '@uniswap/sdk-core'; import { Pool, FeeAmount, computePoolAddress } from '@uniswap/v3-sdk'; import { ethers } from 'ethers'; // 定义代币信息(主网环境) const WETH = new Token(ChainId.MAINNET, '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', 18, 'WETH', 'Wrapped Ether'); const ONEINCH = new Token(ChainId.MAINNET, '0x111111111117dC0aa78b770fA6A738034120C302', 18, '1INCH', '1inch Token'); // 连接以太坊节点(替换为你的Alchemy/Infura节点URL) const provider = new ethers.providers.JsonRpcProvider('你的节点URL'); // 计算WETH-1INCH流动性池地址(0.05%手续费层级) const poolAddress = computePoolAddress({ factoryAddress: '0x1F98431c8aD98523631AE4a59f267346ea31F984', tokenA: WETH, tokenB: ONEINCH, fee: FeeAmount.LOW }); // 池合约ABI片段(仅获取价格所需方法) const poolAbi = [ 'function slot0() external view returns (uint160 sqrtPriceX96, int24 tick, uint16 observationIndex, uint16 observationCardinality, uint16 observationCardinalityNext, uint8 feeProtocol, bool unlocked)' ]; const poolContract = new ethers.Contract(poolAddress, poolAbi, provider); // 计算并打印价格 async function fetchPrice() { const { sqrtPriceX96 } = await poolContract.slot0(); // 从sqrtPriceX96计算1 WETH对应的1INCH数量 const oneEthInOneinch = WETH.priceOf(ONEINCH, sqrtPriceX96); console.log(`1 WETH = ${oneEthInOneinch.toFixed(4)} 1INCH`); } fetchPrice();
如果用Uniswap V2,安装@uniswap/v2-sdk,通过Pair类获取reserve0和reserve1,直接用reserve1 / reserve0计算价格即可。
二、直接调用Uniswap Router合约
Uniswap V3
Router合约提供了quoteExactInputSingle方法,可直接计算指定金额代币的兑换产出:
import { ChainId, Token } from '@uniswap/sdk-core'; import { FeeAmount } from '@uniswap/v3-sdk'; import { ethers } from 'ethers'; const WETH = new Token(ChainId.MAINNET, '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', 18); const ONEINCH = new Token(ChainId.MAINNET, '0x111111111117dC0aa78b770fA6A738034120C302', 18); const provider = new ethers.providers.JsonRpcProvider('你的节点URL'); // V3 Router地址 const routerAddress = '0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45'; const routerAbi = [ 'function quoteExactInputSingle(address tokenIn, address tokenOut, uint24 fee, uint256 amountIn, uint160 sqrtPriceLimitX96) external view returns (uint256 amountOut)' ]; const routerContract = new ethers.Contract(routerAddress, routerAbi, provider); async function getQuote() { const amountIn = ethers.utils.parseEther('1'); // 1 WETH const amountOut = await routerContract.quoteExactInputSingle( WETH.address, ONEINCH.address, FeeAmount.LOW, amountIn, 0 // 不设置价格限制 ); console.log(`1 WETH = ${ethers.utils.formatEther(amountOut)} 1INCH`); } getQuote();
Uniswap V2
V2 Router的getAmountOut方法需要先获取流动性池的储备数据,再计算:
import { ethers } from 'ethers'; const WETH_ADDR = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'; const ONEINCH_ADDR = '0x111111111117dC0aa78b770fA6A738034120C302'; const provider = new ethers.providers.JsonRpcProvider('你的节点URL'); // V2 Router地址 const v2RouterAddress = '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D'; const routerAbi = [ 'function getPair(address tokenA, address tokenB) external view returns (address)', 'function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) public pure returns (uint amountOut)' ]; const routerContract = new ethers.Contract(v2RouterAddress, routerAbi, provider); async function getV2Price() { // 获取WETH-1INCH池地址 const pairAddr = await routerContract.getPair(WETH_ADDR, ONEINCH_ADDR); // 获取池的储备数据 const pairAbi = ['function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast)']; const pairContract = new ethers.Contract(pairAddr, pairAbi, provider); const { reserve0, reserve1 } = await pairContract.getReserves(); // 计算1 WETH对应的1INCH数量 const amountOut = await routerContract.getAmountOut(ethers.utils.parseEther('1'), reserve0, reserve1); console.log(`1 WETH = ${ethers.utils.formatEther(amountOut)} 1INCH`); } getV2Price();
注意事项
- 必须用WETH而非原生ETH,Uniswap的流动性池仅支持ERC20代币。
- 确认网络ChainId正确(主网1、Goerli测试网5等)。
- 不同手续费层级的池价格可能有差异,需匹配目标池的fee tier(0.01%、0.05%、0.3%、1%)。
内容的提问来源于stack exchange,提问作者Shadq
相关产品推荐
相关产品推荐

