> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mobula.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Pool Targeting: Route Swaps Through Specific Pools

> Learn how to target specific liquidity pools or DEX protocols when executing swaps via the Mobula Swap API

## Overview

By default, the Mobula Swap API automatically finds the best route across all available liquidity sources. However, you may want to **target a specific pool** or **restrict routing to certain protocols** — for example, to:

* Execute a swap directly through a specific Aerodrome CL pool on Base
* Restrict routing to only Uniswap V3 pools
* Avoid certain factory contracts
* Force routing through a specific DEX for compliance or analytics

The Swap API provides three parameters for pool targeting:

| Parameter           | Routing             | Description                                                                                  |
| ------------------- | ------------------- | -------------------------------------------------------------------------------------------- |
| `poolAddress`       | **Direct on-chain** | Target a specific pool by address — bypasses aggregators, executes directly via MobulaRouter |
| `onlyProtocols`     | Via aggregator      | Restrict to specific pool types (e.g., `uniswap-v3`) — routed through KyberSwap/Jupiter      |
| `excludedProtocols` | Via aggregator      | Exclude specific factory addresses from routing                                              |

<Note>
  **Key difference**: `poolAddress` routes the swap **directly on-chain** through MobulaRouter's `executeRoute` function. `onlyProtocols` passes the restriction to an external aggregator (KyberSwap, Jupiter) which handles the routing.
</Note>

## Direct Pool Access (`poolAddress`)

Use `poolAddress` when you know the exact pool contract address and want to swap **directly through it**, without going through an external aggregator. The swap is executed on-chain via MobulaRouter's internal routing engine.

### Basic Example

Route a USDC → WETH swap directly through a specific Aerodrome CL pool on Base:

```bash theme={null}
curl -X GET "https://api.mobula.io/api/2/swap/quoting?\
chainId=evm:8453\
&tokenIn=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\
&tokenOut=0x4200000000000000000000000000000000000006\
&amount=100\
&walletAddress=0xYourWallet\
&slippage=1\
&poolAddress=0xb4cb800910b228ed3d0834cf79d697127bbb00e5"
```

### Concrete Example — USDC to TKFG on Aerodrome CL (Base)

This example swaps \~300 USDC (raw units) to TKFG on Base, routed directly through the Aerodrome CL pool:

```bash theme={null}
curl -X GET "https://api.mobula.io/api/2/swap/quoting?\
chainId=evm%3A8453\
&tokenIn=0x833589fcd6edb6e08f4c7c32d4f71b54bda02913\
&tokenOut=0xe9d139df6212fde346ec650e83039f322018f60d\
&amountRaw=300539874\
&walletAddress=0xYourWallet\
&slippage=1\
&poolAddress=0x66fbdb0b14a889b3735da163843289a55d28bb97"
```

The response transaction will use MobulaRouter's `executeRoute` selector (`0xa564dfa4`), executing the swap directly on-chain without any aggregator intermediary.

<Tip>
  You can discover pool addresses using the [Token Markets](/rest-api-reference/endpoint/token-markets) endpoint, which returns all pools for a given token pair along with their addresses, types, and liquidity.
</Tip>

### When to Use `poolAddress`

* You want **zero aggregator fees** — the swap goes directly through the pool
* You need **deterministic routing** — always the exact same pool, no fallback
* You're building a **pool-specific UI** (e.g., showing swap for a specific market)
* Multiple pools exist for the same pair (e.g., different fee tiers) and you want a specific one

## Filtering by Protocol (`onlyProtocols`)

Use `onlyProtocols` to restrict the swap to pools of a specific type. The swap is routed through an external aggregator (KyberSwap on EVM, Jupiter on Solana) which applies the filter.

### Single Protocol

Route a swap exclusively through Uniswap V3 pools:

```bash theme={null}
curl -X GET "https://api.mobula.io/api/2/swap/quoting?\
chainId=evm:1\
&tokenIn=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE\
&tokenOut=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\
&amount=0.5\
&walletAddress=0xYourWallet\
&slippage=1\
&onlyProtocols=uniswap-v3"
```

### Multiple Protocols

Route through either Aerodrome CL or Uniswap V3 pools on Base:

```bash theme={null}
curl -X GET "https://api.mobula.io/api/2/swap/quoting?\
chainId=evm:8453\
&tokenIn=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\
&tokenOut=0x4200000000000000000000000000000000000006\
&amount=100\
&walletAddress=0xYourWallet\
&slippage=1\
&onlyProtocols=aerodrome-cl-2,uniswap-v3"
```

## Excluding Protocols (`excludedProtocols`)

Use `excludedProtocols` to exclude specific factory addresses from routing. Unlike `onlyProtocols` which takes pool type names, this parameter takes **factory contract addresses**:

```bash theme={null}
curl -X GET "https://api.mobula.io/api/2/swap/quoting?\
chainId=evm:1\
&tokenIn=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE\
&tokenOut=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\
&amount=1\
&walletAddress=0xYourWallet\
&slippage=1\
&excludedProtocols=0x1F98431c8aD98523631AE4a59f267346ea31F984"
```

