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

# Route Swaps

> Multi-hop swaps across multiple pools for indirect asset pairs

Route swaps (or multi-hop swaps) allow you to trade between two assets by routing the transaction through one or more intermediary pools. This is useful when there's no direct liquidity pool for a specific asset pair but a path exists through other pools.

The Flashnet SDK simplifies this process by allowing you to define a series of "hops" that make up the desired route.

<Note>
  The maximum number of hops allowed in a single route swap is 4.
</Note>

## Simulating a Route Swap

Before executing, it's crucial to simulate the route swap to get an estimate of the expected output, price impact, and fees.

```typescript theme={null}
async function simulateRouteSwap() {
  try {
    const simulation = await client.simulateRouteSwap({
      hops: [
        {
          poolId: "btc-usdb-pool-id",
          assetInAddress: "bitcoin-pubkey",
          assetOutAddress: "usdb-pubkey",
        },
        {
          poolId: "usdb-eur-pool-id",
          assetInAddress: "usdb-pubkey",
          assetOutAddress: "eur-pubkey",
        },
      ],
      amountIn: "10000000", // 0.1 BTC
      maxRouteSlippageBps: "100", // 1%
    });

    console.log('Expected final output amount:', simulation.outputAmount);
    console.log('Total price impact %:', simulation.totalPriceImpactPct);
    console.log('Hop breakdown:', simulation.hopBreakdown);
    
    return simulation;
  } catch (error) {
    console.error('Route swap simulation failed:', error);
  }
}
```

The simulation provides a breakdown for each hop, allowing you to see how the swap progresses at each stage.

## Executing a Route Swap

To execute the swap, you provide the same hop structure along with slippage parameters. The SDK handles the transfer to the first pool and the subsequent routing automatically.

```typescript theme={null}
async function executeRouteSwap() {
  try {
    // First, simulate to get an expected output
    const simulation = await client.simulateRouteSwap({
      hops: [
        { poolId: "btc-usdb-pool-id", assetInAddress: "bitcoin-pubkey", assetOutAddress: "usdb-pubkey" },
        { poolId: "usdb-eur-pool-id", assetInAddress: "usdb-pubkey", assetOutAddress: "eur-pubkey" },
      ],
      amountIn: "10000000", // 0.1 BTC
      maxRouteSlippageBps: "100",
    });

    if (!simulation) {
      throw new Error("Simulation failed, cannot execute.");
    }

    // Set a minimum amount out based on simulation to protect against slippage
    const minAmountOut = (BigInt(simulation.outputAmount) * 99n / 100n).toString(); // 1% tolerance

    const response = await client.executeRouteSwap({
      hops: [
        {
          poolId: "btc-usdb-pool-id",
          assetInAddress: "bitcoin-pubkey",
          assetOutAddress: "usdb-pubkey",
        },
        {
          poolId: "usdb-eur-pool-id",
          assetInAddress: "usdb-pubkey",
          assetOutAddress: "eur-pubkey",
        },
      ],
      initialAssetAddress: "bitcoin-pubkey",
      inputAmount: "10000000",
      maxRouteSlippageBps: "100", // 1%
      minAmountOut: minAmountOut,
    });

    console.log('Route swap successful!');
    console.log('Final amount out:', response.outputAmount);
    console.log('Final transfer ID:', response.finalOutboundTransferId);

  } catch (error) {
    console.error('Route swap execution failed:', error);
  }
}
```

### Integrator Fees

You can also specify integrator fees for the entire route or for individual hops.

```typescript theme={null}
async function executeRouteSwapWithFees() {
    const minAmountOut = "950000"; // calculated from simulation

    await client.executeRouteSwap({
      hops: [
        {
          poolId: "btc-usdb-pool-id",
          assetInAddress: "bitcoin-pubkey",
          assetOutAddress: "usdb-pubkey",
          hopIntegratorFeeRateBps: 20, // 0.2% fee for this specific hop
        },
        {
          poolId: "usdb-eur-pool-id",
          assetInAddress: "usdb-pubkey",
          assetOutAddress: "eur-pubkey",
        },
      ],
      initialAssetAddress: "bitcoin-pubkey",
      inputAmount: "10000000",
      maxRouteSlippageBps: "100",
      minAmountOut: minAmountOut,
      integratorFeeRateBps: 10, // 0.1% fee for any hop that doesn't have a specific fee
      integratorPublicKey: "your-integrator-pubkey",
    });
}
```

## Error Handling

Route swaps involve multiple pools and can fail at various points. The SDK provides typed errors with automatic fund recovery. See [Error Handling](/products/flashnet-amm/errors) for the complete guide.

```typescript theme={null}
import { isFlashnetError } from '@flashnet/sdk';

async function safeRouteSwap() {
  try {
    const response = await client.executeRouteSwap({
      hops: [
        { poolId: "pool-1", assetInAddress: "btc", assetOutAddress: "usdb" },
        { poolId: "pool-2", assetInAddress: "usdb", assetOutAddress: "token" },
      ],
      initialAssetAddress: "btc",
      inputAmount: "10000000",
      maxRouteSlippageBps: "100",
      minAmountOut: "950000",
    });
    
    console.log('Success:', response.outputAmount);
  } catch (error) {
    if (isFlashnetError(error)) {
      console.log('Error:', error.errorCode, '-', error.userMessage);
      
      // Check fund recovery
      if (error.wasClawbackAttempted()) {
        if (error.wereAllTransfersRecovered()) {
          console.log('✅ Input funds recovered');
        } else {
          console.log('⚠️ Recovery needed for:', error.transferIds);
        }
      } else if (error.willAutoRefund()) {
        console.log('Funds will be auto-refunded');
      }
      
      // Handle specific errors
      if (error.isSlippageError()) {
        console.log('Price moved too much across the route');
      }
    }
  }
}
```

## Next Steps

* [Learn about single-pool swaps](/products/flashnet-amm/swaps)
* [Provide liquidity to earn fees](/products/flashnet-amm/liquidity)
* [Error Handling](/products/flashnet-amm/errors) for complete error reference
