Skip to content

lookteas/eth-tracker

Repository files navigation

ETH Tracker

以太坊交易跟踪器 - 一个高性能的以太坊区块链交易监控和历史数据扫描系统。

🏗️ 系统架构

graph TB
    subgraph "外部服务"
        ETH[以太坊节点<br/>RPC服务]
        DB[(MySQL数据库)]
    end
    
    subgraph "ETH Tracker 系统"
        subgraph "API层"
            HTTP[HTTP服务器<br/>:8081]
            SWAGGER[Swagger文档<br/>/swagger/index.html]
        end
        
        subgraph "业务逻辑层"
            TH[交易处理器<br/>TransactionHandler]
            HH[健康检查处理器<br/>HealthHandler]
        end
        
        subgraph "核心服务层"
            SYNC[实时同步器<br/>Synchronizer]
            SCANNER[历史扫描器<br/>HistoryScanner]
            REPO[数据仓库<br/>Repository]
        end
        
        subgraph "基础设施层"
            CONFIG[配置管理<br/>Config]
            LOGGER[日志系统<br/>Zap Logger]
            CLIENT[以太坊客户端<br/>go-ethereum]
        end
    end
    
    subgraph "用户接口"
        USER[用户/客户端]
        CURL[curl命令]
        BROWSER[浏览器]
    end
    
    %% 连接关系
    USER --> HTTP
    CURL --> HTTP
    BROWSER --> SWAGGER
    
    HTTP --> TH
    HTTP --> HH
    SWAGGER --> HTTP
    
    TH --> SYNC
    TH --> SCANNER
    TH --> REPO
    
    SYNC --> CLIENT
    SCANNER --> CLIENT
    REPO --> DB
    
    CLIENT --> ETH
    
    CONFIG --> SYNC
    CONFIG --> SCANNER
    CONFIG --> HTTP
    
    LOGGER --> TH
    LOGGER --> SYNC
    LOGGER --> SCANNER
    
    %% 样式
    classDef external fill:#e1f5fe
    classDef api fill:#f3e5f5
    classDef business fill:#e8f5e8
    classDef core fill:#fff3e0
    classDef infra fill:#fce4ec
    classDef user fill:#f1f8e9
    
    class ETH,DB external
    class HTTP,SWAGGER api
    class TH,HH business
    class SYNC,SCANNER,REPO core
    class CONFIG,LOGGER,CLIENT infra
    class USER,CURL,BROWSER user
Loading

🚀 快速启动

本地开发环境

前置要求

  • Go 1.24+
  • MySQL 8.0+
  • 以太坊节点访问权限(Infura、Alchemy等)

步骤

  1. 克隆项目
git clone <repository-url>
cd eth-tracker
  1. 安装依赖
go mod download
  1. 配置数据库
# 创建数据库
mysql -u root -p -e "CREATE DATABASE eth_tracker;"

# 运行数据库迁移
go run ./cmd/migrate -config ./configs/config.yaml
  1. 配置文件
# 复制配置模板
cp configs/config.yaml.example configs/config.yaml

# 编辑配置文件,设置数据库连接和RPC端点
vim configs/config.yaml
  1. 启动服务
go run ./cmd/server -config ./configs/config.yaml
  1. 验证服务
# 健康检查
curl http://localhost:8081/api/v1/health

# 访问Swagger文档
open http://localhost:8081/swagger/index.html

Docker 部署

使用 Docker Compose(推荐)

  1. 克隆项目
git clone <repository-url>
cd eth-tracker
  1. 配置环境变量
# 复制环境变量模板
cp .env.example .env

# 编辑环境变量
vim .env
  1. 启动服务
# 启动所有服务(包括MySQL)
docker-compose up -d

# 查看日志
docker-compose logs -f eth-tracker
  1. 验证部署
# 健康检查
curl http://localhost:8081/api/v1/health

# 访问Swagger文档
open http://localhost:8081/swagger/index.html

单独使用 Docker

# 构建镜像
docker build -t eth-tracker .

# 运行容器
docker run -d \
  --name eth-tracker \
  -p 8081:8081 \
  -e DB_HOST=your-mysql-host \
  -e DB_USER=your-mysql-user \
  -e DB_PASSWORD=your-mysql-password \
  -e MAINNET_RPC_URL=your-mainnet-rpc-url \
  eth-tracker

⚙️ 配置项说明

配置项 类型 默认值 说明
数据库配置
database.host string localhost MySQL主机地址
database.port int 3306 MySQL端口
database.user string root MySQL用户名
database.password string - MySQL密码
database.name string eth_tracker 数据库名称
database.max_open_conns int 25 最大连接数
database.max_idle_conns int 5 最大空闲连接数
database.conn_max_lifetime int 300 连接最大生存时间(秒)
服务器配置
server.host string 0.0.0.0 服务器监听地址
server.port int 8081 服务器端口
server.read_timeout int 30 读取超时时间(秒)
server.write_timeout int 30 写入超时时间(秒)
server.cors.enabled bool true 是否启用CORS
server.cors.allowed_origins []string ["*"] 允许的源
server.swagger.enabled bool true 是否启用Swagger
网络配置
networks.mainnet.rpc_url string - 主网RPC地址
networks.mainnet.start_block int 0 开始同步的区块号
networks.mainnet.chain_id int 1 链ID
networks.mainnet.confirmation_blocks int 12 确认区块数
networks.sepolia.rpc_url string - Sepolia测试网RPC地址
networks.sepolia.start_block int 0 开始同步的区块号
networks.sepolia.chain_id int 11155111 链ID
网络映射配置
network_mapping.id_to_name.1 string mainnet 网络ID 1 对应的网络名称
network_mapping.id_to_name.2 string sepolia 网络ID 2 对应的网络名称
network_mapping.id_to_name.3 string polygon 网络ID 3 对应的网络名称
network_mapping.id_to_name.4 string mumbai 网络ID 4 对应的网络名称
network_mapping.default_network string mainnet 无效网络ID时的默认网络
同步配置
sync.batch_size int 100 批处理大小
sync.worker_count int 5 工作协程数
sync.block_interval int 3 区块同步间隔(秒)
日志配置
log.level string info 日志级别
log.format string json 日志格式
log.output string stdout 日志输出

🌍 环境变量覆盖

系统支持通过环境变量覆盖配置文件中的设置:

数据库配置

export DB_HOST=localhost
export DB_PORT=3306
export DB_USER=eth_tracker
export DB_PASSWORD=your_secure_password
export DB_NAME=eth_tracker
export DB_MAX_OPEN_CONNS=25
export DB_MAX_IDLE_CONNS=5
export DB_CONN_MAX_LIFETIME=300

服务器配置

export SERVER_HOST=0.0.0.0
export SERVER_PORT=8081
export SERVER_READ_TIMEOUT=30
export SERVER_WRITE_TIMEOUT=30
export CORS_ENABLED=true
export SWAGGER_ENABLED=true

网络配置

# 主网配置
export MAINNET_RPC_URL=https://mainnet.infura.io/v3/your-project-id
export MAINNET_START_BLOCK=18000000
export MAINNET_CHAIN_ID=1
export MAINNET_CONFIRMATION_BLOCKS=12

# Sepolia测试网配置
export SEPOLIA_RPC_URL=https://sepolia.infura.io/v3/your-project-id
export SEPOLIA_START_BLOCK=4000000
export SEPOLIA_CHAIN_ID=11155111
export SEPOLIA_CONFIRMATION_BLOCKS=3

# Polygon配置
export POLYGON_RPC_URL=https://polygon-mainnet.infura.io/v3/your-project-id
export POLYGON_START_BLOCK=45000000
export POLYGON_CHAIN_ID=137

# Mumbai测试网配置
export MUMBAI_RPC_URL=https://polygon-mumbai.infura.io/v3/your-project-id
export MUMBAI_START_BLOCK=35000000
export MUMBAI_CHAIN_ID=80001

同步配置

export SYNC_BATCH_SIZE=100
export SYNC_WORKER_COUNT=5
export SYNC_BLOCK_INTERVAL=3

日志配置

export LOG_LEVEL=info
export LOG_FORMAT=json
export LOG_OUTPUT=stdout

网络映射配置说明

网络映射功能允许API同时支持网络名称和网络ID作为参数,提供更灵活的使用方式:

  • mainnet (主网) → ID: 1
  • sepolia (Sepolia测试网) → ID: 2
  • polygon (Polygon主网) → ID: 3
  • mumbai (Mumbai测试网) → ID: 4

在API调用中,您可以使用网络名称(如 network=sepolia)或对应的网络ID(如 network=2),两种方式完全等价。

Docker Compose 环境变量示例

# .env 文件
DB_HOST=mysql
DB_PORT=3306
DB_USER=eth_tracker
DB_PASSWORD=secure_password_123
DB_NAME=eth_tracker

SERVER_PORT=8081
SWAGGER_ENABLED=true

MAINNET_RPC_URL=https://mainnet.infura.io/v3/your-project-id
SEPOLIA_RPC_URL=https://sepolia.infura.io/v3/your-project-id

LOG_LEVEL=info
SYNC_BATCH_SIZE=50
SYNC_WORKER_COUNT=3

📋 API 错误码

HTTP状态码 错误代码 说明 示例
400 Bad Request
400 missing_address 地址参数缺失 {"error": "missing_address", "message": "地址参数不能为空"}
400 invalid_address 地址格式无效 {"error": "invalid_address", "message": "无效的地址格式"}
400 missing_scan_id 扫描ID参数缺失 {"error": "missing_scan_id", "message": "扫描ID参数不能为空"}
400 invalid_request 请求参数无效 {"error": "invalid_request", "message": "请求参数无效"}
400 invalid_page_size 分页参数无效 {"error": "invalid_page_size", "message": "页面大小必须在1-100之间"}
404 Not Found
404 scan_not_found 扫描任务未找到 {"error": "scan_not_found", "message": "未找到扫描任务"}
404 network_not_found 网络配置未找到 {"error": "network_not_found", "message": "网络配置未找到"}
404 address_not_found 地址未找到交易记录 {"error": "address_not_found", "message": "该地址暂无交易记录"}
409 Conflict
409 scan_already_exists 扫描任务已存在 {"error": "scan_already_exists", "message": "该地址已有正在进行的扫描任务"}
409 scan_already_running 扫描任务正在运行 {"error": "scan_already_running", "message": "扫描任务正在运行中"}
500 Internal Server Error
500 internal_error 内部服务器错误 {"error": "internal_error", "message": "服务器内部错误"}
500 database_error 数据库错误 {"error": "database_error", "message": "数据库操作失败"}
500 rpc_error RPC连接错误 {"error": "rpc_error", "message": "以太坊节点连接失败"}
500 scan_start_failed 扫描启动失败 {"error": "scan_start_failed", "message": "扫描启动失败"}

错误响应格式

{
  "error": "error_code",
  "message": "详细错误描述"
}

🔧 API 使用示例

1. 健康检查

# 检查服务状态
curl -X GET "http://localhost:8081/api/v1/health" \
  -H "accept: application/json"

# 响应示例
{
  "status": "healthy",
  "timestamp": "2024-01-15T10:30:00Z",
  "version": "1.0.0",
  "uptime": "2h30m15s"
}

2. 获取最新交易列表

# 获取最新交易(默认20条)
curl -X GET "http://localhost:8081/api/v1/transactions" \
  -H "accept: application/json"

# 分页获取交易
curl -X GET "http://localhost:8081/api/v1/transactions?page=2&size=50" \
  -H "accept: application/json"

# 响应示例
{
  "data": [
    {
      "id": 12345,
      "hash": "0x1234567890abcdef...",
      "block_number": 18500000,
      "block_hash": "0xabcdef1234567890...",
      "transaction_index": 45,
      "from": "0x742d35Cc6634C0532925a3b8D4C9db96C4C4C4C4",
      "to": "0x8ba1f109551bD432803012645Hac136c22C501e5",
      "value": "1000000000000000000",
      "gas": 21000,
      "gas_price": "20000000000",
      "gas_used": 21000,
      "status": 1,
      "network": "mainnet",
      "created_at": "2024-01-15T10:25:30Z"
    }
  ],
  "total": 1500,
  "page": 1,
  "size": 20,
  "total_pages": 75
}

3. 根据地址获取交易

# 获取指定地址的交易记录
curl -X GET "http://localhost:8081/api/v1/transactions/0x742d35Cc6634C0532925a3b8D4C9db96C4C4C4C4" \
  -H "accept: application/json"

# 分页获取地址交易
curl -X GET "http://localhost:8081/api/v1/transactions/0x742d35Cc6634C0532925a3b8D4C9db96C4C4C4C4?page=1&size=10" \
  -H "accept: application/json"

# 指定网络获取地址交易(使用网络名称)
curl -X GET "http://localhost:8081/api/v1/transactions/0x742d35Cc6634C0532925a3b8D4C9db96C4C4C4C4?network=sepolia" \
  -H "accept: application/json"

# 指定网络获取地址交易(使用网络ID)
curl -X GET "http://localhost:8081/api/v1/transactions/0x742d35Cc6634C0532925a3b8D4C9db96C4C4C4C4?network=2" \
  -H "accept: application/json"

# 响应格式同上

4. 获取地址交易统计

# 获取地址统计信息
curl -X GET "http://localhost:8081/api/v1/transactions/0x742d35Cc6634C0532925a3b8D4C9db96C4C4C4C4/stats" \
  -H "accept: application/json"

# 指定网络的统计(使用网络名称)
curl -X GET "http://localhost:8081/api/v1/transactions/0x742d35Cc6634C0532925a3b8D4C9db96C4C4C4C4/stats?network=sepolia" \
  -H "accept: application/json"

# 指定网络的统计(使用网络ID)
curl -X GET "http://localhost:8081/api/v1/transactions/0x742d35Cc6634C0532925a3b8D4C9db96C4C4C4C4/stats?network=2" \
  -H "accept: application/json"

# 响应示例
{
  "address": "0x742d35Cc6634C0532925a3b8D4C9db96C4C4C4C4",
  "network": "mainnet",
  "total_transactions": 156,
  "total_sent": 45,
  "total_received": 111,
  "first_transaction": "2023-06-15T08:30:00Z",
  "last_transaction": "2024-01-15T10:25:30Z",
  "first_block_number": 17500000,
  "last_block_number": 18500000
}

5. 启动历史交易扫描

# 启动历史扫描任务(使用网络名称)
curl -X POST "http://localhost:8081/api/v1/transactions/scan" \
  -H "accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "address": "0x742d35Cc6634C0532925a3b8D4C9db96C4C4C4C4",
    "network": "sepolia",
    "start_block": 5000000,
    "end_block": 5100000,
    "batch_size": 1000
  }'

# 启动历史扫描任务(使用网络ID)
curl -X POST "http://localhost:8081/api/v1/transactions/scan" \
  -H "accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "address": "0x742d35Cc6634C0532925a3b8D4C9db96C4C4C4C4",
    "network": "2",
    "start_block": 5000000,
    "end_block": 5100000,
    "batch_size": 1000
  }'

#### 使用地址路径启动历史扫描(查询参数)
```bash
# 通过地址路径 + 查询参数启动扫描(支持 network 名称或 ID)
curl -X POST "http://localhost:8081/api/v1/transactions/0x742d35Cc6634C0532925a3b8D4C9db96C4C4C4C4/scan?network=sepolia&start_block=5000000&end_block=5100000&batch_size=100" \
  -H "accept: application/json"

说明:batch_size 为每批处理的区块数量,默认 100;start_block 默认为 0,end_block 默认为最新区块。

# 响应示例
{
  "address": "0x742d35Cc6634C0532925a3b8D4C9db96C4C4C4C4",
  "network": "sepolia",
  "start_block": 5000000,
  "end_block": 5100000,
  "status": "running",
  "message": "扫描任务已启动"
}

6. 获取扫描进度

# 获取所有扫描任务进度
curl -X GET "http://localhost:8081/api/v1/transactions/scan-progress" \
  -H "accept: application/json"

# 获取特定扫描任务进度
curl -X GET "http://localhost:8081/api/v1/transactions/scan/scan_1728467905_abc123/progress" \
  -H "accept: application/json"

# 响应示例
{
  "id": "scan_1728467905_abc123",
  "address": "0x742d35Cc6634C0532925a3b8D4C9db96C4C4C4C4",
  "network": "sepolia",
  "start_block": 5000000,
  "end_block": 5100000,
  "current_block": 5050000,
  "total_blocks": 100000,
  "scanned_transactions": 1250,
  "status": "running",
  "progress": 50.0,
  "created_at": "2024-01-15T09:45:05Z",
  "updated_at": "2024-01-15T09:50:15Z"
}

7. 停止扫描任务

# 停止特定扫描任务
curl -X POST "http://localhost:8081/api/v1/transactions/scan/scan_1728467905_abc123/stop" \
  -H "accept: application/json"

# 停止地址相关的扫描任务
curl -X POST "http://localhost:8081/api/v1/transactions/0x742d35Cc6634C0532925a3b8D4C9db96C4C4C4C4/scan-stop" \
  -H "accept: application/json"

# 响应示例
{
  "success": true,
  "message": "扫描任务已停止"
}

8. 错误处理示例

# 无效地址格式
curl -X GET "http://localhost:8081/api/v1/transactions/invalid-address" \
  -H "accept: application/json"

# 错误响应
{
  "error": "invalid_address",
  "message": "无效的地址格式"
}

# 扫描任务不存在
curl -X GET "http://localhost:8081/api/v1/transactions/scan/nonexistent_scan_id/progress" \
  -H "accept: application/json"

# 错误响应
{
  "error": "scan_not_found",
  "message": "未找到扫描任务"
}

📚 更多信息

🤝 贡献

欢迎提交 Issue 和 Pull Request 来改进这个项目。

📄 许可证

本项目采用 MIT 许可证。详情请参阅 LICENSE 文件。

About

An eth tracker developed in Go

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages