Skip to main content
You spot a honeypot token on trending. The chart looks perfect—steady climb, healthy volume. Your users buy in. When they try to sell, nothing happens. The contract blocks all sells except for the developer’s wallet. $3.2 million locked forever. This guide shows you how to screen tokens before your users get burned.

Why Token Screening Matters

Honeypot Detection

Block tokens that won’t let users sell

Tax Analysis

Expose hidden buy/sell taxes before users swap

Rug Risk Assessment

Identify concentrated holdings and suspicious patterns
Why DEX developers choose Webacy:
  • Contract security analysis — Detect honeypots, malicious functions, and rug mechanics
  • Hidden tax detection — Find buy/sell taxes hidden in contract code
  • Holder concentration — Identify tokens where insiders hold most supply
  • Liquidity analysis — Assess pool depth and rug pull indicators
  • Trading Lite API — Sub-second screening for real-time user protection
  • Multi-chain support — ETH, Solana, Base, Arbitrum, BSC, and more

Prerequisites

Before implementing token screening, ensure you have:
  • A Webacy API key (sign up here)
  • Basic familiarity with REST APIs or the Webacy SDK
  • Your swap interface’s token selection and pre-swap flows identified

Token Listing Due Diligence

Screen tokens before they appear on your platform.

Contract Security Analysis

Get a comprehensive security analysis of any token contract.
curl -X GET "https://api.webacy.com/contracts/0xTokenAddress...?chain=eth" \
  -H "x-api-key: YOUR_API_KEY"
Key fields to check:
FieldDescriptionRed Flag
isHoneypotContract blocks sellsBlock immediately
overallRisk0-100 risk score> 70 requires review
vulnerabilities[]Security issues foundAny critical severity
hasProxyContractContract is upgradeableHidden risk

Hidden Tax Detection

Many scam tokens hide excessive taxes that steal from users on every transaction.
The Tax Trap: A token advertises “5% tax for marketing.” The contract actually takes 90% on sells. Users buy in at market price and can only exit at 10 cents on the dollar.
curl -X GET "https://api.webacy.com/contracts/0xTokenAddress.../tax?chain=eth" \
  -H "x-api-key: YOUR_API_KEY"
Tax warning thresholds:
Tax LevelRecommendation
0-5%Normal range
5-10%Show warning to users
10-25%Strong warning + require confirmation
> 25%Block or hide token

Holder Concentration Analysis

Identify tokens where insiders control most of the supply.
curl -X GET "https://api.webacy.com/holder-analysis/TokenMintAddress...?chain=sol" \
  -H "x-api-key: YOUR_API_KEY"
Holder red flags:
MetricRed Flag ThresholdWhat It Means
Top 10 %> 80%Insiders can dump
Sniper count> 10Coordinated buying at launch
Bundler count> 3Multiple wallets acting as one
Dev wallet %> 20%Developer can rug

Real-Time User Warnings

Screen tokens in real-time when users try to swap.

Pre-Swap Screening

Check tokens before users execute swaps.
curl -X GET "https://api.webacy.com/contracts/0xTokenAddress...?chain=eth" \
  -H "x-api-key: YOUR_API_KEY"

Trading Lite for Speed

For high-volume DEXes, use Trading Lite for sub-second token screening.
Trading Lite is currently available for Solana only. Use the standard contract analysis endpoints for EVM chains.
curl -X GET "https://api.webacy.com/trading-lite/PumpTokenAddress..." \
  -H "x-api-key: YOUR_API_KEY"

Liquidity Analysis

Check if there’s enough liquidity to actually execute trades.

Pool Data

curl -X GET "https://api.webacy.com/tokens/0xTokenAddress.../pools?chain=eth" \
  -H "x-api-key: YOUR_API_KEY"
Liquidity warning thresholds:
LiquidityRisk LevelUser Guidance
> $100kLowNormal trading
10k10k-100kMediumWarn about slippage
1k1k-10kHighStrong slippage warning
< $1kCriticalMay be rug pull or dead token

Rug Pull Indicators

Combine multiple signals to detect potential rug pulls.
interface RugPullRisk {
  score: number; // 0-100
  indicators: string[];
  recommendation: 'safe' | 'caution' | 'avoid';
}

async function assessRugPullRisk(
  tokenAddress: string,
  chain: Chain
): Promise<RugPullRisk> {
  const indicators: string[] = [];
  let score = 0;

  // Get all data
  const [contract, tax, pools, holders] = await Promise.all([
    client.contracts.analyze(tokenAddress, { chain }),
    client.contracts.getTax(tokenAddress, { chain }),
    tradingClient.tokens.getPools(tokenAddress, { chain }),
    tradingClient.holderAnalysis.get(tokenAddress, { chain }),
  ]);

  // Check contract risks
  if (contract.isHoneypot) {
    indicators.push('Honeypot detected');
    score += 50;
  }

  if (contract.hasProxyContract) {
    indicators.push('Upgradeable contract');
    score += 15;
  }

  // Check taxes
  if (tax.sellTax > 25) {
    indicators.push(`Extreme sell tax: ${tax.sellTax}%`);
    score += 30;
  } else if (tax.sellTax > 10) {
    indicators.push(`High sell tax: ${tax.sellTax}%`);
    score += 15;
  }

  // Check liquidity
  const totalLiquidity = pools.pools.reduce((sum, p) => sum + p.liquidity, 0);
  if (totalLiquidity < 10000) {
    indicators.push(`Low liquidity: $${totalLiquidity.toLocaleString()}`);
    score += 20;
  }

  // Check holder concentration
  if (holders.top10Percentage > 80) {
    indicators.push(`High concentration: Top 10 hold ${holders.top10Percentage}%`);
    score += 25;
  }

  if (holders.sniperCount > 10) {
    indicators.push(`${holders.sniperCount} snipers at launch`);
    score += 10;
  }

  // Determine recommendation
  let recommendation: 'safe' | 'caution' | 'avoid' = 'safe';
  if (score >= 50) {
    recommendation = 'avoid';
  } else if (score >= 25) {
    recommendation = 'caution';
  }

  return {
    score: Math.min(score, 100),
    indicators,
    recommendation,
  };
}

Complete Integration Workflow

Token Listing Flow

Pre-Swap User Warning Flow

Full TypeScript Implementation

import { ThreatClient, TradingClient, Chain } from '@webacy-xyz/sdk';

const threatClient = new ThreatClient({
  apiKey: process.env.WEBACY_API_KEY,
});

const tradingClient = new TradingClient({
  apiKey: process.env.WEBACY_API_KEY,
});

interface TokenScreeningResult {
  allowed: boolean;
  riskScore: number;
  warnings: Warning[];
  taxes: { buy: number; sell: number };
  liquidity: number;
  holderConcentration: number;
  recommendation: 'safe' | 'caution' | 'avoid' | 'block';
}

interface Warning {
  severity: 'info' | 'warning' | 'critical';
  message: string;
  category: string;
}

