GMGN 前排统计

统计GMGN任意代币前排地址的数据,让数字来说话!新增首次记录和涨跌提醒功能,所有数字可点击查看详情,弹框显示净流入数据,负数红色显示,点击外部关闭

当前为 2025-08-12 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         GMGN 前排统计
// @namespace    http://tampermonkey.net/
// @version      4.7
// @description  统计GMGN任意代币前排地址的数据,让数字来说话!新增首次记录和涨跌提醒功能,所有数字可点击查看详情,弹框显示净流入数据,负数红色显示,点击外部关闭
// @match        https://gmgn.ai/*
// @match        https://www.gmgn.ai/*
// @require      https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js
// @require      https://code.jquery.com/jquery-3.6.0.min.js
// @grant        none
// @run-at       document-start
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // 动态添加 CSS
    const style = document.createElement('style');
    style.textContent = `
    .statistic-gmgn-stats-container {
        background-color: transparent;
        border-radius: 4px;
        font-family: Arial, sans-serif;
        margin-right: 8px;
        margin-bottom:8px;
        border: 1px solid #333;
        /* 精细的右侧和下侧发光效果 */
        box-shadow:
            2px 2px 4px rgba(0, 119, 255, 0.6),  /* 右下外发光(更小的偏移和模糊) */
            1px 1px 2px rgba(0, 119, 255, 0.4),  /* 精细的次级发光 */
            inset 0 0 3px rgba(0, 119, 255, 0.2); /* 更细腻的内发光 */
        padding: 4px 6px;
        max-width: fit-content;
    }
    .statistic-gmgn-stats-header, .statistic-gmgn-stats-data {
        display: grid;
        grid-template-columns: repeat(11, 1fr);
        text-align: center;
        gap: 6px;
        font-weight: normal;
        font-size: 13px;
    }
    .statistic-gmgn-stats-header.sol-network, .statistic-gmgn-stats-data.sol-network {
        grid-template-columns: repeat(12, minmax(auto, 1fr));
        gap: 4px;
        font-size: 12px;
    }
    .statistic-gmgn-stats-header span {
        color: #ccc;
        font-weight: normal;
        padding: 1px 2px;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .statistic-gmgn-stats-header.sol-network span {
        font-size: 11px;
        padding: 1px;
    }
    .statistic-gmgn-stats-data span {
        color: #00ff00;
        font-weight: normal;
        cursor: default;
        transition: all 0.2s ease;
        padding: 1px 3px;
        border-radius: 2px;
        min-width: 0;
        white-space: nowrap;
    }
    .statistic-gmgn-stats-data span.clickable {
        cursor: pointer;
    }
    .statistic-gmgn-stats-data span.clickable:hover {
        background-color: rgba(0, 255, 0, 0.1);
        border-radius: 3px;
        transform: scale(1.03);
    }
    .statistic-gmgn-stats-data.sol-network span {
        padding: 1px 2px;
        font-size: 12px;
    }
    .statistic-gmgn-stats-data span .statistic-up-arrow,
    .statistic-up-arrow {
        color: green !important;
        margin-left: 2px;
        font-weight: bold;
    }
    .statistic-gmgn-stats-data span .statistic-down-arrow,
    .statistic-down-arrow {
        color: red !important;
        margin-left: 2px;
        font-weight: bold;
    }




    /* 完整弹框CSS样式 - 从token_holding_temp.js复制并添加statistic前缀 */
    .statistic-gmgn-modal {
                position: fixed;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                background-color: rgba(0, 0, 0, 0.5);
                display: flex;
                align-items: center;
                justify-content: center;
                z-index: 1000;
    }
    .statistic-gmgn-modal-content {
        background-color: #1e293b !important;
        border-radius: 8px !important;
        width: 80% !important;
        max-width: 800px !important;
        max-height: 80vh !important;
        overflow-y: auto !important;
        padding: 20px !important;
        color: white !important;
        position: fixed !important;
        top: 50% !important;
        left: 50% !important;
        transform: translate(-50%, -50%) !important;
        box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5) !important;
        margin: 0 !important;
        z-index: 100000 !important;
        box-sizing: border-box !important;
        min-height: auto !important;
        min-width: 300px !important;
        pointer-events: auto !important;
    }
    .statistic-gmgn-modal-header {
        display: flex !important;
        justify-content: space-between !important;
        align-items: center !important;
        margin-bottom: 16px !important;
        padding: 0 !important;
    }
    .statistic-gmgn-modal-title {
        font-size: 18px !important;
        font-weight: 600 !important;
        color: white !important;
        margin: 0 !important;
    }
    .statistic-gmgn-modal-close {
        background: none !important;
        border: none !important;
        color: #94a3b8 !important;
        font-size: 20px !important;
        cursor: pointer !important;
        padding: 5px !important;
        line-height: 1 !important;
        width: auto !important;
        height: auto !important;
        min-width: 30px !important;
        min-height: 30px !important;
    }
    .statistic-gmgn-modal-close:hover {
        color: #ff4444 !important;
        background-color: rgba(255, 255, 255, 0.1) !important;
        border-radius: 4px !important;
    }
    .statistic-gmgn-result-item {
        background-color: #334155;
        border-radius: 6px;
        padding: 12px;
        margin-bottom: 12px;
    }
    .statistic-gmgn-analysis-summary {
        margin-bottom: 16px;
        padding: 12px;
        background-color: #263238;
        border-radius: 6px;
        display: flex;
        justify-content: space-between;
        align-items: center;
    }
    .statistic-gmgn-summary-stats {
        display: flex;
        gap: 20px;
    }
    .statistic-gmgn-stat-item {
        display: flex;
        align-items: baseline;
    }
    .statistic-gmgn-stat-label {
        color: #94a3b8;
        margin-right: 5px;
    }
    .statistic-gmgn-stat-value {
        font-weight: 600;
        color: #3b82f6;
    }
    .statistic-gmgn-result-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 8px;
        flex-wrap: wrap;
        gap: 8px;
    }
    .statistic-gmgn-result-rank {
        font-size: 14px;
        color: #94a3b8;
        font-weight: 600;
        min-width: 30px;
    }
    .statistic-gmgn-result-address {
        font-weight: 600;
        word-break: break-all;
        cursor: pointer;
        padding: 4px 8px;
        border-radius: 4px;
        transition: all 0.2s ease;
        background-color: #475569;
        flex: 1;
        min-width: 200px;
        color: #00ff88;
        font-family: monospace;
    }
    .statistic-gmgn-result-address:hover {
        background-color: #64748b;
        transform: translateY(-1px);
    }
    .statistic-gmgn-detail-section {
        margin-bottom: 12px;
    }
    .statistic-gmgn-section-title {
        font-size: 13px;
        font-weight: 600;
        color: #94a3b8;
        margin-bottom: 8px;
    }
    .statistic-gmgn-detail-grid {
        display: grid;
        grid-template-columns: 80px 1fr 80px 1fr;
        gap: 4px 8px;
        align-items: start;
        font-size: 12px;
    }
    .statistic-gmgn-detail-label {
        color: #94a3b8;
        font-size: 12px;
        padding: 2px 0;
        align-self: start;
    }
    .statistic-gmgn-detail-value {
        font-size: 12px;
        color: #e2e8f0;
        padding: 2px 0;
        word-break: break-word;
        line-height: 1.4;
    }
    .statistic-gmgn-value-highlight {
        color: #3b82f6;
        font-weight: 600;
    }
    .statistic-gmgn-compact-details .statistic-gmgn-detail-section {
        margin-bottom: 8px;
    }
    .statistic-gmgn-compact-details .statistic-gmgn-detail-section {
        margin-left: 10px;
    }
    .statistic-gmgn-address-jump-btn {
        background-color: #10b981;
        color: white;
        padding: 4px 8px;
        border-radius: 6px;
        font-size: 11px;
        font-weight: 500;
        margin-left: 8px;
        cursor: pointer;
        transition: all 0.2s ease;
        text-decoration: none;
        display: inline-block;
        border: none;
    }
    .statistic-gmgn-address-jump-btn:hover {
        background-color: #059669;
        transform: translateY(-1px);
        box-shadow: 0 2px 4px rgba(16, 185, 129, 0.3);
    }

    .statistic-gmgn-profit-positive {
        color: #00ff88 !important;
    }

    .statistic-gmgn-profit-negative {
        color: #ff4444 !important;
    }

    .statistic-gmgn-empty-message {
        text-align: center;
        color: #ccc;
        padding: 20px;
        margin: 0;
    }

    .statistic-gmgn-stats-info {
        text-align: center !important;
        margin-bottom: 15px !important;
        padding: 10px !important;
        background: rgba(0, 119, 255, 0.1) !important;
        border-radius: 8px !important;
        border: 1px solid rgba(0, 119, 255, 0.3) !important;
        color: #fff !important;
        font-size: 14px !important;
    }

    .statistic-gmgn-export-btn {
        background-color: #10b981 !important;
        color: white !important;
        border: none !important;
        padding: 8px 16px !important;
        border-radius: 6px !important;
        font-size: 12px !important;
        font-weight: 500 !important;
        cursor: pointer !important;
        transition: all 0.2s ease !important;
        display: flex !important;
        align-items: center !important;
        gap: 4px !important;
    }

    .statistic-gmgn-export-btn:hover {
        background-color: #059669 !important;
        transform: translateY(-1px) !important;
        box-shadow: 0 2px 4px rgba(16, 185, 129, 0.3) !important;
    }
`;
    document.head.appendChild(style);

    // 存储拦截到的数据
    let interceptedData = null;
    // 存储首次加载的数据
    let initialStats = null;
    // 标记是否是首次加载
    let isFirstLoad = true;
    // 新增存储当前CA地址
    let currentCaAddress = null;
    // 存储首次加载的CA地址
    let initialCaAddress = null;

    // 检查当前网络是否为SOL
    function isSolNetwork() {
        const url = window.location.href;
        return url.includes('/sol/') || url.includes('gmgn.ai/sol');
    }

    // 检查是否为交易所地址
    function isExchangeAddress(holder) {
        const exchangeNames = ['coinbase', 'binance', 'bybit', 'bitget', 'okx', 'kraken', 'coinsquare', 'crypto.com', 'robinhood', 'mexc'];

        // 检查native_transfer中的name
        if (holder.native_transfer && holder.native_transfer.name) {
            const name = holder.native_transfer.name.toLowerCase();
            if (exchangeNames.some(exchange => name.includes(exchange))) {
                return true;
            }
        }

        // 检查其他可能的transfer字段
        if (holder.transfer && holder.transfer.name) {
            const name = holder.transfer.name.toLowerCase();
            if (exchangeNames.some(exchange => name.includes(exchange))) {
                return true;
            }
        }

        return false;
    }

    // 获取交易所名称
    function getExchangeName(holder) {
        const exchangeNames = ['coinbase', 'binance', 'bybit', 'bitget', 'okx', 'kraken', 'coinsquare', 'crypto.com', 'robinhood', 'mexc'];

        let sourceName = '';
        if (holder.native_transfer && holder.native_transfer.name) {
            sourceName = holder.native_transfer.name.toLowerCase();
        } else if (holder.transfer && holder.transfer.name) {
            sourceName = holder.transfer.name.toLowerCase();
        }

        for (let exchange of exchangeNames) {
            if (sourceName.includes(exchange)) {
                return exchange.charAt(0).toUpperCase() + exchange.slice(1);
            }
        }

        return 'Unknown';
    }
    // 交易所专用弹框
    function createExchangeModal(data, caAddress) {
        // 移除已存在的弹框
        const existingModal = document.querySelector('.statistic-gmgn-modal');
        if (existingModal) {
            existingModal.remove();
        }

        // 按交易所分组数据
        const exchangeGroups = {};
        data.forEach(holder => {
            const exchangeName = getExchangeName(holder);
            if (!exchangeGroups[exchangeName]) {
                exchangeGroups[exchangeName] = [];
            }
            exchangeGroups[exchangeName].push(holder);
        });

        // 创建弹框
        const modal = document.createElement('div');
        modal.className = 'statistic-gmgn-modal';

        // 生成交易所统计数据
        const exchangeSummary = Object.keys(exchangeGroups).map(exchange => {
            return {
                name: exchange,
                count: exchangeGroups[exchange].length,
                addresses: exchangeGroups[exchange]
            };
        }).sort((a, b) => b.count - a.count);

        modal.innerHTML = `
            <div class="statistic-gmgn-modal-content">
                <div class="statistic-gmgn-modal-header">
                    <div class="statistic-gmgn-modal-title">🏢 交易所地址分析 (共${data.length}个地址)</div>
                    <button class="statistic-gmgn-modal-close">&times;</button>
                </div>
                <div class="statistic-gmgn-analysis-summary">
                    <div class="statistic-gmgn-summary-stats">
                        <div class="statistic-gmgn-stat-item">
                            <span class="statistic-gmgn-stat-label">CA地址:</span>
                            <span class="statistic-gmgn-stat-value">${caAddress || 'N/A'}</span>
                        </div>
                        <div class="statistic-gmgn-stat-item">
                            <span class="statistic-gmgn-stat-label">交易所数:</span>
                            <span class="statistic-gmgn-stat-value">${Object.keys(exchangeGroups).length}</span>
                        </div>
                    </div>
                    <button id="statistic-export-exchange-btn" class="statistic-gmgn-export-btn" title="导出Excel">📄 导出Excel</button>
                </div>
                <div id="statistic-exchange-summary">
                    <div class="statistic-gmgn-section-title">📈 交易所统计</div>
                    <div class="statistic-exchange-summary-grid">
                        ${exchangeSummary.map(item => `
                            <div class="statistic-exchange-summary-item" data-exchange="${item.name}">
                                <span class="statistic-exchange-name">${item.name}</span>
                                <span class="statistic-exchange-count">${item.count}个地址</span>
                            </div>
                        `).join('')}
                    </div>
                </div>
                <div id="statistic-exchange-details"></div>
            </div>
        `;

        document.body.appendChild(modal);

        // 添加交易所统计样式
        if (!document.getElementById('exchange-summary-styles')) {
            const summaryStyles = document.createElement('style');
            summaryStyles.id = 'exchange-summary-styles';
            summaryStyles.textContent = `
                .statistic-exchange-summary-grid {
                    display: grid;
                    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
                    gap: 12px;
                    margin-bottom: 20px;
                }
                .statistic-exchange-summary-item {
                    background-color: #475569;
                    border-radius: 8px;
                    padding: 12px 16px;
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    cursor: pointer;
                    transition: all 0.3s ease;
                    border: 2px solid transparent;
                }
                .statistic-exchange-summary-item:hover {
                    background-color: #64748b;
                    border-color: #3b82f6;
                    transform: translateY(-2px);
                }
                .statistic-exchange-summary-item.active {
                    background-color: #3b82f6;
                    border-color: #1d4ed8;
                }
                .statistic-exchange-name {
                    font-weight: 600;
                    color: #e2e8f0;
                    font-size: 14px;
                }
                .statistic-exchange-count {
                    color: #10b981;
                    font-weight: 600;
                    font-size: 13px;
                }
                .statistic-exchange-details-section {
                    margin-bottom: 20px;
                }
                .statistic-exchange-section-header {
                    background-color: #1e293b;
                    padding: 12px 16px;
                    border-radius: 8px 8px 0 0;
                    border-left: 4px solid #3b82f6;
                    margin-bottom: 0;
                }
                .statistic-exchange-section-title {
                    font-size: 16px;
                    font-weight: 600;
                    color: #3b82f6;
                    margin: 0;
                }
                .statistic-exchange-section-count {
                    font-size: 12px;
                    color: #94a3b8;
                    margin-top: 4px;
                }
            `;
            document.head.appendChild(summaryStyles);
        }

        // 绑定交易所统计点击事件
        exchangeSummary.forEach(item => {
            const summaryItem = modal.querySelector(`[data-exchange="${item.name}"]`);
            if (summaryItem) {
                summaryItem.addEventListener('click', () => {
                    // 移除所有活跃状态
                    modal.querySelectorAll('.statistic-exchange-summary-item').forEach(el => {
                        el.classList.remove('active');
                    });
                    // 添加当前活跃状态
                    summaryItem.classList.add('active');
                    // 显示该交易所的详细信息
                    displayExchangeDetails(item.addresses, item.name, modal);
                });
            }
        });

        // ESC键关闭处理函数
        const escKeyHandler = (e) => {
            if (e.key === 'Escape') {
                document.body.removeChild(modal);
                document.removeEventListener('keydown', escKeyHandler);
            }
        };
        document.addEventListener('keydown', escKeyHandler);

        // 绑定导出Excel按钮事件
        const exportBtn = modal.querySelector('#statistic-export-exchange-btn');
        if (exportBtn) {
            exportBtn.addEventListener('click', () => {
                exportExchangeToExcel(exchangeGroups, caAddress);
            });
        }

        // 绑定关闭按钮事件
        modal.querySelector('.statistic-gmgn-modal-close').addEventListener('click', () => {
            document.body.removeChild(modal);
            document.removeEventListener('keydown', escKeyHandler);
        });

        // 点击模态框外部关闭
        modal.addEventListener('click', (e) => {
            if (e.target === modal) {
                document.body.removeChild(modal);
                document.removeEventListener('keydown', escKeyHandler);
            }
        });

        // 默认显示第一个交易所的详情
        if (exchangeSummary.length > 0) {
            const firstItem = modal.querySelector(`[data-exchange="${exchangeSummary[0].name}"]`);
            if (firstItem) {
                firstItem.click();
            }
        }
    }

    // 显示交易所详细信息
    function displayExchangeDetails(addresses, exchangeName, modal) {
        const detailsContainer = modal.querySelector('#statistic-exchange-details');

        // 创建全局排名映射 - 基于原始完整数据按持仓比例排序
        const globalRankMap = new Map();
        if (interceptedData?.data?.list) {
            const allHolders = [...interceptedData.data.list];
            allHolders
                .sort((a, b) => (b.amount_percentage || 0) - (a.amount_percentage || 0))
                .forEach((holder, index) => {
                    globalRankMap.set(holder.address, index + 1);
                });
        }

        // 按持仓比例排序
        const sortedAddresses = addresses.sort((a, b) => (b.amount_percentage || 0) - (a.amount_percentage || 0));

        detailsContainer.innerHTML = `
            <div class="statistic-exchange-details-section">
                <div class="statistic-exchange-section-header">
                    <div class="statistic-exchange-section-title">${exchangeName} 地址详情</div>
                    <div class="statistic-exchange-section-count">共 ${sortedAddresses.length} 个地址</div>
                </div>
                ${sortedAddresses.map((holder, index) => {
                    const globalRank = globalRankMap.get(holder.address) || (index + 1);
                    const processedData = {
                        rank: index + 1,
                        rankIndex: globalRank, // 使用全局排名
                        address: holder.address,
                        balance: formatNumber(holder.balance),
                        usdValue: formatNumber(holder.usd_value),
                        netflowUsd: formatNumber(holder.netflow_usd),
                        netflowClass: (holder.netflow_usd || 0) >= 0 ? 'statistic-gmgn-profit-positive' : 'statistic-gmgn-profit-negative',
                        profit: formatNumber(holder.profit),
                        profitSign: holder.profit >= 0 ? '+' : '',
                        profitClass: holder.profit >= 0 ? 'statistic-gmgn-profit-positive' : 'statistic-gmgn-profit-negative',
                        profitChange: holder.profit_change ? (holder.profit_change * 100).toFixed(1) + '%' : 'N/A',
                        profitChangeClass: (holder.profit_change || 0) >= 0 ? 'statistic-gmgn-profit-positive' : 'statistic-gmgn-profit-negative',
                        exchangeName: getExchangeName(holder),
                        transferName: (holder.native_transfer && holder.native_transfer.name) || (holder.transfer && holder.transfer.name) || 'N/A',
                        amountPercentage: holder.amount_percentage ? (holder.amount_percentage * 100).toFixed(2) + '%' : 'N/A',
                        sellPercentage: holder.sell_amount_percentage ? (holder.sell_amount_percentage * 100).toFixed(2) + '%' : '0.00%' // 筹码已卖
                    };

                    return `
                        <div class="statistic-gmgn-result-item">
                            <div class="statistic-gmgn-result-header">
                                <div class="statistic-gmgn-result-rank">
                                    <span style="color: #ff6b35; font-weight: bold; background: rgba(255, 107, 53, 0.15); padding: 2px 6px; border-radius: 12px; border: 1px solid rgba(255, 107, 53, 0.3); font-size: 12px;">榜${processedData.rankIndex}</span>
                                </div>
                                <div class="statistic-gmgn-result-address" title="点击复制地址" onclick="navigator.clipboard.writeText('${processedData.address}'); this.style.backgroundColor='#16a34a'; this.style.color='white'; setTimeout(() => { this.style.backgroundColor=''; this.style.color=''; }, 1000);">${processedData.address}</div>
                                <a href="https://gmgn.ai/sol/address/${processedData.address}" target="_blank" class="statistic-gmgn-address-jump-btn" title="查看钱包详情">详情</a>
                            </div>
                            <div class="statistic-gmgn-compact-details">
                                <div class="statistic-gmgn-detail-section">
                                    <div class="statistic-gmgn-section-title">基本信息</div>
                                    <div class="statistic-gmgn-detail-grid">
                                        <span class="statistic-gmgn-detail-label">持仓:</span>
                                        <span class="statistic-gmgn-detail-value">${processedData.balance}</span>
                                        <span class="statistic-gmgn-detail-label">持仓占比:</span>
                                        <span class="statistic-gmgn-detail-value statistic-gmgn-value-highlight">${processedData.amountPercentage}</span>
                                        <span class="statistic-gmgn-detail-label">筹码已卖:</span>
                                        <span class="statistic-gmgn-detail-value" style="color: ${processedData.sellPercentage === '0.00%' ? '#00ff88' : '#ff6b35'}; font-weight: bold;">${processedData.sellPercentage}</span>
                                        <span class="statistic-gmgn-detail-label">净流入:</span>
                                        <span class="statistic-gmgn-detail-value ${processedData.netflowClass}">$${processedData.netflowUsd}</span>
                                        <span class="statistic-gmgn-detail-label">盈亏:</span>
                                        <span class="statistic-gmgn-detail-value ${processedData.profitClass}">${processedData.profitSign}$${processedData.profit}</span>
                                        <span class="statistic-gmgn-detail-label">倍数:</span>
                                        <span class="statistic-gmgn-detail-value ${processedData.profitChangeClass}">${processedData.profitChange}</span>
                                        <span class="statistic-gmgn-detail-label">交易所:</span>
                                        <span class="statistic-gmgn-detail-value statistic-gmgn-value-highlight">${processedData.exchangeName}</span>
                                        <span class="statistic-gmgn-detail-label">标签:</span>
                                        <span class="statistic-gmgn-detail-value">${processedData.transferName}</span>
                                    </div>
                                </div>
                            </div>
                        </div>
                    `;
                }).join('')}
            </div>
        `;
    }

    // 交易所数据导出函数
    function exportExchangeToExcel(exchangeGroups, caAddress) {
        try {
            const worksheetData = [];

            // 添加标题行
            worksheetData.push(['交易所', '排名', '地址', '持仓数量', '持仓比例', '筹码已卖', 'USD价值', '净流入USD', '盈亏USD', '盈亏倍数', '标签名称']);

            // 按交易所排序添加数据
            Object.keys(exchangeGroups).forEach(exchangeName => {
                const addresses = exchangeGroups[exchangeName].sort((a, b) => (b.amount_percentage || 0) - (a.amount_percentage || 0));
                addresses.forEach((holder, index) => {
                    const row = [
                        exchangeName,
                        index + 1,
                        holder.address,
                        formatNumber(holder.balance),
                        holder.amount_percentage ? (holder.amount_percentage * 100).toFixed(2) + '%' : 'N/A',
                        holder.sell_amount_percentage ? (holder.sell_amount_percentage * 100).toFixed(2) + '%' : '0.00%',
                        formatNumber(holder.usd_value),
                        formatNumber(holder.netflow_usd),
                        (holder.profit >= 0 ? '+' : '') + formatNumber(holder.profit),
                        holder.profit_change ? (holder.profit_change * 100).toFixed(1) + '%' : 'N/A',
                        (holder.native_transfer && holder.native_transfer.name) || (holder.transfer && holder.transfer.name) || 'N/A'
                    ];
                    worksheetData.push(row);
                });
            });

            // 创建工作簿
            const wb = XLSX.utils.book_new();
            const ws = XLSX.utils.aoa_to_sheet(worksheetData);

            // 设置列宽
            const colWidths = [
                {wch: 12},  // 交易所
                {wch: 6},   // 排名
                {wch: 45},  // 地址
                {wch: 15},  // 持仓数量
                {wch: 10},  // 持仓比例
                {wch: 10},  // 已卖比例
                {wch: 15},  // USD价值
                {wch: 15},  // 净流入
                {wch: 15},  // 盈亏
                {wch: 12},  // 倍数
                {wch: 25}   // 标签名称
            ];
            ws['!cols'] = colWidths;

            // 添加工作表到工作簿
            XLSX.utils.book_append_sheet(wb, ws, '交易所地址');

            // 生成文件名
            const timestamp = new Date().toISOString().slice(0, 19).replace(/:/g, '-');
            const fileName = `交易所地址_${caAddress ? caAddress.slice(0, 8) : 'data'}_${timestamp}.xlsx`;

            // 下载文件
            XLSX.writeFile(wb, fileName);

            // 显示成功提示
            const exportBtn = document.querySelector('#statistic-export-exchange-btn');
            if (exportBtn) {
                const originalText = exportBtn.textContent;
                exportBtn.textContent = '✅ 导出成功';
                exportBtn.style.backgroundColor = '#059669';
                setTimeout(() => {
                    exportBtn.textContent = originalText;
                    exportBtn.style.backgroundColor = '';
                }, 2000);
            }

        } catch (error) {
            console.error('Excel导出失败:', error);
            alert('导出失败,请检查浏览器控制台了解详情');
        }
    }

    // 优化后的弹框管理函数
    function createModal(title, data, caAddress, showSolBalance = false) {
        // 移除已存在的弹框
        const existingModal = document.querySelector('.statistic-gmgn-modal');
        if (existingModal) {
            existingModal.remove();
        }

        // 1. 数据预处理 - 首先获取全局排名
        if (!interceptedData?.data?.list) {
            console.error('无法获取原始数据进行全局排名');
            return;
        }

        // 创建全局排名映射 - 基于原始完整数据按持仓比例排序
        const globalRankMap = new Map();
        const allHolders = [...interceptedData.data.list];
        allHolders
            .sort((a, b) => (b.amount_percentage || 0) - (a.amount_percentage || 0))
            .forEach((holder, index) => {
                globalRankMap.set(holder.address, index + 1);
            });

        // 2. 处理筛选后的数据,使用全局排名
        const processedData = data
            .sort((a, b) => (b.amount_percentage || 0) - (a.amount_percentage || 0)) // 按持仓比例排序
            .map((holder, index) => {
                const globalRank = globalRankMap.get(holder.address) || (index + 1);
                const baseData = {
                    rank: index + 1, // 在当前数据集中的排名(用于显示序号)
                    rankIndex: globalRank, // 在全局数据中的排名(用于显示"榜X")
                    address: holder.address,
                    balance: formatNumber(holder.balance),
                    usdValue: formatNumber(holder.usd_value),
                    netflowUsd: formatNumber(holder.netflow_usd),
                    netflowClass: (holder.netflow_usd || 0) >= 0 ? 'statistic-gmgn-profit-positive' : 'statistic-gmgn-profit-negative',
                    profit: formatNumber(holder.profit),
                    profitSign: holder.profit >= 0 ? '+' : '',
                    profitClass: holder.profit >= 0 ? 'statistic-gmgn-profit-positive' : 'statistic-gmgn-profit-negative',
                    profitChange: holder.profit_change ? (holder.profit_change * 100).toFixed(1) + '%' : 'N/A',
                    profitChangeClass: (holder.profit_change || 0) >= 0 ? 'statistic-gmgn-profit-positive' : 'statistic-gmgn-profit-negative',
                    amountPercentage: holder.amount_percentage ? (holder.amount_percentage * 100).toFixed(2) + '%' : 'N/A',
                    sellPercentage: holder.sell_amount_percentage ? (holder.sell_amount_percentage * 100).toFixed(2) + '%' : '0.00%' // 筹码已卖
                };

                // 只有在需要显示SOL余额时才添加
                if (showSolBalance) {
                    baseData.solBalance = holder.native_balance ? ((holder.native_balance / 1000000000).toFixed(2) + ' SOL') : 'N/A';
                }

                return baseData;
            });

        // 2. 创建弹框基础结构 - 使用token_holding_temp.js的DOM结构
        const modal = document.createElement('div');
        modal.className = 'statistic-gmgn-modal';
        modal.innerHTML = `
            <div class="statistic-gmgn-modal-content">
                <div class="statistic-gmgn-modal-header">
                    <div class="statistic-gmgn-modal-title">📊 ${title} (${processedData.length}个地址)</div>
                    <button class="statistic-gmgn-modal-close">&times;</button>
                </div>
                <div class="statistic-gmgn-analysis-summary">
                    <div class="statistic-gmgn-summary-stats">
                        <div class="statistic-gmgn-stat-item">
                            <span class="statistic-gmgn-stat-label">CA地址:</span>
                            <span class="statistic-gmgn-stat-value">${caAddress || 'N/A'}</span>
                        </div>
                        <div class="statistic-gmgn-stat-item">
                            <span class="statistic-gmgn-stat-label">总数量:</span>
                            <span class="statistic-gmgn-stat-value">${processedData.length}</span>
                        </div>
                    </div>
                    <button id="statistic-export-excel-btn" class="statistic-gmgn-export-btn" title="导出Excel">📊 导出Excel</button>
                </div>
                <div id="statistic-gmgn-results-list"></div>
                </div>
        `;

        // 3. 插入DOM
        document.body.appendChild(modal);

        // 4. 填充结果列表 - 参考token_holding_temp.js的方式
        const resultsList = document.getElementById('statistic-gmgn-results-list');
        processedData.forEach((holder, index) => {
            const item = document.createElement('div');
            item.className = 'statistic-gmgn-result-item';
            item.innerHTML = `
                <div class="statistic-gmgn-result-header">
                    <div class="statistic-gmgn-result-rank">
                        <span style="color: #ff6b35; font-weight: bold; background: rgba(255, 107, 53, 0.15); padding: 2px 6px; border-radius: 12px; border: 1px solid rgba(255, 107, 53, 0.3); font-size: 12px;">榜${holder.rankIndex}</span>
                    </div>
                    <div class="statistic-gmgn-result-address" title="点击复制地址">${holder.address}</div>
                    <a href="https://gmgn.ai/sol/address/${holder.address}" target="_blank" class="statistic-gmgn-address-jump-btn" title="查看钱包详情">详情</a>
                                </div>

                <div class="statistic-gmgn-compact-details">
                    <div class="statistic-gmgn-detail-section">
                        <div class="statistic-gmgn-section-title">基本信息</div>
                        <div class="statistic-gmgn-detail-grid">
                            <span class="statistic-gmgn-detail-label">持仓:</span>
                            <span class="statistic-gmgn-detail-value">${holder.balance}</span>
                            <span class="statistic-gmgn-detail-label">持仓占比:</span>
                            <span class="statistic-gmgn-detail-value statistic-gmgn-value-highlight">${holder.amountPercentage}</span>
                            <span class="statistic-gmgn-detail-label">筹码已卖:</span>
                            <span class="statistic-gmgn-detail-value" style="color: ${holder.sellPercentage === '0.00%' ? '#00ff88' : '#ff6b35'}; font-weight: bold;">${holder.sellPercentage}</span>
                            <span class="statistic-gmgn-detail-label">净流入:</span>
                            <span class="statistic-gmgn-detail-value ${holder.netflowClass}">$${holder.netflowUsd}</span>
                            <span class="statistic-gmgn-detail-label">盈亏:</span>
                            <span class="statistic-gmgn-detail-value ${holder.profitClass}">${holder.profitSign}$${holder.profit}</span>
                            <span class="statistic-gmgn-detail-label">倍数:</span>
                            <span class="statistic-gmgn-detail-value ${holder.profitChangeClass}">${holder.profitChange}</span>
                            ${holder.solBalance ? `
                            <span class="statistic-gmgn-detail-label">SOL餘額:</span>
                            <span class="statistic-gmgn-detail-value statistic-gmgn-value-highlight">${holder.solBalance}</span>
                            ` : ''}
                            </div>
                </div>
            </div>
        `;

            // 添加地址复制功能
            const addressElement = item.querySelector('.statistic-gmgn-result-address');
            addressElement.addEventListener('click', () => {
                navigator.clipboard.writeText(holder.address).then(() => {
                    addressElement.style.backgroundColor = '#16a34a';
                    addressElement.style.color = 'white';
                    setTimeout(() => {
                        addressElement.style.backgroundColor = '';
                        addressElement.style.color = '';
                    }, 1000);
                });
            });

            resultsList.appendChild(item);
        });

        // ESC键关闭处理函数
        const escKeyHandler = (e) => {
            if (e.key === 'Escape') {
                document.body.removeChild(modal);
                document.removeEventListener('keydown', escKeyHandler);
            }
        };
        document.addEventListener('keydown', escKeyHandler);

        // 5. 绑定导出Excel按钮事件
        const exportBtn = modal.querySelector('#statistic-export-excel-btn');
        if (exportBtn) {
            exportBtn.addEventListener('click', () => {
                exportToExcel(processedData, title, caAddress, showSolBalance);
            });
        }

        // 6. 绑定关闭按钮事件
        modal.querySelector('.statistic-gmgn-modal-close').addEventListener('click', () => {
            document.body.removeChild(modal);
            document.removeEventListener('keydown', escKeyHandler);
        });

        // 点击模态框外部关闭
        modal.addEventListener('click', (e) => {
            if (e.target === modal) {
                document.body.removeChild(modal);
                document.removeEventListener('keydown', escKeyHandler);
            }
        });
    }





    // 数字格式化函数
    function formatNumber(num) {
        if (num === null || num === undefined) return 'N/A';

        // 處理負數:保留負號,對絕對值進行格式化
        const isNegative = num < 0;
        const absNum = Math.abs(num);

        let formatted;
        if (absNum >= 1000000000) {
            formatted = (absNum / 1000000000).toFixed(2) + 'B';
        } else if (absNum >= 1000000) {
            formatted = (absNum / 1000000).toFixed(2) + 'M';
        } else if (absNum >= 1000) {
            formatted = (absNum / 1000).toFixed(2) + 'K';
        } else {
            formatted = absNum.toFixed(2);
        }

        return isNegative ? '-' + formatted : formatted;
    }

    // Excel导出功能
    function exportToExcel(data, title, caAddress, showSolBalance) {
        try {
            // 创建工作表数据
            const worksheetData = [];

            // 添加标题行
            const headers = ['排名', '地址', '持仓数量', '持仓占比', '筹码已卖', 'USD价值', '净流入USD', '盈亏USD', '盈亏倍数'];
            if (showSolBalance) {
                headers.push('SOL餘額');
            }
            worksheetData.push(headers);

            // 添加数据行
            data.forEach((holder, index) => {
                const row = [
                    holder.rank,
                    holder.address,
                    holder.balance,
                    holder.amountPercentage,
                    holder.sellPercentage,
                    holder.usdValue,
                    holder.netflowUsd,
                    (holder.profitSign || '') + holder.profit,
                    holder.profitChange
                ];

                if (showSolBalance) {
                    row.push(holder.solBalance || 'N/A');
                }

                worksheetData.push(row);
            });

            // 创建工作簿
            const wb = XLSX.utils.book_new();
            const ws = XLSX.utils.aoa_to_sheet(worksheetData);

            // 设置列宽
            const colWidths = [
                {wch: 6},   // 排名
                {wch: 45},  // 地址
                {wch: 15},  // 持仓数量
                {wch: 10},  // 持仓比例
                {wch: 10},  // 已卖比例
                {wch: 15},  // USD价值
                {wch: 15},  // 净流入
                {wch: 15},  // 盈亏
                {wch: 12}   // 倍数
            ];
            if (showSolBalance) {
                colWidths.push({wch: 12}); // SOL餘額
            }
            ws['!cols'] = colWidths;

            // 添加工作表到工作簿
            XLSX.utils.book_append_sheet(wb, ws, title);

            // 生成文件名
            const timestamp = new Date().toISOString().slice(0, 19).replace(/:/g, '-');
            const fileName = `${title}_${caAddress ? caAddress.slice(0, 8) : 'data'}_${timestamp}.xlsx`;

            // 下载文件
            XLSX.writeFile(wb, fileName);

            // 显示成功提示
            const exportBtn = document.querySelector('#statistic-export-excel-btn');
            if (exportBtn) {
                const originalText = exportBtn.textContent;
                exportBtn.textContent = '✅ 导出成功';
                exportBtn.style.backgroundColor = '#059669';
                setTimeout(() => {
                    exportBtn.textContent = originalText;
                    exportBtn.style.backgroundColor = '';
                }, 2000);
            }

        } catch (error) {
            console.error('Excel导出失败:', error);
            alert('导出失败,请检查浏览器控制台了解详情');
        }
    }

    // 根据类型获取对应的地址数据
    function getAddressByType(type) {
        if (!interceptedData?.data?.list) return [];

        const currentTime = Math.floor(Date.now() / 1000);
        const sevenDaysInSeconds = 7 * 24 * 60 * 60;
        const holders = interceptedData.data.list;

        switch(type) {
            case 'fullPosition':
                return holders.filter(h =>
                    h.sell_amount_percentage === 0 &&
                    (!h.token_transfer_out || !h.token_transfer_out.address)
                );
            case 'profitable':
                return holders.filter(h => h.profit > 0);
            case 'losing':
                return holders.filter(h => h.profit < 0);
            case 'active24h':
                return holders.filter(h => h.last_active_timestamp > currentTime - 86400);
            case 'diamondHands':
                return holders.filter(h => h.maker_token_tags?.includes('diamond_hands'));
            case 'newAddress':
                return holders.filter(h => h.tags?.includes('fresh_wallet'));
            case 'holdingLessThan7Days':
                return holders.filter(h =>
                    h.start_holding_at &&
                    (currentTime - h.start_holding_at) < sevenDaysInSeconds
                );
            case 'highProfit':
                return holders.filter(h => h.profit_change > 5);
            case 'suspicious':
                return holders.filter(h =>
                    h.is_suspicious ||
                    (h.maker_token_tags && (
                        h.maker_token_tags.includes('rat_trader') ||
                        h.maker_token_tags.includes('transfer_in')
                    ))
                );
            case 'lowSolBalance':
                return holders.filter(h =>
                    h.native_balance && (h.native_balance / 1000000000) < 1
                );
            case 'tokenTransferIn':
                return holders.filter(h =>
                    h.token_transfer_in && h.token_transfer_in.address && h.token_transfer_in.address.trim() !== ''
                );
            case 'exchangeAddresses':
                return holders.filter(h => isExchangeAddress(h));
            default:
                return [];
        }
    }

    // 获取类型对应的中文标题
    function getTypeTitle(type) {
        const titles = {
            'fullPosition': '满仓地址',
            'profitable': '盈利地址',
            'losing': '亏损地址',
            'active24h': '24小时活跃地址',
            'diamondHands': '钻石手地址',
            'newAddress': '新地址',
            'holdingLessThan7Days': '持仓小于7天的地址',
            'highProfit': '5倍以上盈利地址',
            'suspicious': '可疑地址',
            'lowSolBalance': 'SOL餘額不足1的地址',
            'tokenTransferIn': '代币转入地址',
            'exchangeAddresses': '交易所地址'
        };
        return titles[type] || '未知类型';
    }

    // 1. 拦截 fetch 请求
    const originalFetch = window.fetch;
    window.fetch = function(url, options) {
        if (isTargetApi(url)) {
            console.log('[拦截] fetch 请求:', url);
            return originalFetch.apply(this, arguments)
                .then(response => {
                if (response.ok) {
                    processResponse(response.clone());
                }
                return response;
            });
        }
        return originalFetch.apply(this, arguments);
    };

    // 2. 拦截 XMLHttpRequest
    const originalXHR = window.XMLHttpRequest;
    window.XMLHttpRequest = function() {
        const xhr = new originalXHR();
        const originalOpen = xhr.open;
        xhr.open = function(method, url) {
            if (isTargetApi(url)) {
                console.log('[拦截] XHR 请求:', url);
                const originalOnload = xhr.onload;
                xhr.onload = function() {
                    if (xhr.readyState === 4 && xhr.status === 200) {
                        processResponse(xhr.responseText);
                    }
                    originalOnload?.apply(this, arguments);
                };
            }
            return originalOpen.apply(this, arguments);
        };
        return xhr;
    };

    function isTargetApi(url) {
        if (typeof url !== 'string') return false;

        // 检查是否是token_holders API且包含limit参数
        const isTokenHoldersApi = /vas\/api\/v1\/token_holders\/(sol|eth|base|bsc|tron)(\/|$|\?)/i.test(url);
        const hasLimitParam = /[?&]limit=/i.test(url);

        const isTarget = isTokenHoldersApi && hasLimitParam;

        if (isTarget) {
            // 从URL中提取CA地址
            const match = url.match(/vas\/api\/v1\/token_holders\/sol\/([^/?]+)/i);
            console.log('匹配的ca:',match)
            console.log('包含limit参数的URL:', url)
            if (match && match[1]) {
                currentCaAddress = match[1];
            }
        }
        return isTarget;
    }

    function processResponse(response) {
        console.log('开始处理响应数据');

        try {
            const dataPromise = typeof response === 'string' ?
                  Promise.resolve(JSON.parse(response)) :
            response.json();

            dataPromise.then(data => {
                interceptedData = data;
                console.log('[成功] 拦截到数据量:', data.data?.list?.length);
                console.log('[成功] 拦截到数据:',data);

                const currentStats = calculateStats();
                if (isFirstLoad) {
                    // 首次加载,记录初始数据和CA地址
                    initialStats = currentStats;
                    initialCaAddress = currentCaAddress;
                    isFirstLoad = false;
                    updateStatsDisplay(currentStats, true);
                } else {
                    // 非首次加载,比较CA地址
                    const isSameCa = currentCaAddress === initialCaAddress;
                    updateStatsDisplay(currentStats, !isSameCa);

                    // 如果CA地址不同,更新初始数据为当前数据
                    if (!isSameCa) {
                        initialStats = currentStats;
                        initialCaAddress = currentCaAddress;
                    }
                }
            }).catch(e => console.error('解析失败:', e));
        } catch (e) {
            console.error('处理响应错误:', e);
        }
    }


    // 3. 计算所有统计指标
    function calculateStats() {
        if (!interceptedData?.data?.list) return null;

        const currentTime = Math.floor(Date.now() / 1000);
        const sevenDaysInSeconds = 7 * 24 * 60 * 60; // 7天的秒数
        const holders = interceptedData.data.list;
        const stats = {
            fullPosition: 0,    // 全仓
            profitable: 0,      // 盈利
            losing: 0,         // 亏损
            active24h: 0,      // 24h活跃
            diamondHands: 0,   // 钻石手
            newAddress: 0,     // 新地址
            highProfit: 0,     // 10x盈利
            suspicious: 0,     // 新增:可疑地址
            holdingLessThan7Days: 0, // 新增:持仓小于7天
            lowSolBalance: 0,   // 新增:SOL餘額小於1的地址
            tokenTransferIn: 0, // 新增:代币转入地址数
            exchangeAddresses: 0 // 新增:交易所地址数
        };

        holders.forEach(holder => {
                // 满判断条件:1.没有卖出;2.没有出货地址
            if (holder.sell_amount_percentage === 0 &&
                (!holder.token_transfer_out || !holder.token_transfer_out.address)) {
                stats.fullPosition++;
            }
            if (holder.profit > 0) stats.profitable++;
            if (holder.profit < 0) stats.losing++;
            if (holder.last_active_timestamp > currentTime - 86400) stats.active24h++;
            if (holder.maker_token_tags?.includes('diamond_hands')) stats.diamondHands++;
            if (holder.tags?.includes('fresh_wallet')) stats.newAddress++;
            if (holder.profit_change > 5) stats.highProfit++;
            // 增强版可疑地址检测
            if (
                holder.is_suspicious ||
                (holder.maker_token_tags && (
                    holder.maker_token_tags.includes('rat_trader') ||
                    holder.maker_token_tags.includes('transfer_in')
                ))
            ) {
                stats.suspicious++;
            }
            // 新增7天持仓统计
            if (holder.start_holding_at &&
                (currentTime - holder.start_holding_at) < sevenDaysInSeconds) {
                stats.holdingLessThan7Days++;
            }
            // 新增低SOL餘額統計(小於1 SOL)
            if (holder.native_balance && (holder.native_balance / 1000000000) < 1) {
                stats.lowSolBalance++;
            }
            // 新增代币转入地址统计
            if (holder.token_transfer_in && holder.token_transfer_in.address && holder.token_transfer_in.address.trim() !== '') {
                stats.tokenTransferIn++;
            }
            // 新增交易所地址统计
            if (isExchangeAddress(holder)) {
                stats.exchangeAddresses++;
            }
        });
        return stats;
    }

    // 1. 持久化容器监听
    const observer = new MutationObserver(() => {
        const targetContainer = document.querySelector('.flex.overflow-x-auto.overflow-y-hidden.scroll-smooth.w-full');
        if (targetContainer && !targetContainer.querySelector('#statistic-gmgn-stats-item')) {
            injectStatsItem(targetContainer);
        }
    });

    function injectStatsItem(container) {
        if (container.querySelector('#statistic-gmgn-stats-item')) return;

        const isSol = isSolNetwork();
        const statsItem = document.createElement('div');
        statsItem.id = 'statistic-gmgn-stats-item';
        statsItem.className = 'statistic-gmgn-stats-container';

        const headerClass = isSol ? 'statistic-gmgn-stats-header sol-network' : 'statistic-gmgn-stats-header';
        const dataClass = isSol ? 'statistic-gmgn-stats-data sol-network' : 'statistic-gmgn-stats-data';

        statsItem.innerHTML = `
        <div class="${headerClass}">
    <span title="持有代币且未卖出任何数量的地址(排除转移代币卖出的地址)">满仓</span>
    <span title="当前持仓价值高于买入成本的地址">盈利</span>
    <span title="当前持仓价值低于买入成本的地址">亏损</span>
    <span title="过去24小时内有交易活动的地址">活跃</span>
    <span title="长期持有且很少卖出的地址">钻石</span>
    <span title="新钱包">新址</span>
    <span title="持仓时间小于7天的地址">7天</span>
    <span title="盈利超过5倍的地址">5X</span>
    <span title="标记为可疑或异常行为的地址">可疑</span>
    <span title="有代币转入记录的地址">转入</span>
    <span title="与交易所相关的地址">交易所</span>
    ${isSol ? '<span title="SOL餘額小於1的地址">低SOL</span>' : ''}
        </div>
        <div class="${dataClass}">
            <span id="fullPosition">-</span>
            <span id="profitable">-</span>
            <span id="losing">-</span>
            <span id="active24h">-</span>
            <span id="diamondHands">-</span>
            <span id="newAddress">-</span>
            <span id="holdingLessThan7Days">-</span>
            <span id="highProfit">-</span>
            <span id="suspicious">-</span>
            <span id="tokenTransferIn">-</span>
            <span id="exchangeAddresses">-</span>
            ${isSol ? '<span id="lowSolBalance">-</span>' : ''}
        </div>
    `;
        container.insertAdjacentElement('afterbegin', statsItem);
    }

    function updateStatsDisplay(currentStats, forceNoArrows) {
        if (!currentStats) return;

        // 确保DOM已存在
        if (!document.getElementById('statistic-gmgn-stats-item')) {
            injectStatsItem();
        }

        const updateStatElement = (id, value, hasChanged, isIncrease) => {
            const element = document.getElementById(id);
            if (!element) return;

            element.innerHTML = `<strong style="color: ${id === 'profitable' ? '#2E8B57' :
            (id === 'losing' || id === 'suspicious' ? '#FF1493' :
             id === 'holdingLessThan7Days' ? '#00E5EE' :
             id === 'lowSolBalance' ? '#FFA500' : '#e9ecef')}">${value}</strong>`;

            // 只有当不是强制不显示箭头且确实有变化时才显示箭头
            if (!forceNoArrows && hasChanged) {
                const arrow = document.createElement('span');
                arrow.className = isIncrease ? 'statistic-up-arrow' : 'statistic-down-arrow';
                arrow.textContent = isIncrease ? '▲' : '▼';

                // 移除旧的箭头(如果有)
                const oldArrow = element.querySelector('.statistic-up-arrow, .statistic-down-arrow');
                if (oldArrow) oldArrow.remove();

                element.appendChild(arrow);
            } else {
                // 没有变化或强制不显示箭头,移除箭头(如果有)
                const oldArrow = element.querySelector('.statistic-up-arrow, .statistic-down-arrow');
                if (oldArrow) oldArrow.remove();
            }

            // 为所有统计类型添加点击事件监听器
            const baseClickableTypes = ['fullPosition', 'profitable', 'losing', 'active24h', 'diamondHands', 'newAddress', 'holdingLessThan7Days', 'highProfit', 'suspicious', 'tokenTransferIn', 'exchangeAddresses'];
            const clickableTypes = isSolNetwork() ? [...baseClickableTypes, 'lowSolBalance'] : baseClickableTypes;

            if (clickableTypes.includes(id)) {
                element.classList.add('clickable');
                element.onclick = (e) => {
                    e.preventDefault();
                    e.stopPropagation();
                    const addresses = getAddressByType(id);

                    // 交易所地址使用专用弹框
                    if (id === 'exchangeAddresses') {
                        createExchangeModal(addresses, currentCaAddress);
                    } else {
                        const title = getTypeTitle(id);
                        const showSolBalance = id === 'lowSolBalance';
                        createModal(title, addresses, currentCaAddress, showSolBalance);
                    }
                };
            } else {
                // 其他类型移除点击样式和事件
                element.classList.remove('clickable');
                element.onclick = null;
            }
        };
        // 更新各个统计指标
            // 新增7天持仓统计更新
        updateStatElement('holdingLessThan7Days', currentStats.holdingLessThan7Days,
                          initialStats && currentStats.holdingLessThan7Days !== initialStats.holdingLessThan7Days,
                          initialStats && currentStats.holdingLessThan7Days > initialStats.holdingLessThan7Days);

        updateStatElement('fullPosition', currentStats.fullPosition,
                          initialStats && currentStats.fullPosition !== initialStats.fullPosition,
                          initialStats && currentStats.fullPosition > initialStats.fullPosition);

        updateStatElement('profitable', currentStats.profitable,
                          initialStats && currentStats.profitable !== initialStats.profitable,
                          initialStats && currentStats.profitable > initialStats.profitable);
        updateStatElement('losing', currentStats.losing,
                          currentStats.losing !== initialStats.losing,
                          currentStats.losing > initialStats.losing);

        updateStatElement('active24h', currentStats.active24h,
                          currentStats.active24h !== initialStats.active24h,
                          currentStats.active24h > initialStats.active24h);

        updateStatElement('diamondHands', currentStats.diamondHands,
                          currentStats.diamondHands !== initialStats.diamondHands,
                          currentStats.diamondHands > initialStats.diamondHands);

        updateStatElement('newAddress', currentStats.newAddress,
                          currentStats.newAddress !== initialStats.newAddress,
                          currentStats.newAddress > initialStats.newAddress);

        updateStatElement('highProfit', currentStats.highProfit,
                          currentStats.highProfit !== initialStats.highProfit,
                          currentStats.highProfit > initialStats.highProfit);

        updateStatElement('suspicious', currentStats.suspicious,
                          currentStats.suspicious !== initialStats.suspicious,
                          currentStats.suspicious > initialStats.suspicious);

        updateStatElement('tokenTransferIn', currentStats.tokenTransferIn,
                          initialStats && currentStats.tokenTransferIn !== initialStats.tokenTransferIn,
                          initialStats && currentStats.tokenTransferIn > initialStats.tokenTransferIn);

        updateStatElement('exchangeAddresses', currentStats.exchangeAddresses,
                          initialStats && currentStats.exchangeAddresses !== initialStats.exchangeAddresses,
                          initialStats && currentStats.exchangeAddresses > initialStats.exchangeAddresses);

        // 只在SOL网络时更新低SOL余额统计
        if (isSolNetwork()) {
            updateStatElement('lowSolBalance', currentStats.lowSolBalance,
                              initialStats && currentStats.lowSolBalance !== initialStats.lowSolBalance,
                              initialStats && currentStats.lowSolBalance > initialStats.lowSolBalance);
        }
    }

    // 4. 初始化
    if (document.readyState === 'complete') {
        startObserving();
    } else {
        window.addEventListener('DOMContentLoaded', startObserving);
    }

    function startObserving() {
        // 立即检查一次
        const initialContainer = document.querySelector('.flex.overflow-x-auto.overflow-y-hidden.scroll-smooth.w-full');
        if (initialContainer) injectStatsItem(initialContainer);

        // 持续监听DOM变化
        observer.observe(document.body, {
            childList: true,
            subtree: true,
            attributes: false
        });
    }
})();