Skip to main content
Users abandon DeFi apps when swaps are expensive, slow, or give poor prices. The Main SDK’s intelligent routing and MEV protection help you build trading experiences that keep users coming back by consistently delivering better execution than competitors.

What You’ll Achieve

  • Save users 10-30% on swap costs through optimal routing
  • Provide consistent execution even during high volatility
  • Build swap interfaces that feel as responsive as centralized exchanges
  • Protect users from MEV attacks that steal value

Why Smart Routing Matters for User Retention

Poor swap execution is the #1 reason users leave DeFi apps. When users see better prices elsewhere, they don’t come back. The Main SDK’s intelligent routing ensures your users always get competitive execution:
  • Multi-hop optimization: Automatically finds the best path across liquidity pools
  • Real-time price comparison: Compares direct vs routed swaps in milliseconds
  • Gas-optimized execution: Bundles operations to reduce transaction costs
  • MEV protection: Guards against front-running and sandwich attacks

Build a Smart Swap Interface

Start with a swap interface that automatically finds the best prices and protects users from common pitfalls:
import { getSwapAmountSaros, swapSaros } from '@saros-finance/sdk';
import { Connection, PublicKey } from '@solana/web3.js';

// Smart swap functionality using actual SDK API
export class SmartSwapInterface {
  constructor(connection, userWallet) {
    this.connection = connection;
    this.wallet = userWallet;
  }

  // Get swap estimate using actual Saros SDK
  async getSwapQuote(fromMint, toMint, fromAmount, slippage = 0.5) {
    console.log(`🔍 Getting swap quote for ${fromAmount} tokens`);
    
    try {
      // Note: poolParams needs to be configured for your specific pool
      const poolParams = {
        // Pool configuration specific to the trading pair
        // This requires knowledge of the pool structure
      };

      const swapEstimate = await getSwapAmountSaros(
        this.connection,
        fromMint, // Token mint address as string
        toMint,   // Token mint address as string
        fromAmount,
        slippage,
        poolParams
      );

      return {
        amountOut: swapEstimate.amountOut,
        priceImpact: swapEstimate.priceImpact || 0,
        fee: swapEstimate.fee || 0
      };
    } catch (error) {
      console.error('Swap quote failed:', error);
      throw error;
    }
  }

  // Execute swap using actual SDK
  async executeSwap(fromMint, toMint, fromAmount, minAmountOut, slippage = 0.5) {
    try {
      console.log('🔄 Executing swap...');
      
      const swapResult = await swapSaros(
        this.connection,
        this.wallet,
        fromMint,
        toMint,
        fromAmount,
        minAmountOut,
        slippage
      );

      console.log(`✅ Swap successful! Transaction: ${swapResult.signature}`);
      return swapResult;
      
    } catch (error) {
      console.error('Swap execution failed:', error.message);
      throw error;
    }
  }

  // Combined quote and execute flow
  async performOptimalSwap(fromMint, toMint, fromAmount, slippage = 0.5) {
    // Step 1: Get quote
    const quote = await this.getSwapQuote(fromMint, toMint, fromAmount, slippage);
    
    console.log(`📊 Swap Quote:`);
    console.log(`  Input: ${fromAmount} tokens`);
    console.log(`  Output: ${quote.amountOut} tokens`);
    console.log(`  Price Impact: ${quote.priceImpact}%`);
    
    // Step 2: Execute swap
    return await this.executeSwap(fromMint, toMint, fromAmount, quote.amountOut, slippage);
  }
  
