# Router Swap

### Overview

The Router module automatically finds the optimal path for your swap by:

* **Path Discovery**: Finds all possible routes between tokens
* **TVL Optimization**: Prioritizes pools with higher liquidity
* **Multi-hop Support**: Routes through intermediate tokens when beneficial
* **Best Rate Selection**: Compares all paths to find optimal execution

### Quick Start

```typescript
// 1. Find best route
const bestRoute = await sdk.Router.getBestInternalRouter(
  '0x2::sui::SUI',           // From token
  '0x...::usdc::USDC',       // To token
  new BN('1000000000'),      // Amount (1 SUI)
  true,                      // Fix input amount
  0.01,                      // 1% slippage
  ''                         // No partner
)

// 2. Create swap transaction
if (bestRoute && !bestRoute.isExceed) {
  const tx = await TransactionUtil.buildRouterSwapTransaction(
    sdk,
    bestRoute.createTxParams,
    true,  // byAmountIn
    allCoinAssets
  )
  
  const result = await sdk.fullClient.signAndExecuteTransaction({
    transaction: tx,
    signer: keypair
  })
}
```

### Find Optimal Route

#### Basic Route Finding

```typescript
const bestRoute = await sdk.Router.getBestInternalRouter(
  fromCoin,      // Source token
  toCoin,        // Target token
  amount,        // Swap amount
  true,          // Fix input (true) or output (false)
  0.005,         // 0.5% slippage
  ''             // Partner ID (optional)
)

console.log({
  inputAmount: bestRoute.amountIn.toString(),
  outputAmount: bestRoute.amountOut.toString(),
  paths: bestRoute.paths.length,
  isExceed: bestRoute.isExceed
})
```

#### With Fallback Options

```typescript
// Fallback params for direct swap if no route found
const fallbackParams = {
  poolAddresses: ['0xpool1...', '0xpool2...'],
  coinTypeA: fromCoin,
  coinTypeB: toCoin,
  a2b: true,
  byAmountIn: true,
  amount: swapAmount.toString()
}

const bestRoute = await sdk.Router.getBestInternalRouter(
  fromCoin,
  toCoin,
  swapAmount,
  true,
  0.01,
  '',
  fallbackParams  // Will use direct swap if no route
)
```

### Route Types

#### Single-Hop Route

Direct swap in one pool:

```typescript
// Route: SUI -> USDC
bestRoute.paths[0] = {
  poolAddress: ['0xpool...'],
  a2b: [true],
  coinType: ['0x2::sui::SUI', '0x...::usdc::USDC'],
  amountIn: BN,
  amountOut: BN
}
```

#### Multi-Hop Route

Through intermediate token:

```typescript
// Route: SUI -> USDT -> USDC
bestRoute.paths[0] = {
  poolAddress: ['0xpool1...', '0xpool2...'],
  a2b: [true, true],
  coinType: ['0x2::sui::SUI', '0x...::usdt::USDT', '0x...::usdc::USDC'],
  amountIn: BN,
  amountOut: BN
}
```

### Complete Swap Flow

```typescript
async function smartRouterSwap() {
  try {
    // 1. Get user's coin assets
    const allCoinAssets = await sdk.getOwnerCoinAssets(userAddress)
    
    // 2. Define swap parameters
    const fromCoin = '0x2::sui::SUI'
    const toCoin = '0x...::usdc::USDC'
    const swapAmount = new BN('10000000000') // 10 SUI
    const slippage = 0.01 // 1%
    
    // 3. Find optimal route
    console.log('Finding best route...')
    const bestRoute = await sdk.Router.getBestInternalRouter(
      fromCoin,
      toCoin,
      swapAmount,
      true,     // Fix input
      slippage,
      ''        // No partner
    )
    
    // 4. Check if route is valid
    if (!bestRoute || bestRoute.isExceed) {
      throw new Error('No valid route found')
    }
    
    // 5. Display route info
    console.log('Route found:')
    console.log(`  Input: ${bestRoute.amountIn.toString()}`)
    console.log(`  Output: ${bestRoute.amountOut.toString()}`)
    console.log(`  Hops: ${bestRoute.paths[0].poolAddress.length}`)
    console.log(`  Pools: ${bestRoute.paths[0].poolAddress.join(' -> ')}`)
    
    // 6. Create swap transaction
    const tx = await TransactionUtil.buildRouterSwapTransaction(
      sdk,
      bestRoute.createTxParams,
      true,  // byAmountIn
      allCoinAssets
    )
    
    // 7. Execute swap
    const result = await sdk.fullClient.signAndExecuteTransaction({
      transaction: tx,
      signer: keypair
    })
    
    console.log('Swap completed:', result.digest)
    
  } catch (error) {
    console.error('Router swap failed:', error)
  }
}
```

