Skip to main content

Multi-SDK Integration Strategies

Build sophisticated DeFi applications by combining the concentrated liquidity power of DLMM with the comprehensive ecosystem features of the Main SDK.

Multi-SDK Architecture Pattern

Unified SDK Integration Design

Cross-Pool Arbitrage Flow

The Integration Advantage

When you combine both SDKs, you unlock capabilities that neither SDK provides alone:
  • Liquidity optimization across concentrated and traditional pools
  • Yield maximization through intelligent pool routing
  • Risk distribution across different AMM mechanisms
  • Advanced arbitrage between pool types

Architecture Pattern: Unified Pool Manager

import { DLMM } from '@saros-finance/dlmm-sdk';
import { SarosSDK } from '@saros-finance/sdk';
import { Connection, PublicKey } from '@solana/web3.js';

class UnifiedPoolManager {
  private dlmm: DLMM;
  private mainSDK: SarosSDK;
  private connection: Connection;

  constructor(connection: Connection, wallet: PublicKey) {
    this.connection = connection;
    this.dlmm = new DLMM(connection, wallet);
    this.mainSDK = new SarosSDK(connection, wallet);
  }

  async getBestSwapRoute(
    tokenA: PublicKey,
    tokenB: PublicKey,
    amount: number
  ): Promise<SwapRoute> {
    // Check both DLMM and traditional pools
    const [dlmmQuote, tradQuote] = await Promise.all([
      this.dlmm.getSwapQuote(tokenA, tokenB, amount),
      this.mainSDK.getSwapQuote(tokenA, tokenB, amount)
    ]);

    // Return the better route
    return dlmmQuote.outputAmount > tradQuote.outputAmount 
      ? { type: 'dlmm', quote: dlmmQuote }
      : { type: 'traditional', quote: tradQuote };
  }

  async executeOptimalSwap(route: SwapRoute): Promise<string> {
    if (route.type === 'dlmm') {
      return await this.dlmm.swap(route.quote);
    } else {
      return await this.mainSDK.swap(route.quote);
    }
  }
}

Cross-Pool Arbitrage System

Build an arbitrage system that captures price differences between DLMM and traditional pools:
class CrossPoolArbitrage {
  private poolManager: UnifiedPoolManager;
  private minProfitBps: number = 50; // 0.5% minimum profit

  async scanArbitrageOpportunities(): Promise<ArbitrageOp[]> {
    const opportunities = [];
    
    for (const pair of this.getActivePairs()) {
      const [dlmmPrice, tradPrice] = await Promise.all([
        this.dlmm.getPrice(pair.tokenA, pair.tokenB),
        this.mainSDK.getPrice(pair.tokenA, pair.tokenB)
      ]);

      const priceDiff = Math.abs(dlmmPrice - tradPrice) / Math.min(dlmmPrice, tradPrice);
      
      if (priceDiff * 10000 > this.minProfitBps) {
        opportunities.push({
          pair,
          buyPool: dlmmPrice < tradPrice ? 'dlmm' : 'traditional',
          sellPool: dlmmPrice < tradPrice ? 'traditional' : 'dlmm',
          expectedProfit: priceDiff,
          volume: await this.calculateOptimalVolume(pair, priceDiff)
        });
      }
    }

    return opportunities.sort((a, b) => b.expectedProfit - a.expectedProfit);
  }

  async executeArbitrage(opportunity: ArbitrageOp): Promise<boolean> {
    try {
      // Execute both legs atomically
      const buyTx = opportunity.buyPool === 'dlmm' 
        ? await this.dlmm.swap(opportunity.buyQuote)
        : await this.mainSDK.swap(opportunity.buyQuote);

      const sellTx = opportunity.sellPool === 'dlmm'
        ? await this.dlmm.swap(opportunity.sellQuote) 
        : await this.mainSDK.swap(opportunity.sellQuote);

      return true;
    } catch (error) {
      console.error('Arbitrage failed:', error);
      return false;
    }
  }
}

Intelligent Yield Optimization

Automatically move liquidity between pool types based on market conditions:
class YieldOptimizer {
  async optimizeLiquidityPlacement(
    tokenA: PublicKey,
    tokenB: PublicKey,
    totalLiquidity: number
  ): Promise<LiquidityAllocation> {
    const analysis = await this.analyzeLiquidityConditions(tokenA, tokenB);
    
    // Dynamic allocation based on volatility and volume
    if (analysis.volatility > 0.15 && analysis.volume > 1000000) {
      // High volatility + high volume = favor DLMM
      return {
        dlmmAllocation: 0.7,
        traditionalAllocation: 0.3,
        reasoning: 'High volatility favors concentrated liquidity fees'
      };
    } else if (analysis.volatility < 0.05) {
      // Low volatility = favor traditional AMM
      return {
        dlmmAllocation: 0.3,
        traditionalAllocation: 0.7,
        reasoning: 'Low volatility reduces impermanent loss in traditional pools'
      };
    }

    // Balanced approach for moderate conditions
    return {
      dlmmAllocation: 0.5,
      traditionalAllocation: 0.5,
      reasoning: 'Balanced allocation for moderate market conditions'
    };
  }
}

Performance Monitoring

Track performance across both SDK implementations:
class PerformanceTracker {
  async trackCrossSDKMetrics(): Promise<PerformanceReport> {
    const [dlmmMetrics, mainMetrics] = await Promise.all([
      this.dlmm.getPerformanceMetrics(),
      this.mainSDK.getPerformanceMetrics()
    ]);

    return {
      totalVolume: dlmmMetrics.volume + mainMetrics.volume,
      averageLatency: (dlmmMetrics.latency + mainMetrics.latency) / 2,
      successRate: this.calculateWeightedSuccessRate(dlmmMetrics, mainMetrics),
      profitability: {
        dlmm: dlmmMetrics.totalFees - dlmmMetrics.impermanentLoss,
        traditional: mainMetrics.totalFees - mainMetrics.impermanentLoss,
        arbitrage: this.arbitrageProfit
      },
      recommendations: this.generateOptimizationTips(dlmmMetrics, mainMetrics)
    };
  }
}

Production Deployment Patterns

Microservice Architecture

// API Gateway service
class SarosAPIGateway {
  private services = {
    dlmm: new DLMMService(),
    traditional: new TraditionalAMMService(),
    arbitrage: new ArbitrageService()
  };

  async route(request: APIRequest): Promise<APIResponse> {
    const optimalService = await this.determineOptimalService(request);
    return await this.services[optimalService].handle(request);
  }
}

// Load balancing for high-frequency operations
class LoadBalancer {
  async distributeRequests(requests: SwapRequest[]): Promise<SwapResult[]> {
    const dlmmRequests = requests.filter(r => r.prefersDLMM);
    const tradRequests = requests.filter(r => !r.prefersDLMM);

    return await Promise.all([
      this.processDLMMBatch(dlmmRequests),
      this.processTradBatch(tradRequests)
    ]).then(results => results.flat());
  }
}

Next Steps

Ready to implement advanced strategies? Choose your path:
Pro Tip: Always benchmark your multi-SDK implementation against single-SDK approaches. The added complexity should deliver measurable benefits in yield, efficiency, or user experience.