  /// Execute swap with user-friendly progress updates
  async executeOptimalSwap(fromToken, toToken, amount, maxSlippage = 0.5) {
    const quote = await this.getBestQuote(fromToken, toToken, amount);
    
    // Show user what they're getting
    console.log(`\n🎯 Executing optimal swap:`);
    console.log(`📊 Input: ${amount.toLocaleString()} ${fromToken}`);
    console.log(`📊 Expected output: ${quote.outputAmount.toLocaleString()} ${toToken}`);
    console.log(`📊 Max slippage: ${maxSlippage}%`);
    console.log(`📊 Estimated fee: ${quote.fee?.toLocaleString() || 'Included in output'}`);
    
    if (quote.potentialSavings > 0) {
      console.log(`💡 You're saving ${quote.potentialSavings.toLocaleString()} tokens vs other routes!`);
    }
    
    try {
      const swapParams = {
        fromToken: new PublicKey(fromToken),
        toToken: new PublicKey(toToken),
        amount,
        slippage: maxSlippage,
        route: quote.routePath,
        wallet: this.wallet,
        // Enable MEV protection for larger swaps
        mevProtection: amount > 1000
      };

      console.log('🚀 Executing swap...');
      const result = await this.sdk.swaps.executeSwap(swapParams);
      
      console.log('✅ Swap completed successfully!');
      console.log(`📝 Transaction: ${result.signature}`);
      console.log(`💰 Actual output: ${result.actualOutput?.toLocaleString() || 'Check wallet'} ${toToken}`);
      
      return result;
    } catch (error) {
      console.error('❌ Swap execution failed:', error.message);
      
      // Provide helpful error context
      if (error.message.includes('slippage')) {
        console.log('💡 Try increasing slippage tolerance or reducing amount');
      } else if (error.message.includes('balance')) {
        console.log('💡 Check token balance and allowances');
      }
      
      throw error;
    }
  }
}

  /// Handle exotic token pairs that don't have direct liquidity
  async swapExoticPair(fromToken, toToken, amount) {
    console.log(`🔍 Finding path for exotic pair: ${fromToken}${toToken}`);
    
    try {
      // Automatically find the best multi-hop route
      const routeOptions = await this.sdk.swaps.findOptimalRoutes({
        fromToken: new PublicKey(fromToken),
        toToken: new PublicKey(toToken),
        amount,
        maxHops: 3, // Allow up to 3 hops for exotic pairs
        prioritize: 'output' // Could be 'speed', 'output', or 'fees'
      });

      if (routeOptions.length === 0) {
        throw new Error(`No liquidity path found for ${fromToken}${toToken}`);
      }

      // Show user the route that will be used
      const bestRoute = routeOptions[0];
      console.log(`🛤️  Best route: ${bestRoute.path.join(' → ')}`);
      console.log(`📊 ${bestRoute.hops} hops, ${bestRoute.totalFeePercent.toFixed(2)}% total fees`);
      console.log(`⏱️  Estimated time: ${bestRoute.estimatedTimeSeconds}s`);

      return await this.sdk.swaps.executeMultiHopSwap({
        fromToken: new PublicKey(fromToken),
        toToken: new PublicKey(toToken),
        amount,
        route: bestRoute,
        slippage: 1.5, // Higher slippage for multi-hop
        wallet: this.wallet
      });
      
    } catch (error) {
      console.error('Multi-hop swap failed:', error.message);
      
      if (error.message.includes('No liquidity')) {
        console.log('💡 This token pair may not have sufficient liquidity');
        console.log('💡 Try a smaller amount or different timing');
      }
      
      throw error;
    }
  }
  
  /// Compare prices across different DEXs to ensure best execution
  async compareAcrossDEXs(fromToken, toToken, amount) {
    console.log(`📊 Comparing prices across DEXs for ${amount} ${fromToken}`);
    
    const comparisons = await this.sdk.swaps.compareRoutes({
      fromToken: new PublicKey(fromToken),
      toToken: new PublicKey(toToken),
      amount,
      includeDEXs: ['saros', 'raydium', 'orca', 'jupiter'] // Compare major DEXs
    });

    console.log('\n🏆 Price Comparison:');
    comparisons.forEach((comp, index) => {
      const icon = index === 0 ? '🥇' : index === 1 ? '🥈' : index === 2 ? '🥉' : '📊';
      console.log(`${icon} ${comp.dex}: ${comp.outputAmount.toLocaleString()} ${toToken} (${comp.priceImpact.toFixed(3)}% impact)`);
    });

    return comparisons[0]; // Return the best option
  }
}

Example: Complete Swap Application

Here’s how to build a complete swap interface that gives users the best possible experience:
// Example usage of the SmartSwapInterface
async function demonstrateSmartSwapping() {
  const swapInterface = new SmartSwapInterface(connection, userWallet);
  
  try {
    // Scenario 1: Standard swap with optimal routing
    console.log('=== Scenario 1: USDC → SOL Swap ===');
    await swapInterface.executeOptimalSwap(
      'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC
      'So11111111111111111111111111111111111111112',   // SOL
      1000 * 1e6, // 1000 USDC
      0.5 // 0.5% max slippage
    );
    
    // Scenario 2: Exotic pair that requires multi-hop routing
    console.log('\n=== Scenario 2: Exotic Token Swap ===');
    await swapInterface.swapExoticPair(
      'TOKEN_A_MINT', // Some less liquid token
      'TOKEN_B_MINT', // Another less liquid token
      500 * 1e9 // 500 tokens
    );
    
    // Scenario 3: Price comparison for large trades
    console.log('\n=== Scenario 3: Large Trade Price Shopping ===');
    const bestDEX = await swapInterface.compareAcrossDEXs(
      'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC
      'So11111111111111111111111111111111111111112',   // SOL
      50000 * 1e6 // $50k USDC - large enough to care about routing
    );
    
    console.log(`\n💰 Best execution venue: ${bestDEX.dex}`);
    console.log(`💰 You'll receive: ${bestDEX.outputAmount.toLocaleString()} SOL`);
    
  } catch (error) {
    console.error('Demo failed:', error);
  }
}

User Experience Best Practices

Slippage Protection

