Skip to main content
GET
https://api-mainnet.onzks.com
/
v1
/
trading
/
leaderboard
Get Trading Leaderboard
curl --request GET \
  --url https://api-mainnet.onzks.com/v1/trading/leaderboard \
  --header 'Authorization: Bearer <token>'
{
  "success": true,
  "leaderboard": [
    {
      "rank": 123,
      "address": "<string>",
      "zksId": "<string>",
      "score": 123,
      "value": "<string>",
      "change": {
        "position": 123,
        "direction": "<string>",
        "percentage": 123
      },
      "stats": {
        "totalVolume": "<string>",
        "totalTrades": 123,
        "winRate": 123,
        "totalPnL": "<string>",
        "averageTrade": "<string>",
        "uniqueProtocols": 123,
        "uniqueAssets": 123,
        "riskScore": 123,
        "consistency": 123
      },
      "badges": [
        {
          "id": "<string>",
          "name": "<string>",
          "icon": "<string>",
          "rarity": "<string>"
        }
      ]
    }
  ],
  "pagination": {
    "total": 123,
    "limit": 123,
    "offset": 123,
    "hasMore": true
  },
  "metadata": {
    "metric": "<string>",
    "timeframe": "<string>",
    "lastUpdated": "<string>",
    "totalTraders": 123,
    "averageScore": 123,
    "topScore": 123
  },
  "timestamp": "<string>"
}

Overview

Retrieve ranked leaderboards of top traders based on different performance metrics. This endpoint provides competitive rankings perfect for building leaderboards, competitions, and showcasing top performers.
Use this endpoint to display top traders, create competitions, and motivate users to improve their trading performance through gamification.

Parameters

metric
string
Ranking metric
  • volume - Total trading volume (default)
  • profit - Total profit/loss
  • winRate - Win rate percentage
  • trades - Number of trades
  • efficiency - Profit per volume ratio
  • consistency - Consistency score
  • riskAdjusted - Risk-adjusted returns
timeframe
string
Time period for rankings
  • 7d - Last 7 days
  • 30d - Last 30 days (default)
  • 90d - Last 90 days
  • 1y - Last year
  • all - All time
chainId
number
Filter by specific blockchain
  • 1 - Ethereum mainnet
  • 137 - Polygon
  • 56 - BSC
  • 42161 - Arbitrum
  • 10 - Optimism
  • 250 - Fantom
  • 43114 - Avalanche
protocol
string
Filter by specific protocol
  • uniswap - Uniswap
  • sushiswap - SushiSwap
  • 1inch - 1inch
  • curve - Curve
  • balancer - Balancer
  • pancakeswap - PancakeSwap
category
string
Trader category
  • all - All traders (default)
  • whale - High volume traders
  • retail - Retail traders
  • professional - Professional traders
  • institutional - Institutional traders
limit
number
Number of traders to return (default: 100, max: 1000)
offset
number
Number of traders to skip for pagination (default: 0)
includeStats
boolean
Include detailed statistics for each trader (default: true)
includeRanking
boolean
Include ranking information (default: true)

Response

success
boolean
Indicates if the request was successful
leaderboard
array
Array of ranked traders
pagination
object
Pagination information
metadata
object
Leaderboard metadata
timestamp
string
ISO 8601 timestamp of the response

Examples

curl "https://api.onzks.com/v1/trading/leaderboard?metric=volume" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "success": true,
  "leaderboard": [
    {
      "rank": 1,
      "address": "0x1234567890abcdef...",
      "zksId": "whale.trader",
      "score": 1250000.50,
      "value": "$1,250,000.50",
      "change": {
        "position": 2,
        "direction": "up",
        "percentage": 15.5
      },
      "stats": {
        "totalVolume": "1250000.50",
        "totalTrades": 342,
        "winRate": 68.5,
        "totalPnL": "125000.75",
        "averageTrade": "3654.97",
        "uniqueProtocols": 15,
        "uniqueAssets": 28,
        "riskScore": 42.3,
        "consistency": 78.5
      },
      "badges": [
        {
          "id": "volume-king",
          "name": "Volume King",
          "icon": "https://cdn.onzks.com/badges/volume-king.png",
          "rarity": "legendary"
        },
        {
          "id": "defi-pioneer",
          "name": "DeFi Pioneer",
          "icon": "https://cdn.onzks.com/badges/defi-pioneer.png",
          "rarity": "epic"
        }
      ]
    },
    {
      "rank": 2,
      "address": "0xabcdef1234567890...",
      "zksId": "profit.master",
      "score": 98.5,
      "value": "98.5%",
      "change": {
        "position": -1,
        "direction": "down",
        "percentage": -2.3
      },
      "stats": {
        "totalVolume": "850000.25",
        "totalTrades": 156,
        "winRate": 98.5,
        "totalPnL": "425000.12",
        "averageTrade": "5448.72",
        "uniqueProtocols": 8,
        "uniqueAssets": 15,
        "riskScore": 25.7,
        "consistency": 95.2
      },
      "badges": [
        {
          "id": "win-rate-champion",
          "name": "Win Rate Champion",
          "icon": "https://cdn.onzks.com/badges/win-rate-champion.png",
          "rarity": "legendary"
        }
      ]
    },
    {
      "rank": 3,
      "address": "0x9876543210fedcba...",
      "zksId": "efficiency.expert",
      "score": 2.1,
      "value": "2.1x",
      "change": {
        "position": 0,
        "direction": "same",
        "percentage": 0.0
      },
      "stats": {
        "totalVolume": "650000.00",
        "totalTrades": 89,
        "winRate": 75.2,
        "totalPnL": "136500.00",
        "averageTrade": "7303.37",
        "uniqueProtocols": 12,
        "uniqueAssets": 22,
        "riskScore": 35.8,
        "consistency": 82.1
      },
      "badges": [
        {
          "id": "efficiency-master",
          "name": "Efficiency Master",
          "icon": "https://cdn.onzks.com/badges/efficiency-master.png",
          "rarity": "epic"
        }
      ]
    }
  ],
  "pagination": {
    "total": 12547,
    "limit": 100,
    "offset": 0,
    "hasMore": true
  },
  "metadata": {
    "metric": "volume",
    "timeframe": "30d",
    "lastUpdated": "2024-01-20T15:45:00Z",
    "totalTraders": 12547,
    "averageScore": 125000.50,
    "topScore": 1250000.50
  },
  "timestamp": "2024-01-20T15:45:00Z"
}

