Skip to main content
Glama

token_analyze

Analyze Hedera tokens to assess holder distribution, transfer velocity, liquidity, and risk scoring using live blockchain data.

Instructions

Deep analysis of a Hedera token including holder distribution, transfer velocity, liquidity, and risk scoring. Costs 0.3 HBAR.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
api_keyYesYour HederaIntel API key
token_idYesHedera token ID to analyze (e.g. 0.0.123456)

Implementation Reference

  • The handler for the 'token_analyze' tool, which performs a deep analysis of a Hedera token including holder distribution, concentration, risk scoring, and administration keys.
    if (name === "token_analyze") {
      const payment = chargeForTool("token_analyze", args.api_key);
      const base = getMirrorNodeBase();
    
      const tokenRes = await axios.get(`${base}/api/v1/tokens/${args.token_id}`);
      const token = tokenRes.data;
      const decimals = parseInt(token.decimals || 0);
      const totalSupply = parseInt(token.total_supply || 0);
      const adjustedSupply = totalSupply / Math.pow(10, decimals);
    
      // Holder distribution — fetch max and sort client-side by balance desc
      const balRes = await axios.get(
        `${base}/api/v1/tokens/${args.token_id}/balances?limit=100&account.balance.gt=0`
      ).catch(() => ({ data: { balances: [] } }));
      const holders = (balRes.data.balances || []).sort((a, b) => parseInt(b.balance || 0) - parseInt(a.balance || 0));
    
      // Concentration analysis
      const top1Pct = holders[0] ? (parseInt(holders[0].balance) / totalSupply * 100).toFixed(1) : 0;
      const top5Balance = holders.slice(0, 5).reduce((s, b) => s + parseInt(b.balance || 0), 0);
      const top10Balance = holders.slice(0, 10).reduce((s, b) => s + parseInt(b.balance || 0), 0);
      const top5Pct = totalSupply > 0 ? (top5Balance / totalSupply * 100).toFixed(1) : 0;
      const top10Pct = totalSupply > 0 ? (top10Balance / totalSupply * 100).toFixed(1) : 0;
    
      // SaucerSwap listing info
      const saucerTokens = await getSaucerSwapTokens();
      const saucerToken = saucerTokens.find(t => t.id === args.token_id);
    
      // Risk scoring
      let riskScore = 0;
      let riskFactors = [];
      if (parseFloat(top1Pct) > 50) { riskScore += 30; riskFactors.push("Single holder controls over 50% of supply"); }
      else if (parseFloat(top1Pct) > 30) { riskScore += 15; riskFactors.push("Single holder controls over 30% of supply"); }
      if (parseFloat(top5Pct) > 80) { riskScore += 25; riskFactors.push("Top 5 holders control over 80% of supply"); }
      else if (parseFloat(top5Pct) > 60) { riskScore += 10; riskFactors.push("Top 5 holders control over 60% of supply"); }
      if (holders.length < 10) { riskScore += 20; riskFactors.push("Very few holders - low distribution"); }
      else if (holders.length < 50) { riskScore += 10; riskFactors.push("Limited holder count"); }
      if (token.freeze_key) { riskScore += 10; riskFactors.push("Token has freeze key - admin can freeze accounts"); }
      if (token.wipe_key) { riskScore += 10; riskFactors.push("Token has wipe key - admin can wipe balances"); }
      if (token.supply_key) { riskFactors.push("Token has supply key - admin can mint or burn tokens"); }
      if (saucerToken && !saucerToken.dueDiligenceComplete) { riskScore += 15; riskFactors.push("SaucerSwap due diligence not complete"); }
    
      const riskLevel = riskScore >= 60 ? "HIGH" : riskScore >= 30 ? "MEDIUM" : "LOW";
    
      const topHolders = holders.slice(0, 10).map((b, i) => ({
        rank: i + 1,
        account: b.account,
        balance: (parseInt(b.balance) / Math.pow(10, decimals)).toLocaleString(),
        pct_supply: totalSupply > 0 ? (parseInt(b.balance) / totalSupply * 100).toFixed(2) + "%" : "unknown",
      }));
    
      return {
        token_id: args.token_id,
        name: token.name || "Unknown",
        symbol: token.symbol || "?",
        decimals,
        total_supply: adjustedSupply.toLocaleString(),
        type: token.type || "FUNGIBLE_COMMON",
        treasury: token.treasury_account_id,
        total_holders: holders.length,
        dex_listed: !!saucerToken,
        dex_price_usd: saucerToken?.priceUsd || null,
        due_diligence_complete: saucerToken?.dueDiligenceComplete ?? null,
        top_holders: topHolders,
        concentration: {
          top_1_pct: top1Pct + "%",
          top_5_pct: top5Pct + "%",
          top_10_pct: top10Pct + "%",
        },
        admin_keys: {
          freeze_key: !!token.freeze_key,
          wipe_key: !!token.wipe_key,
          supply_key: !!token.supply_key,
          kyc_key: !!token.kyc_key,
          pause_key: !!token.pause_key,
        },
        risk_assessment: {
          score: riskScore,
          level: riskLevel,
          factors: riskFactors.length > 0 ? riskFactors : ["No major risk factors detected"],
        },
        created_timestamp: token.created_timestamp,
        memo: token.memo || null,
        payment,
        timestamp: new Date().toISOString(),
      };
    }
  • The schema definition for the 'token_analyze' tool, specifying its input requirements (token_id and api_key).
    {
      name: "token_analyze",
      description: "Deep analysis of a Hedera token including holder distribution, transfer velocity, liquidity, and risk scoring. Costs 0.6 HBAR.",
      inputSchema: {
        type: "object",
        properties: {
          token_id: { type: "string", description: "Hedera token ID to analyze (e.g. 0.0.123456)" },
          api_key: { type: "string", description: "Your HederaIntel API key" },
        },
        required: ["token_id", "api_key"],
      },
    },

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mountainmystic/hederatoolbox'

If you have feedback or need assistance with the MCP directory API, please join our Discord server