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

# SDK Examples

# Simpfor.fun Integration Examples

Real-world examples showing how to build apps with the Simpfor.fun SDK. From simple copy trading bots to full dashboard applications.

## Copy Trading Bot

Build an automated copy trading bot that finds top traders and manages risk.

```typescript theme={"system"}
import { SimpforFunSDK } from 'simpfor-fun-sdk';

interface TraderCriteria {
  minROI: number;
  maxDrawdown: number;
  minWinRate: number;
  minFollowValue: number;
}

class CopyTradingBot {
  private sdk: SimpforFunSDK;
  private userId: number;
  private activeTrades = new Map<string, number>(); // trader -> copyTradeId

  constructor() {
    this.sdk = new SimpforFunSDK();
  }

  async initialize(email: string, otp: string) {
    const loginResult = await this.sdk.verifyOtp(email, otp);
    this.userId = loginResult.data.user.uid;
    console.log('Bot initialized for user:', this.userId);
  }

  async findQualifyingTraders(criteria: TraderCriteria) {
    const traders = await this.sdk.fetchTopTraders();
    
    return traders.filter(trader => 
      trader.roi >= criteria.minROI &&
      trader.maxDrawdown <= criteria.maxDrawdown &&
      trader.winRate >= criteria.minWinRate &&
      trader.followValue >= criteria.minFollowValue
    );
  }

  async startCopyTrade(traderAddress: string, walletAddress: string) {
    try {
      // Create copy trade relationship
      const copyTrade = await this.sdk.createCopyTrade(
        this.userId,
        traderAddress,
        walletAddress
      );

      // Start copying
      await this.sdk.runCopyTrade(this.userId, copyTrade.data.info.copyTradeId);
      
      // Track active trade
      this.activeTrades.set(traderAddress, copyTrade.data.info.copyTradeId);
      
      console.log(`Started copying ${traderAddress}`);
      return copyTrade.data.info.copyTradeId;
      
    } catch (error) {
      console.error(`Failed to copy ${traderAddress}:`, error);
      throw error;
    }
  }

  async monitorPerformance(stopLossPercent: number = 15) {
    const monitorInterval = setInterval(async () => {
      for (const [traderAddress, copyTradeId] of this.activeTrades) {
        try {
          const pnl = await this.sdk.getCopyTradeTotalPnl(
            this.userId, 
            'your-wallet-address'
          );
          
          // Calculate drawdown (simplified)
          const currentDrawdown = Math.abs(pnl.data.pnl) / 1000; // Assuming 1000 USDC base
          
          console.log(`${traderAddress}: ${pnl.data.pnl} USDC PnL`);
          
          // Stop loss check
          if (currentDrawdown > stopLossPercent / 100) {
            console.log(`Stop loss triggered for ${traderAddress} at ${currentDrawdown * 100}%`);
            await this.sdk.stopCopyTrade(this.userId, copyTradeId, true);
            this.activeTrades.delete(traderAddress);
          }
          
        } catch (error) {
          console.error(`Error monitoring ${traderAddress}:`, error);
        }
      }
      
      // Stop monitoring if no active trades
      if (this.activeTrades.size === 0) {
        clearInterval(monitorInterval);
        console.log('No active trades to monitor');
      }
    }, 60000); // Check every minute

    return monitorInterval;
  }

  async getPortfolioSummary() {
    const copyTrades = await this.sdk.listCopyTrades(this.userId);
    
    const summary = {
      activeTrades: 0,
      totalPnl: 0,
      trades: [] as Array<{
        leader: string;
        follower: string;
        pnl: number;
        active: boolean;
      }>
    };

    for (const trade of copyTrades.data.infos) {
      if (trade.active) {
        summary.activeTrades++;
        
        try {
          const pnl = await this.sdk.getCopyTradeTotalPnl(this.userId, trade.followerAccount);
          summary.totalPnl += pnl.data.pnl;
          
          summary.trades.push({
            leader: trade.leaderAccount,
            follower: trade.followerAccount,
            pnl: pnl.data.pnl,
            active: trade.active
          });
        } catch (error) {
          console.error(`Error getting PnL for ${trade.leaderAccount}:`, error);
        }
      }
    }

    return summary;
  }
}

// Usage Example
async function runBot() {
  const bot = new CopyTradingBot();
  
  // Initialize with your credentials
  await bot.initialize('your-email@example.com', '123456');

  // Find qualifying traders
  const criteria: TraderCriteria = {
    minROI: 0.20,        // 20% minimum ROI
    maxDrawdown: 0.15,   // 15% max drawdown
    minWinRate: 0.65,    // 65% win rate
    minFollowValue: 1000 // At least 1000 USDC following
  };

  const topTraders = await bot.findQualifyingTraders(criteria);
  console.log(`Found ${topTraders.length} qualifying traders`);

  // Start copying the best traders (limit to top 3)
  for (const trader of topTraders.slice(0, 3)) {
    try {
      await bot.startCopyTrade(trader.address, 'your-wallet-address');
      console.log(`Started copying ${trader.address} with ${trader.roi * 100}% ROI`);
    } catch (error) {
      console.error(`Failed to copy ${trader.address}:`, error);
    }
  }

  // Start monitoring with 15% stop loss
  await bot.monitorPerformance(15);

  // Get portfolio summary every 5 minutes
  setInterval(async () => {
    const summary = await bot.getPortfolioSummary();
    console.log('Portfolio Summary:', summary);
  }, 300000);
}

// Run the bot
runBot().catch(console.error);
```

