Swapping and Adding Liquidity on Uniswap V3: A Complete Guide

·

Introduction

This guide provides a step-by-step walkthrough for executing a swap-and-add liquidity operation in a single atomic transaction on Uniswap V3. By combining a swap with liquidity provision, you can optimize asset ratios before depositing into pools—ensuring 100% utilization of your tokens.

Key Concepts Covered:


Prerequisites


Step 1: Setting Up the Router Instance

Approving Token Transfers

Before swapping, approve the SwapRouter contract to manage your tokens:

const tokenInApproval = await getTokenTransferApproval(
  token0,
  V3_SWAP_ROUTER_ADDRESS
);
const tokenOutApproval = await getTokenTransferApproval(
  token1,
  V3_SWAP_ROUTER_ADDRESS
);

Initializing AlphaRouter

Configure the router with a mainnet provider (even for local forks):

import { AlphaRouter } from '@uniswap/smart-order-router';
const router = new AlphaRouter({ chainId: 1, provider });

👉 Learn more about Uniswap routing strategies


Step 2: Configuring Ratio Parameters

Currency Amounts

Define input amounts using CurrencyAmount:

const token0Amount = CurrencyAmount.fromRawAmount(
  token0,
  fromReadableAmount(token0AmountToAdd, token0.decimals)
);

Placeholder Position

Create a temporary position to calculate liquidity:

const placeholderPosition = new Position({
  pool,
  liquidity: 1,
  tickLower: nearestUsableTick(pool.tickCurrent, pool.tickSpacing) - pool.tickSpacing * 2,
  tickUpper: nearestUsableTick(pool.tickCurrent, pool.tickSpacing) + pool.tickSpacing * 2
});

Swap Configuration

Set tolerance and iteration limits:

const swapAndAddConfig = {
  ratioErrorTolerance: new Fraction(1, 100), // 1% margin
  maxIterations: 6
};

Step 3: Calculating Optimal Ratios

Calling routeToRatio

Execute the ratio-finding algorithm:

const response = await router.routeToRatio(
  token0Amount,
  token1Amount,
  placeholderPosition,
  swapAndAddConfig,
  {
    swapOptions: {
      type: SwapType.SWAP_ROUTER_02,
      recipient: address,
      slippageTolerance: new Percent(50, 10_000), // 0.5%
      deadline: Math.floor(Date.now() / 1000) + 60 * 20 // 20 minutes
    },
    addLiquidityOptions: { tokenId: existingPositionId }
  }
);

Handling Responses

Verify success status before proceeding:

if (response?.status !== SwapToRatioStatus.SUCCESS) {
  throw new Error('Route calculation failed');
}

Step 4: Executing the Transaction

Construct and submit the transaction:

const route = response.result;
const tx = {
  data: route.methodParameters.calldata,
  to: V3_SWAP_ROUTER_ADDRESS,
  value: route.methodParameters.value,
  from: address
};
const txRes = await wallet.sendTransaction(tx);

👉 Explore advanced DeFi strategies


FAQs

Why use atomic swap-and-add?

Atomic transactions prevent price slippage between the swap and liquidity addition steps, ensuring optimal asset ratios.

What if the algorithm exceeds max iterations?

Reduce ratioErrorTolerance or increase maxIterations (trade-off: longer computation time).

Can I add liquidity without an existing position?

No—you must mint a position first via NonfungiblePositionManager.


Conclusion

By following this guide, you’ve learned to:

  1. Configure the AlphaRouter for ratio optimization
  2. Calculate and validate currency ratios
  3. Execute atomic swap-and-add transactions

Implement this method to maximize capital efficiency in Uniswap V3 liquidity provision. For further optimization, explore Uniswap’s SDK examples.


### Key Features of This Guide: