The Swap Module provides a comprehensive token swapping solution that integrates multiple DEX providers into a unified interface for the Solana blockchain. It automatically finds the best routes and prices across different protocols to maximize trading efficiency.

Core Features

Multi-Provider Support

Integrated support for Jupiter aggregation, Raydium pools, and PumpSwap custom routing

Intelligent Routing

Automatic route optimization to find the best prices and lowest fees across all DEXs

Real-time Pricing

Live price updates, slippage calculations, and fee estimates for informed trading decisions

Advanced Controls

Customizable slippage, provider selection, and transaction parameters for power users

Installation & Setup

1

Import Module

Import the swap components and hooks:

import { 
  SwapScreen,
  useSwapLogic,
  TradeService,
  SelectTokenModal 
} from '@/modules/swap';
2

Wallet Integration

Ensure wallet providers are configured:

import { useWallet } from '@/modules/wallet-providers';
3

DEX Configuration

Configure DEX provider settings (optional):

const swapConfig = {
  defaultProvider: 'jupiter',
  slippageTolerance: 0.5,
  enableCustomPools: true
};

Module Architecture

The swap module is built with a modular, provider-agnostic architecture:

src/modules/swap/
├── components/             # UI components
│   ├── SwapScreen.tsx     # Main swap interface
│   ├── SelectTokenModal.tsx
│   ├── SwapComponents/    # Specialized components
│   │   ├── Shimmer.tsx
│   │   ├── ProviderSelector.tsx
│   │   ├── PumpSwapControls.tsx
│   │   ├── SwapInfo.tsx
│   │   ├── StatusDisplay.tsx
│   │   └── Keypad.tsx
├── hooks/                 # Custom React hooks
│   └── useSwapLogic.ts
├── services/              # DEX integrations
│   ├── TradeService.ts
│   └── JupiterService.ts
└── index.ts              # Public API exports

DEX Providers

Primary DEX Aggregator - Best price discovery across all Solana DEXs

import { JupiterService } from '@/modules/swap';

// Get optimal swap quote
const quote = await JupiterService.getQuote({
  inputMint: 'So11111111111111111111111111111111111111112', // SOL
  outputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC
  amount: 1000000000, // 1 SOL in lamports
  slippageBps: 50 // 0.5% slippage
});

// Execute swap with Jupiter
const result = await JupiterService.executeSwap({
  quote,
  userPublicKey: wallet.publicKey,
  sendTransaction
});

Features:

  • Route optimization across 20+ DEXs
  • Price impact calculation
  • Multi-hop swaps
  • Minimal slippage
  • Best execution prices

Core Components

SwapScreen - Complete swap interface with all features

import { SwapScreen } from '@/modules/swap';

function TradingInterface() {
  return (
    <SwapScreen
      defaultInputToken="SOL"
      defaultOutputToken="USDC"
      theme="dark"
      showProviderSelector={true}
      enableCustomSlippage={true}
    />
  );
}

Features:

  • Token selection with search
  • Real-time price updates
  • Provider selection interface
  • Slippage controls
  • Transaction status tracking
  • Error handling and recovery

Core Hook: useSwapLogic

The primary hook for swap functionality:

import { useSwapLogic } from '@/modules/swap';
import { useWallet } from '@/modules/wallet-providers';