## React Dashboard Application

Complete React dashboard for copy trading management.

```typescript theme={"system"}
import React, { useState, useEffect } from 'react';
import { SimpforFunSDK } from 'simpfor-fun-sdk';

interface DashboardState {
  user: any;
  traders: any[];
  copyTrades: any[];
  loading: boolean;
  error: string | null;
}

const CopyTradingDashboard: React.FC = () => {
  const [sdk] = useState(() => new SimpforFunSDK());
  const [state, setState] = useState<DashboardState>({
    user: null,
    traders: [],
    copyTrades: [],
    loading: false,
    error: null
  });

  // Login handler
  const handleLogin = async (email: string, otp: string) => {
    setState(prev => ({ ...prev, loading: true, error: null }));
    
    try {
      const result = await sdk.verifyOtp(email, otp);
      setState(prev => ({ ...prev, user: result.data.user }));
      await loadDashboardData(result.data.user.uid);
    } catch (error: any) {
      setState(prev => ({ 
        ...prev, 
        error: `Login failed: ${error.message}` 
      }));
    } finally {
      setState(prev => ({ ...prev, loading: false }));
    }
  };

  // Load dashboard data
  const loadDashboardData = async (userId: number) => {
    try {
      const [topTraders, userCopyTrades] = await Promise.all([
        sdk.fetchTopTraders(),
        sdk.listCopyTrades(userId)
      ]);
      
      setState(prev => ({
        ...prev,
        traders: topTraders.slice(0, 10),
        copyTrades: userCopyTrades.data.infos
      }));
    } catch (error: any) {
      setState(prev => ({ 
        ...prev, 
        error: `Failed to load data: ${error.message}` 
      }));
    }
  };

  // Start copy trading
  const startCopyTrade = async (traderAddress: string) => {
    if (!state.user) return;
    
    setState(prev => ({ ...prev, loading: true }));
    
    try {
      const copyTrade = await sdk.createCopyTrade(
        state.user.uid,
        traderAddress,
        'your-wallet-address' // Replace with actual wallet
      );
      
      await sdk.runCopyTrade(state.user.uid, copyTrade.data.info.copyTradeId);
      
      // Refresh data
      await loadDashboardData(state.user.uid);
      
      alert('Copy trading started successfully!');
    } catch (error: any) {
      setState(prev => ({ 
        ...prev, 
        error: `Failed to start copy trading: ${error.message}` 
      }));
    } finally {
      setState(prev => ({ ...prev, loading: false }));
    }
  };

  // Stop copy trading
  const stopCopyTrade = async (copyTradeId: number) => {
    if (!state.user) return;
    
    setState(prev => ({ ...prev, loading: true }));
    
    try {
      await sdk.stopCopyTrade(state.user.uid, copyTradeId, true);
      await loadDashboardData(state.user.uid);
      alert('Copy trading stopped');
    } catch (error: any) {
      setState(prev => ({ 
        ...prev, 
        error: `Failed to stop copy trading: ${error.message}` 
      }));
    } finally {
      setState(prev => ({ ...prev, loading: false }));
    }
  };

  return (
    <div className="dashboard">
      <h1>Copy Trading Dashboard</h1>
      
      {state.error && (
        <div className="error-banner">
          {state.error}
          <button onClick={() => setState(prev => ({ ...prev, error: null }))}>
            ✕
          </button>
        </div>
      )}

      {!state.user ? (
        <LoginForm onLogin={handleLogin} loading={state.loading} />
      ) : (
        <>
          <UserInfo user={state.user} />
          <TopTraders 
            traders={state.traders} 
            onCopy={startCopyTrade}
            loading={state.loading} 
          />
          <CopyTradesList 
            trades={state.copyTrades}
            onStop={stopCopyTrade}
            loading={state.loading}
          />
        </>
      )}
    </div>
  );
};

// Login Form Component
const LoginForm: React.FC<{
  onLogin: (email: string, otp: string) => void;
  loading: boolean;
}> = ({ onLogin, loading }) => {
  const [email, setEmail] = useState('');
  const [otp, setOtp] = useState('');
  const [otpSent, setOtpSent] = useState(false);
  const [sdk] = useState(() => new SimpforFunSDK());

  const sendOtp = async () => {
    try {
      await sdk.sendVerificationCode(email);
      setOtpSent(true);
      alert('OTP sent to your email');
    } catch (error: any) {
      alert(`Failed to send OTP: ${error.message}`);
    }
  };

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    onLogin(email, otp);
  };

  return (
    <form onSubmit={handleSubmit} className="login-form">
      <div>
        <input
          type="email"
          placeholder="Email address"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          required
        />
        <button type="button" onClick={sendOtp} disabled={!email || otpSent}>
          {otpSent ? 'OTP Sent' : 'Send OTP'}
        </button>
      </div>
      
      {otpSent && (
        <div>
          <input
            type="text"
            placeholder="Enter 6-digit OTP"
            value={otp}
            onChange={(e) => setOtp(e.target.value)}
            maxLength={6}
            required
          />
          <button type="submit" disabled={loading || otp.length !== 6}>
            {loading ? 'Logging in...' : 'Login'}
          </button>
        </div>
      )}
    </form>
  );
};

// User Info Component
const UserInfo: React.FC<{ user: any }> = ({ user }) => (
  <div className="user-info">
    <h2>Welcome, {user.email}</h2>
    <p>User ID: {user.uid}</p>
    <p>Referral Code: {user.referralCode}</p>
  </div>
);

// Top Traders Component
const TopTraders: React.FC<{
  traders: any[];
  onCopy: (address: string) => void;
  loading: boolean;
}> = ({ traders, onCopy, loading }) => (
  <div className="section">
    <h2>Top Traders</h2>
    <div className="traders-grid">
      {traders.map(trader => (
        <div key={trader.address} className="trader-card">
          <h3>{trader.address.slice(0, 8)}...{trader.address.slice(-6)}</h3>
          <div className="trader-stats">
            <p><strong>ROI:</strong> {(trader.roi * 100).toFixed(2)}%</p>
            <p><strong>PnL:</strong> {trader.pnl.toFixed(2)} USDC</p>
            <p><strong>Win Rate:</strong> {(trader.winRate * 100).toFixed(2)}%</p>
            <p><strong>Max Drawdown:</strong> {(trader.maxDrawdown * 100).toFixed(2)}%</p>
            <p><strong>Followers:</strong> {trader.followValue.toFixed(0)} USDC</p>
          </div>
          
          <button 
            onClick={() => onCopy(trader.address)}
            disabled={loading || trader.copying}
            className={`copy-btn ${trader.copying ? 'active' : ''}`}
          >
            {trader.copying ? 'Copying' : loading ? 'Starting...' : 'Copy Trade'}
          </button>
        </div>
      ))}
    </div>
  </div>
);

// Copy Trades List Component
const CopyTradesList: React.FC<{
  trades: any[];
  onStop: (id: number) => void;
  loading: boolean;
}> = ({ trades, onStop, loading }) => (
  <div className="section">
    <h2>Your Copy Trades</h2>
    {trades.length === 0 ? (
      <p>No active copy trades</p>
    ) : (
      <div className="trades-list">
        {trades.map(trade => (
          <div key={trade.copyTradeId} className="trade-item">
            <div className="trade-info">
              <p><strong>Leader:</strong> {trade.leaderAccount.slice(0, 8)}...{trade.leaderAccount.slice(-6)}</p>
              <p><strong>Follower:</strong> {trade.followerAccount.slice(0, 8)}...{trade.followerAccount.slice(-6)}</p>
              <p><strong>Status:</strong> 
                <span className={`status ${trade.active ? 'active' : 'stopped'}`}>
                  {trade.active ? 'Active' : 'Stopped'}
                </span>
              </p>
              <p><strong>Created:</strong> {new Date(trade.createTime).toLocaleDateString()}</p>
            </div>
            
            {trade.active && (
              <button 
                onClick={() => onStop(trade.copyTradeId)}
                disabled={loading}
                className="stop-btn"
              >
                {loading ? 'Stopping...' : 'Stop'}
              </button>
            )}
          </div>
        ))}
      </div>
    )}
  </div>
);

export default CopyTradingDashboard;
```

## Trader Analytics Tool

Build a tool to analyze and compare trader performance.

```typescript theme={"system"}
import { SimpforFunSDK } from 'simpfor-fun-sdk';

interface TraderAnalytics {
  address: string;
  roi30d: number;
  roi90d: number;
  sharpeRatio: number;
  maxDrawdown: number;
  winRate: number;
  totalTrades: number;
  avgHoldTime: number;
  riskScore: number;
}

class TraderAnalyzer {
  private sdk: SimpforFunSDK;
  private cache = new Map<string, { data: any; timestamp: number }>();
  private readonly CACHE_TTL = 300000; // 5 minutes

  constructor() {
    this.sdk = new SimpforFunSDK();
  }

  async getTraderAnalytics(address: string): Promise<TraderAnalytics> {
    // Check cache first
    const cached = this.cache.get(address);
    if (cached && Date.now() - cached.timestamp < this.CACHE_TTL) {
      return this.calculateAnalytics(cached.data);
    }

    // Fetch fresh data
    const [snapshot30d, snapshot90d, overview] = await Promise.all([
      this.sdk.traderSnapshot(address, '30d'),
      this.sdk.traderSnapshot(address, '90d'),
      this.sdk.traderOverview(address)
    ]);

    const data = { snapshot30d, snapshot90d, overview };
    this.cache.set(address, { data, timestamp: Date.now() });

    return this.calculateAnalytics(data);
  }

  private calculateAnalytics(data: any): TraderAnalytics {
    const { snapshot30d, snapshot90d, overview } = data;
    
    // Calculate risk score (0-100, lower is better)
    const riskScore = this.calculateRiskScore(
      snapshot30d.trader.maxDrawdown,
      snapshot30d.trader.sharpeRatio,
      overview.traderOverview.averageLeverage
    );

    return {
      address: snapshot30d.trader.address,
      roi30d: snapshot30d.trader.roi,
      roi90d: snapshot90d.trader.roi,
      sharpeRatio: snapshot30d.trader.sharpeRatio,
      maxDrawdown: snapshot30d.trader.maxDrawdown,
      winRate: snapshot30d.trader.winRate,
      totalTrades: snapshot30d.trader.totalTrades || 0,
      avgHoldTime: this.calculateAvgHoldTime(snapshot30d.snapshot),
      riskScore
    };
  }

  private calculateRiskScore(maxDrawdown: number, sharpeRatio: number, avgLeverage: number): number {
    // Weighted risk score
    const drawdownScore = Math.min(maxDrawdown * 100, 100); // 0-100
    const sharpeScore = Math.max(0, 50 - (sharpeRatio * 10)); // 0-50
    const leverageScore = Math.min(avgLeverage * 10, 50); // 0-50
    
    return Math.round((drawdownScore * 0.5) + (sharpeScore * 0.3) + (leverageScore * 0.2));
  }

  private calculateAvgHoldTime(snapshots: any[]): number {
    // Simplified calculation - would need more detailed trade data for accuracy
    return snapshots.length > 0 ? snapshots.length * 24 : 0; // Hours
  }

  async compareTraders(addresses: string[]): Promise<TraderAnalytics[]> {
    const analytics = await Promise.all(
      addresses.map(addr => this.getTraderAnalytics(addr))
    );

    // Sort by risk-adjusted return (ROI / risk score)
    return analytics.sort((a, b) => {
      const scoreA = a.roi30d / (a.riskScore || 1);
      const scoreB = b.roi30d / (b.riskScore || 1);
      return scoreB - scoreA;
    });
  }

  async findBestTraders(criteria: {
    minROI?: number;
    maxRisk?: number;
    minWinRate?: number;
    maxDrawdown?: number;
  } = {}): Promise<TraderAnalytics[]> {
    const topTraders = await this.sdk.fetchTopTraders();
    const analyses = await Promise.all(
      topTraders.slice(0, 20).map(trader => this.getTraderAnalytics(trader.address))
    );

    return analyses.filter(trader => {
      if (criteria.minROI && trader.roi30d < criteria.minROI) return false;
      if (criteria.maxRisk && trader.riskScore > criteria.maxRisk) return false;
      if (criteria.minWinRate && trader.winRate < criteria.minWinRate) return false;
      if (criteria.maxDrawdown && trader.maxDrawdown > criteria.maxDrawdown) return false;
      return true;
    });
  }

  generateReport(analytics: TraderAnalytics[]): string {
    let report = "TRADER ANALYSIS REPORT\n";
    report += "=".repeat(50) + "\n\n";

    analytics.forEach((trader, index) => {
      report += `${index + 1}. ${trader.address.slice(0, 8)}...${trader.address.slice(-6)}\n`;
      report += `   30-day ROI: ${(trader.roi30d * 100).toFixed(2)}%\n`;
      report += `   90-day ROI: ${(trader.roi90d * 100).toFixed(2)}%\n`;
      report += `   Sharpe Ratio: ${trader.sharpeRatio.toFixed(2)}\n`;
      report += `   Max Drawdown: ${(trader.maxDrawdown * 100).toFixed(2)}%\n`;
      report += `   Win Rate: ${(trader.winRate * 100).toFixed(2)}%\n`;
      report += `   Risk Score: ${trader.riskScore}/100\n`;
      report += `   Avg Hold Time: ${trader.avgHoldTime.toFixed(1)} hours\n\n`;
    });

    return report;
  }
}

// Usage Example
async function analyzeTraders() {
  const analyzer = new TraderAnalyzer();

  // Find best conservative traders
  const conservativeTraders = await analyzer.findBestTraders({
    minROI: 0.15,      // 15% minimum
    maxRisk: 30,       // Low risk score
    minWinRate: 0.65,  // 65% win rate
    maxDrawdown: 0.20  // 20% max drawdown
  });

  console.log(`Found ${conservativeTraders.length} conservative traders`);
  console.log(analyzer.generateReport(conservativeTraders.slice(0, 5)));

  // Compare specific traders
  const specificTraders = [
    'trader-address-1',
    'trader-address-2', 
    'trader-address-3'
  ];

  const comparison = await analyzer.compareTraders(specificTraders);
  console.log('\nCOMPARISON RESULTS:');
  console.log(analyzer.generateReport(comparison));
}

analyzeTraders().catch(console.error);
```

## Automated Portfolio Rebalancer

Automatically rebalance your copy trading portfolio based on performance.

```typescript theme={"system"}
import { SimpforFunSDK } from 'simpfor-fun-sdk';

interface PortfolioConfig {
  maxTraders: number;
  rebalanceInterval: number; // milliseconds
  performanceWindow: number; // days
  stopLossThreshold: number; // percentage
  minAllocation: number; // USDC
  maxAllocation: number; // USDC
}

class PortfolioRebalancer {
  private sdk: SimpforFunSDK;
  private userId: number;
  private config: PortfolioConfig;
  private rebalanceTimer?: NodeJS.Timeout;

  constructor(config: PortfolioConfig) {
    this.sdk = new SimpforFunSDK();
    this.config = config;
  }

  async initialize(userId: number) {
    this.userId = userId;
    console.log('Portfolio rebalancer initialized');
  }

  async startAutoRebalancing() {
    console.log('Starting automatic rebalancing...');
    
    this.rebalanceTimer = setInterval(async () => {
      try {
        await this.rebalancePortfolio();
      } catch (error) {
        console.error('Rebalancing failed:', error);
      }
    }, this.config.rebalanceInterval);

    // Run initial rebalance
    await this.rebalancePortfolio();
  }

  async stopAutoRebalancing() {
    if (this.rebalanceTimer) {
      clearInterval(this.rebalanceTimer);
      this.rebalanceTimer = undefined;
      console.log('Auto-rebalancing stopped');
    }
  }

  async rebalancePortfolio() {
    console.log('Starting portfolio rebalance...');

    // Get current positions
    const currentTrades = await this.sdk.listCopyTrades(this.userId);
    const activeTrades = currentTrades.data.infos.filter(trade => trade.active);

    // Analyze performance of current traders
    const traderPerformance = await Promise.all(
      activeTrades.map(async (trade) => {
        try {
          const snapshot = await this.sdk.traderSnapshot(
            trade.leaderAccount, 
            `${this.config.performanceWindow}d` as any
          );
          
          const pnl = await this.sdk.getCopyTradeTotalPnl(
            this.userId, 
            trade.followerAccount
          );

          return {
            copyTradeId: trade.copyTradeId,
            leaderAccount: trade.leaderAccount,
            followerAccount: trade.followerAccount,
            performance: snapshot.trader.roi,
            currentPnl: pnl.data.pnl,
            sharpeRatio: snapshot.trader.sharpeRatio,
            maxDrawdown: snapshot.trader.maxDrawdown,
            winRate: snapshot.trader.winRate
          };
        } catch (error) {
          console.error(`Error analyzing ${trade.leaderAccount}:`, error);
          return null;
        }
      })
    );

    const validPerformance = traderPerformance.filter(p => p !== null);

    // Remove underperforming traders
    await this.removeUnderperformers(validPerformance);

    // Add new high-performing traders if needed
    await this.addNewTraders(validPerformance.length);

    console.log('Portfolio rebalance complete');
  }

  private async removeUnderperformers(performance: any[]) {
    for (const trader of performance) {
      const shouldRemove = 
        trader.performance < -this.config.stopLossThreshold / 100 ||
        trader.currentPnl < -this.config.stopLossThreshold * 10 || // Absolute loss threshold
        trader.maxDrawdown > 0.30; // 30% max drawdown

      if (shouldRemove) {
        console.log(`Removing underperformer: ${trader.leaderAccount}`);
        try {
          await this.sdk.stopCopyTrade(
            this.userId, 
            trader.copyTradeId, 
            true // Close positions
          );
        } catch (error) {
          console.error(`Failed to remove ${trader.leaderAccount}:`, error);
        }
      }
    }
  }

  private async addNewTraders(currentCount: number) {
    const spotsAvailable = this.config.maxTraders - currentCount;
    if (spotsAvailable <= 0) return;

    // Find new high-performing traders
    const topTraders = await this.sdk.fetchTopTraders();
    const currentTraders = new Set(
      (await this.sdk.listCopyTrades(this.userId)).data.infos
        .filter(t => t.active)
        .map(t => t.leaderAccount)
    );

    // Filter for traders we're not already copying
    const availableTraders = topTraders.filter(trader => 
      !currentTraders.has(trader.address) &&
      trader.roi > 0.10 && // 10% minimum ROI
      trader.winRate > 0.60 && // 60% win rate
      trader.maxDrawdown < 0.25 && // 25% max drawdown
      trader.followValue > 500 // Some following
    );

    // Add top performers
    const tradersToAdd = availableTraders.slice(0, spotsAvailable);

    for (const trader of tradersToAdd) {
      try {
        console.log(`Adding new trader: ${trader.address}`);
        const copyTrade = await this.sdk.createCopyTrade(
          this.userId,
          trader.address,
          'your-wallet-address' // Replace with actual wallet
        );
        
        await this.sdk.runCopyTrade(this.userId, copyTrade.data.info.copyTradeId);
      } catch (error) {
        console.error(`Failed to add ${trader.address}:`, error);
      }
    }
  }

  async getPortfolioStatus() {
    const trades = await this.sdk.listCopyTrades(this.userId);
    const activeTrades = trades.data.infos.filter(t => t.active);

    const status = {
      totalTrades: activeTrades.length,
      maxTrades: this.config.maxTraders,
      utilization: (activeTrades.length / this.config.maxTraders * 100).toFixed(1),
      trades: [] as any[]
    };

    for (const trade of activeTrades) {
      try {
        const pnl = await this.sdk.getCopyTradeTotalPnl(this.userId, trade.followerAccount);
        const snapshot = await this.sdk.traderSnapshot(trade.leaderAccount, '30d');
        
        status.trades.push({
          leader: trade.leaderAccount.slice(0, 8) + '...',
          pnl: pnl.data.pnl.toFixed(2),
          roi: (snapshot.trader.roi * 100).toFixed(2),
          active: trade.active
        });
      } catch (error) {
        console.error(`Error getting status for ${trade.leaderAccount}:`, error);
      }
    }

    return status;
  }
}

// Usage Example
async function runPortfolioManager() {
  const config: PortfolioConfig = {
    maxTraders: 5,
    rebalanceInterval: 3600000, // 1 hour
    performanceWindow: 7, // 7 days
    stopLossThreshold: 15, // 15%
    minAllocation: 100, // 100 USDC minimum
    maxAllocation: 1000 // 1000 USDC maximum
  };

  const rebalancer = new PortfolioRebalancer(config);
  await rebalancer.initialize(123); // Your user ID

  // Start automatic rebalancing
  await rebalancer.startAutoRebalancing();

  // Check status every 10 minutes
  setInterval(async () => {
    const status = await rebalancer.getPortfolioStatus();
    console.log('Portfolio Status:', status);
  }, 600000);

  // Stop after 24 hours (for demo)
  setTimeout(async () => {
    await rebalancer.stopAutoRebalancing();
    console.log('Demo ended');
  }, 86400000);
}

runPortfolioManager().catch(console.error);
```