// Main screening function
async function screenToken(
  tokenAddress: string,
  chain: Chain
): Promise<TokenScreeningResult> {
  const warnings: Warning[] = [];

  // Parallel fetch all data
  const [contract, tax, pools, holders] = await Promise.all([
    threatClient.contracts.analyze(tokenAddress, { chain }),
    threatClient.contracts.getTax(tokenAddress, { chain }),
    tradingClient.tokens.getPools(tokenAddress, { chain }),
    tradingClient.holderAnalysis.get(tokenAddress, { chain }).catch(() => null),
  ]);

  // Critical: Honeypot check
  if (contract.isHoneypot) {
    warnings.push({
      severity: 'critical',
      message: 'This token appears to be a honeypot. You may not be able to sell.',
      category: 'honeypot',
    });

    return {
      allowed: false,
      riskScore: 100,
      warnings,
      taxes: { buy: tax.buyTax, sell: tax.sellTax },
      liquidity: 0,
      holderConcentration: 0,
      recommendation: 'block',
    };
  }

  // Tax warnings
  if (tax.sellTax > 25) {
    warnings.push({
      severity: 'critical',
      message: `Extreme sell tax: ${tax.sellTax}%. You will lose most of your value when selling.`,
      category: 'tax',
    });
  } else if (tax.sellTax > 10) {
    warnings.push({
      severity: 'warning',
      message: `High sell tax: ${tax.sellTax}%`,
      category: 'tax',
    });
  }

  if (tax.buyTax > 10) {
    warnings.push({
      severity: 'warning',
      message: `High buy tax: ${tax.buyTax}%`,
      category: 'tax',
    });
  }

  // Liquidity warnings
  const totalLiquidity = pools.pools.reduce((sum, p) => sum + p.liquidity, 0);
  if (totalLiquidity < 1000) {
    warnings.push({
      severity: 'critical',
      message: `Very low liquidity: $${totalLiquidity.toLocaleString()}. May be unable to sell.`,
      category: 'liquidity',
    });
  } else if (totalLiquidity < 10000) {
    warnings.push({
      severity: 'warning',
      message: `Low liquidity: $${totalLiquidity.toLocaleString()}. Expect high slippage.`,
      category: 'liquidity',
    });
  }

  // Holder concentration warnings
  const holderConcentration = holders?.top10Percentage ?? 0;
  if (holders) {
    if (holders.top10Percentage > 90) {
      warnings.push({
        severity: 'critical',
        message: `Extreme concentration: Top 10 wallets hold ${holders.top10Percentage}%`,
        category: 'holders',
      });
    } else if (holders.top10Percentage > 70) {
      warnings.push({
        severity: 'warning',
        message: `High concentration: Top 10 wallets hold ${holders.top10Percentage}%`,
        category: 'holders',
      });
    }

    if (holders.sniperCount > 10) {
      warnings.push({
        severity: 'warning',
        message: `${holders.sniperCount} snipers detected at launch`,
        category: 'trading',
      });
    }

    if (holders.bundlerCount > 3) {
      warnings.push({
        severity: 'warning',
        message: `${holders.bundlerCount} bundler wallets detected`,
        category: 'trading',
      });
    }
  }

  // Determine recommendation
  const criticalCount = warnings.filter(w => w.severity === 'critical').length;
  const warningCount = warnings.filter(w => w.severity === 'warning').length;

  let recommendation: 'safe' | 'caution' | 'avoid' | 'block' = 'safe';
  if (criticalCount > 0) {
    recommendation = tax.sellTax > 50 ? 'block' : 'avoid';
  } else if (warningCount >= 2) {
    recommendation = 'caution';
  }

  return {
    allowed: recommendation !== 'block',
    riskScore: contract.overallRisk,
    warnings,
    taxes: { buy: tax.buyTax, sell: tax.sellTax },
    liquidity: totalLiquidity,
    holderConcentration,
    recommendation,
  };
}

// Quick screen for Solana (using Trading Lite)
async function quickScreenSolana(tokenMint: string): Promise<{
  safe: boolean;
  riskScore: number;
  isHoneypot: boolean;
  liquidity: number;
}> {
  const result = await tradingClient.tradingLite.analyze(tokenMint);

  return {
    safe: result.riskScore < 50 && !result.isHoneypot,
    riskScore: result.riskScore,
    isHoneypot: result.isHoneypot,
    liquidity: result.liquidity,
  };
}

// Batch screen for token lists
async function screenTokenList(
  tokens: Array<{ address: string; chain: Chain }>
): Promise<Map<string, TokenScreeningResult>> {
  const results = new Map<string, TokenScreeningResult>();

  // Process in batches of 5 to avoid rate limits
  for (let i = 0; i < tokens.length; i += 5) {
    const batch = tokens.slice(i, i + 5);
    const batchResults = await Promise.all(
      batch.map(t => screenToken(t.address, t.chain))
    );

    batch.forEach((token, index) => {
      results.set(token.address, batchResults[index]);
    });
  }

  return results;
}

Example Tokens for Testing

Known Honeypots

AddressChainDescription
Test with newly deployed tokens on testnets-Honeypots are constantly being deployed

High Tax Tokens

AddressChainDescription
Various “reflection” or “rebase” tokens-Often have hidden mechanics

Safe Tokens (for comparison)

AddressChainDescription
0xdAC17F958D2ee523a2206206994597C13D831ec7ETHUSDT - no tax, high liquidity
0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48ETHUSDC - verified, safe
0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599ETHWBTC - established token
Testing tip: For honeypot and tax testing, use tokens you find in real-time on DEX trending lists. Scam tokens are deployed constantly, so the best test data is fresh data.

API Quick Reference

EndpointUse CaseResponse Time
GET /contracts/{address}Contract analysis~500ms
GET /contracts/{address}/taxTax detection~300ms
GET /holder-analysis/{address}Holder distribution~400ms
GET /tokens/{address}/poolsLiquidity pools~300ms
GET /trading-lite/{address}Quick analysis (SOL)~200ms

Next Steps