function CustomSwapImplementation() {
  const { publicKey, connected, sendTransaction } = useWallet();
  const routeParams = useRoute().params || {};
  
  const {
    // Token state
    inputToken,
    outputToken,
    setInputToken,
    setOutputToken,
    
    // Amount and pricing
    inputAmount,
    setInputAmount,
    outputAmount,
    exchangeRate,
    priceImpact,
    
    // Transaction state
    isLoading,
    transactionStatus,
    error,
    
    // Actions
    handleSwap,
    handleTokenSwitch,
    refreshPrices,
    
    // Provider state
    selectedProvider,
    setSelectedProvider,
    availableProviders,
    
    // Advanced options
    slippage,
    setSlippage,
    customPoolAddress,
    setCustomPoolAddress
  } = useSwapLogic(routeParams, publicKey, connected, sendTransaction);

  return (
    <View style={styles.container}>
      <TokenPairSelector 
        inputToken={inputToken}
        outputToken={outputToken}
        onInputTokenChange={setInputToken}
        onOutputTokenChange={setOutputToken}
        onSwitch={handleTokenSwitch}
      />
      
      <AmountInput
        value={inputAmount}
        onChange={setInputAmount}
        token={inputToken}
      />
      
      <SwapDetails
        outputAmount={outputAmount}
        exchangeRate={exchangeRate}
        priceImpact={priceImpact}
        provider={selectedProvider}
      />
      
      <SwapButton
        onPress={handleSwap}
        loading={isLoading}
        disabled={!connected || !inputAmount}
      />
    </View>
  );
}

TradeService Integration

Provider-agnostic service for executing swaps:

basic_swap_execution
object
advanced_swap_options
object
fee_calculation
object

Quick Start Examples

import { SwapScreen } from '@/modules/swap';
import { useWallet } from '@/modules/wallet-providers';

function BasicTradingApp() {
  const { connected } = useWallet();

  if (!connected) {
    return (
      <View style={styles.connectPrompt}>
        <Text style={styles.title}>Connect Wallet to Trade</Text>
        <ConnectWalletButton />
      </View>
    );
  }

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Token Swap</Text>
      <SwapScreen
        defaultInputToken="SOL"
        defaultOutputToken="USDC"
        showProviderSelector={true}
        enableCustomSlippage={true}
        theme="dark"
      />
    </View>
  );
}

Advanced Features

Real-time Price Monitoring

function useRealTimePricing(inputToken, outputToken, amount) {
  const [quote, setQuote] = useState(null);
  const [priceHistory, setPriceHistory] = useState([]);

  useEffect(() => {
    if (!inputToken || !outputToken || !amount) return;

    const fetchQuote = async () => {
      try {
        const newQuote = await TradeService.getQuote(inputToken, outputToken, amount);
        setQuote(newQuote);
        
        // Track price history
        setPriceHistory(prev => [
          ...prev.slice(-29), // Keep last 30 prices
          {
            timestamp: Date.now(),
            rate: newQuote.rate,
            priceImpact: newQuote.priceImpact
          }
        ]);
      } catch (error) {
        console.error('Quote fetch failed:', error);
      }
    };

    // Initial fetch
    fetchQuote();
    
    // Update every 10 seconds
    const interval = setInterval(fetchQuote, 10000);
    return () => clearInterval(interval);
  }, [inputToken, outputToken, amount]);

  return { quote, priceHistory };
}

Slippage Protection

function useSlippageProtection() {
  const [slippageSettings, setSlippageSettings] = useState({
    auto: true,
    custom: 0.5,
    maxImpact: 5.0
  });

  const calculateOptimalSlippage = (priceImpact, volatility) => {
    if (priceImpact < 0.1) return 0.1;
    if (priceImpact < 0.5) return 0.3;
    if (priceImpact < 1.0) return 0.5;
    if (priceImpact < 3.0) return 1.0;
    return Math.min(priceImpact * 1.5, 5.0);
  };

  const validateSlippage = (quote, slippage) => {
    if (quote.priceImpact > slippageSettings.maxImpact) {
      throw new Error(`Price impact (${quote.priceImpact}%) exceeds maximum allowed (${slippageSettings.maxImpact}%)`);
    }
    
    if (slippage < quote.priceImpact) {
      console.warn('Slippage tolerance may be too low for current market conditions');
    }
    
    return true;
  };

  return {
    slippageSettings,
    setSlippageSettings,
    calculateOptimalSlippage,
    validateSlippage
  };
}

Multi-Route Comparison