## Error Handling & Retry Logic

Production-ready error handling and retry mechanisms.

```typescript theme={"system"}
import { SimpforFunSDK } from 'simpfor-fun-sdk';

interface RetryOptions {
  maxRetries: number;
  baseDelay: number;
  maxDelay: number;
  backoffFactor: number;
}

class RobustSDK {
  private sdk: SimpforFunSDK;
  private defaultRetryOptions: RetryOptions = {
    maxRetries: 3,
    baseDelay: 1000,
    maxDelay: 10000,
    backoffFactor: 2
  };

  constructor() {
    this.sdk = new SimpforFunSDK();
  }

  // Retry wrapper for any SDK method
  async withRetry<T>(
    operation: () => Promise<T>,
    options: Partial<RetryOptions> = {}
  ): Promise<T> {
    const opts = { ...this.defaultRetryOptions, ...options };
    let lastError: any;

    for (let attempt = 0; attempt <= opts.maxRetries; attempt++) {
      try {
        return await operation();
      } catch (error: any) {
        lastError = error;

        // Don't retry on client errors (4xx)
        if (error.code >= 400 && error.code < 500 && error.code !== 429) {
          throw error;
        }

        // Don't retry on last attempt
        if (attempt === opts.maxRetries) {
          break;
        }

        // Calculate delay with exponential backoff
        const delay = Math.min(
          opts.baseDelay * Math.pow(opts.backoffFactor, attempt),
          opts.maxDelay
        );

        console.log(`Attempt ${attempt + 1} failed, retrying in ${delay}ms...`);
        await this.sleep(delay);
      }
    }

    throw lastError;
  }

  // Authentication with retry and refresh
  async authenticateWithRetry(email: string, otp: string) {
    return this.withRetry(async () => {
      return await this.sdk.verifyOtp(email, otp);
    });
  }

  // Fetch traders with caching and retry
  private traderCache: { data: any[]; timestamp: number } | null = null;
  private readonly CACHE_TTL = 300000; // 5 minutes

  async fetchTradersRobust(): Promise<any[]> {
    // Return cached data if fresh
    if (this.traderCache && Date.now() - this.traderCache.timestamp < this.CACHE_TTL) {
      return this.traderCache.data;
    }

    const traders = await this.withRetry(async () => {
      return await this.sdk.fetchTopTraders();
    });

    // Update cache
    this.traderCache = {
      data: traders,
      timestamp: Date.now()
    };

    return traders;
  }

  // Copy trade with comprehensive error handling
  async createCopyTradeRobust(
    userId: number,
    leaderAddress: string,
    followerAddress: string
  ) {
    try {
      // Validate inputs
      if (!this.isValidAddress(leaderAddress)) {
        throw new Error('Invalid leader address');
      }
      if (!this.isValidAddress(followerAddress)) {
        throw new Error('Invalid follower address');
      }

      // Check if already copying this trader
      const existingTrades = await this.withRetry(async () => {
        return await this.sdk.listCopyTrades(userId);
      });

      const alreadyCopying = existingTrades.data.infos.some(
        trade => trade.leaderAccount === leaderAddress && trade.active
      );

      if (alreadyCopying) {
        throw new Error('Already copying this trader');
      }

      // Create copy trade with retry
      const copyTrade = await this.withRetry(async () => {
        return await this.sdk.createCopyTrade(userId, leaderAddress, followerAddress);
      });

      // Start copy trading with retry
      await this.withRetry(async () => {
        return await this.sdk.runCopyTrade(userId, copyTrade.data.info.copyTradeId);
      });

      return copyTrade;

    } catch (error: any) {
      console.error('Copy trade creation failed:', error);
      
      // Provide user-friendly error messages
      switch (error.code) {
        case 400:
          throw new Error('Invalid request. Please check your wallet addresses and try again.');
        case 401:
          throw new Error('Authentication expired. Please log in again.');
        case 409:
          throw new Error('Copy trade relationship already exists.');
        case 429:
          throw new Error('Too many requests. Please wait a moment and try again.');
        case 500:
          throw new Error('Server error. Please try again later.');
        default:
          throw new Error(`Copy trade failed: ${error.message || 'Unknown error'}`);
      }
    }
  }

  // Batch operations with parallel processing and error isolation
  async processBatchOperations<T, R>(
    items: T[],
    operation: (item: T) => Promise<R>,
    maxConcurrency: number = 5
  ): Promise<Array<{ item: T; result?: R; error?: Error }>> {
    const results: Array<{ item: T; result?: R; error?: Error }> = [];
    
    // Process items in batches to control concurrency
    for (let i = 0; i < items.length; i += maxConcurrency) {
      const batch = items.slice(i, i + maxConcurrency);
      
      const batchPromises = batch.map(async (item) => {
        try {
          const result = await this.withRetry(() => operation(item));
          return { item, result };
        } catch (error) {
          return { item, error: error as Error };
        }
      });

      const batchResults = await Promise.all(batchPromises);
      results.push(...batchResults);
    }

    return results;
  }

  // Health check and status monitoring
  async healthCheck(): Promise<{
    status: 'healthy' | 'degraded' | 'unhealthy';
    checks: Record<string, boolean>;
    responseTime: number;
  }> {
    const startTime = Date.now();
    const checks: Record<string, boolean> = {};

    try {
      // Test basic API connectivity
      checks.api = await this.testApiCall();
      
      // Test authentication (if we have credentials)
      checks.auth = await this.testAuthentication();
      
      // Test trader data fetching
      checks.data = await this.testDataFetching();

    } catch (error) {
      console.error('Health check failed:', error);
    }

    const responseTime = Date.now() - startTime;
    const healthyChecks = Object.values(checks).filter(Boolean).length;
    const totalChecks = Object.keys(checks).length;

    let status: 'healthy' | 'degraded' | 'unhealthy';
    if (healthyChecks === totalChecks) {
      status = 'healthy';
    } else if (healthyChecks > 0) {
      status = 'degraded';
    } else {
      status = 'unhealthy';
    }

    return { status, checks, responseTime };
  }

  private async testApiCall(): Promise<boolean> {
    try {
      await this.sdk.fetchTopTraders();
      return true;
    } catch {
      return false;
    }
  }

  private async testAuthentication(): Promise<boolean> {
    // This would test if current auth is valid
    // Implementation depends on how you store auth state
    return true;
  }

  private async testDataFetching(): Promise<boolean> {
    try {
      const traders = await this.sdk.fetchTopTraders();
      return traders.length > 0;
    } catch {
      return false;
    }
  }

  private isValidAddress(address: string): boolean {
    // Basic address validation
    return address && address.length > 20 && address.startsWith('0x');
  }

  private sleep(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

// Usage Example
async function demonstrateRobustSDK() {
  const robustSDK = new RobustSDK();

  // Health check
  const health = await robustSDK.healthCheck();
  console.log('System Health:', health);

  if (health.status === 'unhealthy') {
    console.error('System is unhealthy, aborting operations');
    return;
  }

  // Robust trader fetching
  try {
    const traders = await robustSDK.fetchTradersRobust();
    console.log(`Fetched ${traders.length} traders`);
  } catch (error) {
    console.error('Failed to fetch traders:', error);
  }

  // Batch processing multiple copy trades
  const tradersToFollow = ['trader1', 'trader2', 'trader3'];
  const results = await robustSDK.processBatchOperations(
    tradersToFollow,
    async (traderAddress) => {
      return await robustSDK.createCopyTradeRobust(
        123, // userId
        traderAddress,
        'your-wallet-address'
      );
    }
  );

  // Process results
  results.forEach(({ item, result, error }) => {
    if (error) {
      console.error(`Failed to copy ${item}:`, error.message);
    } else {
      console.log(`Successfully started copying ${item}`);
    }
  });
}

demonstrateRobustSDK().catch(console.error);
```

***

## Next Steps

These examples show real-world implementations using the Simpfor.fun SDK. Pick the example that matches your use case and adapt it to your needs.

**For more help:**

* [SDK Reference](/simpforfun/sdk-reference) - Complete API documentation
* [Getting Started](/simpforfun/getting-started) - Platform basics

**Ready to build?** Start with the copy trading bot example - it's the simplest way to get familiar with the SDK.