Use Cases

1. Trading Competition Dashboard

Create a competitive trading dashboard:
function createTradingCompetition(leaderboard) {
  const competition = {
    topTraders: leaderboard.leaderboard.slice(0, 10),
    categories: {
      volume: leaderboard.leaderboard.filter(t => t.stats.totalVolume > 1000000),
      profit: leaderboard.leaderboard.filter(t => parseFloat(t.stats.totalPnL) > 100000),
      consistency: leaderboard.leaderboard.filter(t => t.stats.consistency > 80)
    },
    badges: extractBadges(leaderboard.leaderboard),
    insights: generateInsights(leaderboard)
  };
  
  return competition;
}

function extractBadges(traders) {
  const badgeCounts = {};
  
  traders.forEach(trader => {
    trader.badges.forEach(badge => {
      badgeCounts[badge.id] = (badgeCounts[badge.id] || 0) + 1;
    });
  });
  
  return Object.entries(badgeCounts)
    .sort(([,a], [,b]) => b - a)
    .slice(0, 10);
}

2. Trader Profile Analysis

Analyze individual trader performance:
function analyzeTraderProfile(trader) {
  const analysis = {
    strengths: [],
    weaknesses: [],
    recommendations: [],
    riskLevel: assessRiskLevel(trader.stats.riskScore),
    performance: assessPerformance(trader.stats)
  };
  
  // Analyze strengths
  if (trader.stats.winRate > 80) {
    analysis.strengths.push('High win rate');
  }
  
  if (trader.stats.consistency > 85) {
    analysis.strengths.push('Consistent performance');
  }
  
  if (trader.stats.uniqueProtocols > 10) {
    analysis.strengths.push('Diversified protocol usage');
  }
  
  // Analyze weaknesses
  if (trader.stats.riskScore > 70) {
    analysis.weaknesses.push('High risk trading');
  }
  
  if (trader.stats.winRate < 60) {
    analysis.weaknesses.push('Low win rate');
  }
  
  // Generate recommendations
  if (trader.stats.riskScore > 60) {
    analysis.recommendations.push('Consider reducing position sizes');
  }
  
  if (trader.stats.uniqueProtocols < 5) {
    analysis.recommendations.push('Explore more protocols for diversification');
  }
  
  return analysis;
}
Analyze leaderboard trends over time:
async function analyzeLeaderboardTrends(metric, timeframe) {
  const [current, previous] = await Promise.all([
    getTradingLeaderboard({ metric, timeframe }),
    getTradingLeaderboard({ metric, timeframe: getPreviousTimeframe(timeframe) })
  ]);
  
  const trends = {
    topMovers: findTopMovers(current.leaderboard, previous.leaderboard),
    newEntries: findNewEntries(current.leaderboard, previous.leaderboard),
    droppedOut: findDroppedOut(current.leaderboard, previous.leaderboard),
    averageChange: calculateAverageChange(current.leaderboard, previous.leaderboard)
  };
  
  return trends;
}

function findTopMovers(current, previous) {
  const previousMap = new Map(previous.map(t => [t.address, t.rank]));
  
  return current
    .filter(trader => {
      const previousRank = previousMap.get(trader.address);
      return previousRank && trader.rank < previousRank;
    })
    .sort((a, b) => (previousMap.get(a.address) - a.rank) - (previousMap.get(b.address) - b.rank))
    .slice(0, 10);
}

4. Category Analysis