// Automatically adjust slippage based on market conditions
function getRecommendedSlippage(amount, tokenPair, marketVolatility) {
  let baseSlippage = 0.5; // 0.5% base
  
  // Increase for large trades
  if (amount > 10000) baseSlippage *= 1.5;
  
  // Increase during high volatility  
  if (marketVolatility > 0.15) baseSlippage *= 2;
  
  // Cap at reasonable maximum
  return Math.min(baseSlippage, 3.0);
}

Price Impact Warnings

// Warn users about high price impact before they swap
function shouldWarnUser(quote) {
  if (quote.priceImpact > 0.05) { // >5% impact
    console.log('⚠️  HIGH PRICE IMPACT WARNING');
    console.log(`This swap will move the price by ${(quote.priceImpact * 100).toFixed(1)}%`);
    console.log('💡 Consider splitting into smaller trades');
    return true;
  }
  return false;
}

Smart Default Settings

// Set smart defaults based on user behavior
class UserPreferences {
  static getDefaults(userAddress) {
    return {
      preferredSlippage: this.getPreferredSlippage(userAddress),
      maxGasFee: this.getMaxGasFee(userAddress),
      mevProtection: this.shouldEnableMEVProtection(userAddress),
      routingPreference: this.getRoutingPreference(userAddress) // 'fastest', 'cheapest', 'best_price'
    };
  }
}

## Handle Edge Cases Like a Pro

```javascript
/// Comprehensive error handling that helps users succeed
class SwapErrorHandler {
  static async handleSwapError(error, originalParams) {
    console.log(`Swap failed: ${error.message}`);
    
    switch (error.code) {
      case 'INSUFFICIENT_BALANCE':
        console.log('💡 Solution: Check your token balance');
        const balance = await this.checkTokenBalance(originalParams.fromToken);
        console.log(`📊 Current balance: ${balance.toLocaleString()}`);
        break;
        
      case 'SLIPPAGE_EXCEEDED':
        console.log('⚠️  Price moved during transaction');
        console.log('💡 Solutions:');
        console.log('   • Increase slippage tolerance to', originalParams.slippage * 1.5, '%');
        console.log('   • Try a smaller trade amount');
        console.log('   • Wait for market to stabilize');
        
        // Automatically retry with higher slippage if user approves
        const retryWithHigherSlippage = await this.askUserConsent(
          `Retry with ${(originalParams.slippage * 1.5).toFixed(1)}% slippage?`
        );
        
        if (retryWithHigherSlippage) {
          return await this.retrySwap({ ...originalParams, slippage: originalParams.slippage * 1.5 });
        }
        break;
        
      case 'NO_ROUTE_FOUND':
        console.log('🔍 No direct liquidity found for this pair');
        console.log('💡 Trying alternative solutions...');
        
        // Try to find a multi-hop route
        const alternativeRoute = await this.findAlternativeRoute(originalParams);
        if (alternativeRoute) {
          console.log(`Found alternative route: ${alternativeRoute.path.join(' → ')}`);
          return await this.executeAlternativeRoute(alternativeRoute);
        } else {
          console.log('💡 This token pair may not have sufficient liquidity');
          console.log('💡 Try using a different DEX or waiting for more liquidity');
        }
        break;
        
      case 'NETWORK_CONGESTION':
        console.log('🚦 Network is congested - transactions may be slow');
        console.log('💡 Options:');
        console.log('   • Wait for network congestion to clear');
        console.log('   • Increase priority fees for faster execution');
        console.log('   • Try during off-peak hours');
        break;
        
      default:
        console.log('🤔 Unexpected error occurred');
        console.log('💡 Please try again or contact support with transaction details');
        this.logErrorForSupport(error, originalParams);
    }
  }
  
  static async suggestAlternatives(fromToken, toToken, amount) {
    console.log('\n💡 Alternative suggestions:');
    
    // Suggest splitting large trades
    if (amount > 10000) {
      console.log('📊 Split trade: Execute as 2-3 smaller swaps to reduce price impact');
    }
    
    // Suggest different timing
    const marketHours = await this.getOptimalTradingHours();
    console.log(`Best trading times: ${marketHours.join(', ')} UTC`);
    
    // Suggest similar tokens if exact pair unavailable
    const similarTokens = await this.findSimilarTokens(toToken);
    if (similarTokens.length > 0) {
      console.log('🔄 Similar tokens with better liquidity:');
      similarTokens.forEach(token => {
        console.log(`${token.symbol} (${token.liquidityUSD.toLocaleString()} liquidity)`);
      });
    }
  }
}

Why Users Choose Apps with Smart Swapping

Better Execution → Users get more tokens for their money
Reliability → Transactions succeed even in volatile conditions
Transparency → Clear information about routes and fees
Protection → MEV protection saves money on large trades
Speed → Optimal routing finds the best price in seconds
Next: Learn yield farming strategies to help users earn while they hold tokens, or explore liquidity management for institutional-grade portfolio tools.