### Load Graph Data

Router needs graph data to find paths:

```typescript
// Method 1: Auto-load from API
if (!sdk.Router.isGraphLoaded) {
  await sdk.Router.loadGraphData()
}

// Method 2: Manual load with custom data
const coinData = {
  coins: [
    { address: '0x2::sui::SUI', decimals: 9 },
    { address: '0x...::usdc::USDC', decimals: 6 },
    { address: '0x...::usdt::USDT', decimals: 6 }
  ]
}

const pathData = {
  paths: [
    {
      base: '0x2::sui::SUI',
      quote: '0x...::usdc::USDC',
      addressMap: new Map([[30, '0xpool1...']]) // 0.3% fee
    }
  ]
}

sdk.Router.loadGraph(coinData, pathData)
```

### Advanced Features

#### TVL-Based Routing

Router prioritizes high-TVL pools:

```typescript
// Router automatically sorts multi-hop paths by minimum TVL
const poolsWithTvl = await sdk.Router.getPoolWithTVL()

poolsWithTvl.forEach(pool => {
  console.log(`Pool ${pool.poolAddress}: ${pool.tvl}`)
})
```

#### Custom Path Preferences

```typescript
// Find route with specific requirements
const bestRoute = await sdk.Router.getBestInternalRouter(
  fromCoin,
  toCoin,
  swapAmount,
  true,
  0.005,    // Tighter slippage for large trades
  partnerID // Route fees to partner
)

// Check route quality
if (bestRoute.paths[0].poolAddress.length > 2) {
  console.log('Route too complex, consider direct swap')
}
```

#### Fix Output Amount

```typescript
// Want exactly 1000 USDC
const bestRoute = await sdk.Router.getBestInternalRouter(
  '0x2::sui::SUI',
  '0x...::usdc::USDC',
  new BN('1000000000'),  // 1000 USDC
  false,                 // Fix output
  0.01,
  ''
)

console.log(`Need ${bestRoute.amountIn} SUI`)
```

### Error Handling

```typescript
try {
  const bestRoute = await sdk.Router.getBestInternalRouter(
    fromCoin, toCoin, amount, true, 0.01, ''
  )
  
  if (!bestRoute) {
    console.log('No route available')
  } else if (bestRoute.isExceed) {
    console.log('Insufficient liquidity in pools')
  } else if (bestRoute.paths.length === 0) {
    console.log('No valid path found')
  }
  
} catch (error) {
  if (error.code === 'InvalidCoin') {
    console.log('Token not supported')
  } else if (error.code === 'NotFoundPath') {
    console.log('No trading path exists')
  }
}
```

### Route Information

```typescript
interface BestInternalRouterResult {
  amountIn: BN              // Input amount
  amountOut: BN             // Output amount
  paths: OnePath[]          // Route paths
  isExceed: boolean         // Exceeds liquidity
  createTxParams: SwapWithRouterParams  // Ready-to-use params
}

interface OnePath {
  poolAddress: string[]     // Pool addresses in order
  a2b: boolean[]           // Swap directions
  coinType: string[]       // Coin types in path
  amountIn: BN             // Path input
  amountOut: BN            // Path output
}
```

### Important Notes

* Router automatically loads graph data on first use
* Multi-hop limited to 2 pools (3 tokens max)
* TVL-based routing improves execution quality
* Partner fees not supported with split paths
* Always check `isExceed` before executing
* Graph data cached for performance


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.ferra.ag/integration/clmm/typescript-sdk/router-swap.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