Analyze different trader categories:
function analyzeTraderCategories(leaderboard) {
  const categories = {
    whale: leaderboard.leaderboard.filter(t => parseFloat(t.stats.totalVolume) > 1000000),
    retail: leaderboard.leaderboard.filter(t => parseFloat(t.stats.totalVolume) < 100000),
    professional: leaderboard.leaderboard.filter(t => t.stats.consistency > 80),
    institutional: leaderboard.leaderboard.filter(t => t.stats.uniqueProtocols > 15)
  };
  
  const analysis = {};
  
  Object.entries(categories).forEach(([category, traders]) => {
    analysis[category] = {
      count: traders.length,
      averageVolume: calculateAverage(traders, 'totalVolume'),
      averageWinRate: calculateAverage(traders, 'winRate'),
      averageRisk: calculateAverage(traders, 'riskScore'),
      topPerformer: traders[0]
    };
  });
  
  return analysis;
}

5. Badge System

Implement a badge system for achievements:
function assignBadges(trader) {
  const badges = [];
  
  // Volume badges
  if (parseFloat(trader.stats.totalVolume) > 1000000) {
    badges.push({ id: 'volume-king', name: 'Volume King', rarity: 'legendary' });
  } else if (parseFloat(trader.stats.totalVolume) > 500000) {
    badges.push({ id: 'volume-master', name: 'Volume Master', rarity: 'epic' });
  }
  
  // Win rate badges
  if (trader.stats.winRate > 95) {
    badges.push({ id: 'win-rate-champion', name: 'Win Rate Champion', rarity: 'legendary' });
  } else if (trader.stats.winRate > 85) {
    badges.push({ id: 'win-rate-expert', name: 'Win Rate Expert', rarity: 'epic' });
  }
  
  // Consistency badges
  if (trader.stats.consistency > 90) {
    badges.push({ id: 'consistency-master', name: 'Consistency Master', rarity: 'legendary' });
  } else if (trader.stats.consistency > 80) {
    badges.push({ id: 'consistency-expert', name: 'Consistency Expert', rarity: 'epic' });
  }
  
  // Protocol diversity badges
  if (trader.stats.uniqueProtocols > 20) {
    badges.push({ id: 'protocol-explorer', name: 'Protocol Explorer', rarity: 'legendary' });
  } else if (trader.stats.uniqueProtocols > 10) {
    badges.push({ id: 'protocol-diversifier', name: 'Protocol Diversifier', rarity: 'epic' });
  }
  
  return badges;
}

Best Practices

1. Caching

Cache leaderboard data for performance:
let leaderboardCache = new Map();
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes

async function getCachedLeaderboard(options = {}) {
  const cacheKey = JSON.stringify(options);
  const cached = leaderboardCache.get(cacheKey);
  
  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return cached.data;
  }
  
  const data = await getTradingLeaderboard(options);
  leaderboardCache.set(cacheKey, {
    data,
    timestamp: Date.now()
  });
  
  return data;
}

2. Real-time Updates

Subscribe to leaderboard updates:
function subscribeToLeaderboardUpdates(metric, callback) {
  const ws = new WebSocket(`wss://api.onzks.com/v1/trading/leaderboard/${metric}/subscribe`);
  
  ws.onmessage = (event) => {
    const update = JSON.parse(event.data);
    callback(update);
  };
  
  return () => ws.close();
}

3. Pagination

Handle large leaderboards with pagination:
async function getAllLeaderboard(metric, options = {}) {
  const allTraders = [];
  let offset = 0;
  const limit = 100;
  
  while (true) {
    const data = await getTradingLeaderboard({
      ...options,
      metric,
      limit,
      offset
    });
    
    allTraders.push(...data.leaderboard);
    
    if (!data.pagination.hasMore) {
      break;
    }
    
    offset += limit;
  }
  
  return allTraders;
}

4. Performance Optimization

Optimize for large datasets:
function optimizeLeaderboardDisplay(leaderboard, viewport = 10) {
  return {
    visible: leaderboard.leaderboard.slice(0, viewport),
    total: leaderboard.pagination.total,
    hasMore: leaderboard.pagination.hasMore,
    loadMore: () => loadMoreTraders(viewport)
  };
}

Troubleshooting

”No traders found”

Cause: No traders match the criteria or invalid filters. Solution:
  • Remove restrictive filters
  • Check if the timeframe has trading activity
  • Verify metric and category values

”Invalid metric”

Cause: Unsupported metric value. Solution:
  • Use supported metrics: volume, profit, winRate, trades, efficiency, consistency, riskAdjusted
  • Check for typos

”Invalid category”

Cause: Unsupported category value. Solution:
  • Use supported categories: all, whale, retail, professional, institutional
  • Check for typos

Rate Limits

Leaderboard requests are subject to rate limits:
  • Free tier: 60 requests per minute
  • Starter tier: 300 requests per minute
  • Professional tier: 1,000 requests per minute
  • Enterprise tier: Custom limits
Implement caching to reduce API calls.