function useMultiRouteComparison(inputToken, outputToken, amount) {
  const [routes, setRoutes] = useState({});
  const [bestRoute, setBestRoute] = useState(null);

  useEffect(() => {
    if (!inputToken || !outputToken || !amount) return;

    const compareRoutes = async () => {
      try {
        const [jupiterQuote, raydiumQuote, pumpQuote] = await Promise.allSettled([
          TradeService.getQuote(inputToken, outputToken, amount, { provider: 'jupiter' }),
          TradeService.getQuote(inputToken, outputToken, amount, { provider: 'raydium' }),
          TradeService.getQuote(inputToken, outputToken, amount, { provider: 'pumpswap' })
        ]);

        const routeResults = {
          jupiter: jupiterQuote.status === 'fulfilled' ? jupiterQuote.value : null,
          raydium: raydiumQuote.status === 'fulfilled' ? raydiumQuote.value : null,
          pumpswap: pumpQuote.status === 'fulfilled' ? pumpQuote.value : null
        };

        setRoutes(routeResults);

        // Find best route by output amount
        const best = Object.entries(routeResults)
          .filter(([_, quote]) => quote !== null)
          .reduce((best, [provider, quote]) => 
            !best || quote.outputAmount > best.quote.outputAmount 
              ? { provider, quote } 
              : best
          , null);

        setBestRoute(best);
      } catch (error) {
        console.error('Route comparison failed:', error);
      }
    };

    compareRoutes();
  }, [inputToken, outputToken, amount]);

  return { routes, bestRoute };
}

Error Handling & Recovery

common_swap_errors
object
function RobustSwapExecution() {
  const executeSwapWithRetry = async (swapParams, maxRetries = 3) => {
    let lastError;
    
    for (let attempt = 1; attempt <= maxRetries; attempt++) {
      try {
        return await TradeService.executeSwap(...swapParams);
      } catch (error) {
        lastError = error;
        console.warn(`Swap attempt ${attempt} failed:`, error.message);
        
        if (attempt === maxRetries) break;
        
        // Handle specific errors
        if (error.message.includes('slippage')) {
          // Increase slippage and retry
          swapParams[5] = { 
            ...swapParams[5], 
            slippageBps: (swapParams[5]?.slippageBps || 50) * 1.5 
          };
        } else if (error.message.includes('network')) {
          // Wait before retry for network issues
          await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
        }
      }
    }
    
    throw lastError;
  };

  return { executeSwapWithRetry };
}

Performance Optimization

Quote Caching: Implement intelligent quote caching to reduce API calls and improve response times.

Rate Limiting: Be mindful of DEX API rate limits when implementing real-time price updates.

function useOptimizedQuoting() {
  const [quoteCache, setQuoteCache] = useState(new Map());
  const [lastQuoteTime, setLastQuoteTime] = useState(0);
  
  const getCachedQuote = (inputToken, outputToken, amount) => {
    const key = `${inputToken}-${outputToken}-${amount}`;
    const cached = quoteCache.get(key);
    
    if (cached && Date.now() - cached.timestamp < 10000) { // 10 second cache
      return cached.quote;
    }
    
    return null;
  };
  
  const fetchQuoteWithCache = async (inputToken, outputToken, amount) => {
    // Check cache first
    const cached = getCachedQuote(inputToken, outputToken, amount);
    if (cached) return cached;
    
    // Rate limiting
    const now = Date.now();
    if (now - lastQuoteTime < 1000) { // 1 second minimum between requests
      await new Promise(resolve => setTimeout(resolve, 1000 - (now - lastQuoteTime)));
    }
    
    const quote = await TradeService.getQuote(inputToken, outputToken, amount);
    
    // Cache result
    const key = `${inputToken}-${outputToken}-${amount}`;
    setQuoteCache(prev => new Map(prev.set(key, {
      quote,
      timestamp: Date.now()
    })));
    
    setLastQuoteTime(Date.now());
    return quote;
  };
  
  return { fetchQuoteWithCache };
}

Integration with Other Modules

API Reference

For detailed API documentation, see:


The Swap Module provides the foundation for all token trading activities in your Solana app, offering users the best possible prices through intelligent multi-DEX routing while maintaining a simple and intuitive interface.