## Common Pool Types

### EVM Chains

| Pool Type         | Description                                            |
| ----------------- | ------------------------------------------------------ |
| `uniswap-v2`      | Uniswap V2 and forks (SushiSwap, PancakeSwap V2, etc.) |
| `uniswap-v3`      | Uniswap V3 concentrated liquidity pools                |
| `uniswap-v4`      | Uniswap V4 pools with hooks                            |
| `aerodrome`       | Aerodrome V2 pools (Base)                              |
| `aerodrome-cl-2`  | Aerodrome CL (concentrated liquidity) pools (Base)     |
| `pancakeswap-v3`  | PancakeSwap V3 pools                                   |
| `solidly-v2`      | Solidly V2 pools and forks                             |
| `solidly-v3`      | Solidly V3 pools (CL)                                  |
| `trader-joe-v2.1` | Trader Joe Liquidity Book pools                        |
| `maverick-v2`     | Maverick V2 pools                                      |

### Solana

| Pool Type        | Description                                 |
| ---------------- | ------------------------------------------- |
| `raydium-amm`    | Raydium AMM pools                           |
| `raydium-clmm`   | Raydium concentrated liquidity pools        |
| `raydium-cpmm`   | Raydium constant product pools              |
| `orca-whirlpool` | Orca Whirlpool concentrated liquidity pools |
| `meteora-dlmm`   | Meteora DLMM pools                          |
| `pumpfun`        | PumpFun bonding curve pools                 |
| `pumpswap`       | PumpSwap pools                              |

<Note>
  Only **tradable** pool types are accepted by `onlyProtocols`. Non-tradable types are automatically filtered out. If no valid pool types remain after filtering, the API returns a "No route found" error.
</Note>

## Choosing a Router (`onlyRouters`)

You can also restrict which **aggregator/router** handles the swap, independently from pool targeting:

| Router      | Chains | Description                          |
| ----------- | ------ | ------------------------------------ |
| `kyberswap` | EVM    | KyberSwap aggregator (no extra fees) |
| `lifi`      | EVM    | LI.FI cross-chain aggregator         |
| `jupiter`   | Solana | Jupiter aggregator                   |

```bash theme={null}
curl -X GET "https://api.mobula.io/api/2/swap/quoting?\
chainId=evm:8453\
&tokenIn=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE\
&tokenOut=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\
&amount=0.01\
&walletAddress=0xYourWallet\
&slippage=1\
&onlyRouters=kyberswap"
```

## TypeScript Example

```typescript theme={null}
// Direct pool access — swap through a specific pool on-chain
async function swapViaSpecificPool() {
  const params = new URLSearchParams({
    chainId: 'evm:8453',
    tokenIn: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC
    tokenOut: '0x4200000000000000000000000000000000000006', // WETH
    amount: '100', // 100 USDC
    walletAddress: '0xYourWallet',
    slippage: '1',
    poolAddress: '0xb4cb800910b228ed3d0834cf79d697127bbb00e5', // Specific pool
  });

  const response = await fetch(
    `https://api.mobula.io/api/2/swap/quoting?${params}`,
    { headers: { Authorization: 'YOUR_API_KEY' } }
  );

  const { data } = await response.json();

  // Transaction uses MobulaRouter's executeRoute (direct on-chain)
  console.log('Route:', data.route);
  console.log('Estimated output:', data.estimatedAmountOut);
  console.log('Transaction:', data.evm?.transaction);
}

// Protocol-filtered — restrict aggregator to specific pool types
async function swapWithProtocolFilter() {
  const params = new URLSearchParams({
    chainId: 'evm:8453',
    tokenIn: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
    tokenOut: '0x4200000000000000000000000000000000000006',
    amount: '100',
    walletAddress: '0xYourWallet',
    slippage: '1',
    onlyProtocols: 'aerodrome-cl-2', // Only Aerodrome CL pools
  });

  const response = await fetch(
    `https://api.mobula.io/api/2/swap/quoting?${params}`,
    { headers: { Authorization: 'YOUR_API_KEY' } }
  );

  const { data } = await response.json();

  // Transaction uses aggregator (KyberSwap) with protocol filter
  console.log('Route:', data.route);
  console.log('Estimated output:', data.estimatedAmountOut);
  console.log('Transaction:', data.evm?.transaction);
}
```

## Troubleshooting

| Issue                                         | Cause                                              | Solution                                                            |
| --------------------------------------------- | -------------------------------------------------- | ------------------------------------------------------------------- |
| `"No route found"`                            | No pool of the requested type exists for this pair | Check the pool type name is correct, or try without `onlyProtocols` |
| `"Pool not found"`                            | The `poolAddress` doesn't exist in Mobula's index  | Verify the pool address on a block explorer                         |
| Swap uses aggregator instead of direct access | Used `onlyProtocols` instead of `poolAddress`      | Use `poolAddress` for direct on-chain routing                       |
| `"Invalid protocol"`                          | Typo in the pool type name                         | Check the [Common Pool Types](#common-pool-types) table above       |
