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:
- Setting up a router instance with
AlphaRouter
- Calculating optimal currency ratios for pool deposits
- Configuring swap-and-add parameters
- Executing atomic transactions using
SwapRouter
Prerequisites
- Familiarity with Uniswap V3 Position Minting
Installed Uniswap SDK packages:
- `@uniswap/v3-sdk` - `@uniswap/sdk-core` - `@uniswap/smart-order-router`
- An existing ERC-721 position (required for adding liquidity)
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:
- Configure the
AlphaRouter
for ratio optimization - Calculate and validate currency ratios
- 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: