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

Uniswap V3(Polygon)按价格切换交易池代码修改求助

Uniswap V3 自动选择最优交易池实现方案(Polygon链)

要实现根据价格自动选择最优交易池,核心思路是遍历同交易对的所有手续费层级池子,通过Quoter计算每个池子完成ExactOutput兑换所需的输入量,最终选用输入量最少(兑换成本最低)的池子。下面是具体实现步骤和修改后的代码:

实现步骤

  • 第一步:获取目标交易对的所有可用Uniswap V3池子
    你需要先通过Uniswap V3的PoolFactory合约或Subgraph,查询出sellToken和buyToken之间所有存在的手续费层级(0.05%、0.3%、1%等)对应的池子地址和实例。
  • 第二步:批量调用Quoter计算每个池子的输入量
    对每个有效池子,调用quoteExactOutputSingle方法,计算固定输出量下所需的输入代币数量。
  • 第三步:筛选最优池子
    比较所有池子的输入量,选择输入量最小的那个池子作为交易路由。
  • 第四步:用最优池子构建交易并执行
    基于选中的池子创建Route和Trade,生成SwapRouter调用参数并发起交易。

修改后的完整代码

// 定义Polygon链上Uniswap V3常用手续费层级,对应0.05%、0.3%、1%
const POOL_FEES = [500, 3000, 10000];

async split(signer: Signer): Promise<void> {
  const address = await signer.getAddress();
  const { buyToken, sellToken, buyAmount } = await this.calculateSplitPurchase(address);

  if (buyAmount.lessThan(0) || buyAmount.equalTo(0)) {
    return;
  }

  console.log(`Buying ${buyAmount.toFixed()} ${buyToken.name} with ${sellToken.name}`);

  // 获取所有可用池子实例
  const pools = await Promise.all(POOL_FEES.map(async (fee) => {
    try {
      // 通过PoolFactory查询池子地址
      const poolAddress = await this.poolFactory.getPool(
        sellToken.isNative ? WETH_ADDRESS : sellToken.address,
        buyToken.isNative ? WETH_ADDRESS : buyToken.address,
        fee
      );
      if (poolAddress === ethers.constants.AddressZero) return null;

      // 初始化池子实例
      const poolContract = this.poolContractFactory.attach(poolAddress);
      const [slot0, liquidity, tickSpacing] = await Promise.all([
        poolContract.slot0(),
        poolContract.liquidity(),
        poolContract.tickSpacing()
      ]);
      
      return new Pool(
        sellToken,
        buyToken,
        fee,
        slot0.sqrtPriceX96.toString(),
        liquidity.toString(),
        tickSpacing
      );
    } catch (err) {
      console.warn(`Failed to fetch pool with fee ${fee}:`, err);
      return null;
    }
  })).then(pools => pools.filter(p => p !== null));

  if (pools.length === 0) {
    throw new Error("No available pools for the token pair");
  }

  // 批量计算每个池子的输入量
  const poolQuotes = await Promise.all(pools.map(async (pool) => {
    try {
      const amountIn = await this.quoter.callStatic.quoteExactOutputSingle(
        sellToken.isNative ? WETH_ADDRESS : sellToken.address,
        buyToken.isNative ? WETH_ADDRESS : buyToken.address,
        pool.fee,
        buyAmount.quotient.toString(10),
        0
      );
      return { pool, amountIn: BigInt(amountIn) };
    } catch (err) {
      console.warn(`Failed to quote pool with fee ${pool.fee}:`, err);
      return null;
    }
  })).then(quotes => quotes.filter(q => q !== null));

  if (poolQuotes.length === 0) {
    throw new Error("No valid quotes from available pools");
  }

  // 筛选输入量最小的最优池子
  const bestQuote = poolQuotes.reduce((prev, curr) => {
    return curr.amountIn < prev.amountIn ? curr : prev;
  });

  // 构建交易路由和参数
  const route = new Route([bestQuote.pool], sellToken, buyToken);
  const trade = Trade.createUncheckedTrade({
    route,
    tradeType: TradeType.EXACT_OUTPUT,
    inputAmount: CurrencyAmount.fromRawAmount(sellToken, bestQuote.amountIn.toString()),
    outputAmount: CurrencyAmount.fromRawAmount(buyToken, buyAmount.quotient.toString(10)),
  });

  const params = SwapRouter.swapCallParameters([trade], {
    slippageTolerance: new Percent(2, 1000),
    recipient: address,
    deadline: ethers.constants.MaxUint256.toString(),
  });

  await this.swap(signer, params);
}

async swap(signer: Signer, params: MethodParameters): Promise<void> {
  const tx = await signer.sendTransaction({
    to: this.router.address,
    from: await signer.getAddress(),
    data: params.calldata,
    value: params.value,
    //gasPrice: await getFastGasPrice(),
    //gasLimit: 1300000,
  });
  await tx.wait(3);
}

关键注意事项

  • 池子获取方式:如果追求效率,建议提前从Uniswap V3 Subgraph批量查询常用交易对的池子信息,避免实时调用合约带来的Gas成本和延迟。
  • 异常处理:要处理池子不存在、Quoter调用失败(比如流动性不足)的情况,避免交易中断。
  • 滑点设置:可以根据不同池子的流动性情况动态调整滑点,流动性高的池子可以设置更小的滑点。
  • 原生币处理:代码中已兼容原生MATIC和WETH的转换,确保交易时正确处理value参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 13:15:40