TRON 区块链 USDT 交易查询程序

程序概述

这是一个用 Go 语言编写的程序,用于查询 TRON 区块链上特定钱包地址在指定时间范围内的 USDT 交易记录。程序通过调用 TRON Grid API 获取交易数据,并将结果格式化为易于使用的结构体。

功能特点

  • 查询指定 TRON 钱包地址的 USDT 交易记录
  • 支持按时间范围过滤交易
  • 自动处理 API 响应和错误
  • 格式化 USDT 金额显示

API 接口说明

程序使用 TRON Grid API 的以下接口:

https://api.trongrid.io/v1/accounts/{address}/transactions/trc20

主要查询参数:

  • contract_address: USDT 合约地址 (TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t)
  • limit: 返回的交易记录数量
  • only_confirmed: 是否只返回已确认的交易
  • min_block_timestamp: 查询的起始时间戳(毫秒)
  • max_block_timestamp: 查询的结束时间戳(毫秒)

数据结构

输出结构体

type TransferDetails struct {
    TokenAbbr     string   // 代币缩写,例如 "USDT"
    TransactionID string   // 交易ID(哈希值)
    Quant         float64  // 交易金额
    FromAddress   string   // 发送方地址
    ToAddress     string   // 接收方地址
    FinalResult   string   // API请求结果状态
}

API 响应解析结构体

type TokenInfo struct {
    Symbol   string `json:"symbol"`
    Address  string `json:"address"`
    Decimals int    `json:"decimals"`
    Name     string `json:"name"`
}

type TransactionData struct {
    TransactionID  string    `json:"transaction_id"`
    TokenInfo      TokenInfo `json:"token_info"`
    BlockTimestamp int64     `json:"block_timestamp"`
    From           string    `json:"from"`
    To             string    `json:"to"`
    Type           string    `json:"type"`
    Value          string    `json:"value"`
}

type Meta struct {
    At          int64             `json:"at"`
    Fingerprint string            `json:"fingerprint"`
    Links       map[string]string `json:"links"`
    PageSize    int               `json:"page_size"`
}

type ApiResponse struct {
    Data    []TransactionData `json:"data"`
    Success bool              `json:"success"`
    Meta    Meta              `json:"meta"`
}

主要函数说明

GetTransactions

func GetTransactions(toAddress string, startTime int64, endTime int64) (TransferDetails, error)

功能:查询指定钱包地址在给定时间范围内的 USDT 交易记录

参数

  • toAddress: 要查询的 TRON 钱包地址
  • startTime: 查询的起始时间戳(毫秒)
  • endTime: 查询的结束时间戳(毫秒)

返回值

  • TransferDetails: 包含交易详情的结构体
  • error: 如果查询过程中出现错误,返回相应的错误信息

处理流程

  1. 构造 API 请求 URL
  2. 发送 HTTP GET 请求
  3. 读取并解析响应数据
  4. 验证交易是否在指定时间范围内
  5. 提取并格式化交易信息

formatAmount

func formatAmount(quant string) float64

功能:将 API 返回的代币数量字符串转换为浮点数

参数

  • quant: 代表代币数量的字符串

返回值

  • float64: 格式化后的代币数量,保留两位小数

处理流程

  1. 将字符串转换为浮点数
  2. 除以 10^6(USDT 的精度因子)
  3. 四舍五入到两位小数

使用示例

func main() {
    // 示例用法:
    addr := "TXFchkPBXBkHGifcUdQdErhBzP5T6kRfyv"                        // 替换为您想查询的地址
    details, err := GetTransactions(addr, 1745337600000, 1745424000000) // 设置时间范围
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Printf("Transaction Details: %+v\n", details)
}

完整源代码

package main

import (
    "encoding/json"
    "fmt"
    "io"
    "log"
    "math"
    "net/http"
    "strconv"
)

func main() {
    // 示例用法:
    addr := "TXFchkPBXBkHGifcUdQdErhBzP5T6kRfyv"                        // 替换为您想查询的地址
    details, err := GetTransactions(addr, 1745337600000, 1745424000000) // startTime 和 endTime 暂时未使用
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Printf("Transaction Details: %+v\n", details)
}

type TransferDetails struct {
    TokenAbbr     string
    TransactionID string
    Quant         float64
    FromAddress   string
    ToAddress     string
    FinalResult   string // 可以用来表示 API 请求是否成功
}

// --- 为解析 JSON 响应定义的结构体 ---
type TokenInfo struct {
    Symbol   string `json:"symbol"`
    Address  string `json:"address"`
    Decimals int    `json:"decimals"`
    Name     string `json:"name"`
}

type TransactionData struct {
    TransactionID  string    `json:"transaction_id"`
    TokenInfo      TokenInfo `json:"token_info"`
    BlockTimestamp int64     `json:"block_timestamp"`
    From           string    `json:"from"`
    To             string    `json:"to"`
    Type           string    `json:"type"`
    Value          string    `json:"value"`
}

type Meta struct {
    At          int64             `json:"at"`
    Fingerprint string            `json:"fingerprint"`
    Links       map[string]string `json:"links"`
    PageSize    int               `json:"page_size"`
}

type ApiResponse struct {
    Data    []TransactionData `json:"data"`
    Success bool              `json:"success"`
    Meta    Meta              `json:"meta"`
}

// --- 结束 JSON 结构体定义 ---

// 传入钱包地址
// 注意:startTime 和 endTime 参数当前未在此函数实现中使用
func GetTransactions(toAddress string, startTime int64, endTime int64) (TransferDetails, error) {
    // --- 开始修改 GetTransactions 函数 ---
    details := TransferDetails{} // 初始化返回的结构体

    // 1. 构造请求 URL
    // 注意:这里硬编码了合约地址和 limit=1,根据需要可以将其作为参数传入
    contractAddress := "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t" // USDT TRC20 合约地址
    limit := 1
    min_timestamp := startTime
    max_timestamp := endTime

    apiURL := fmt.Sprintf("https://api.trongrid.io/v1/accounts/%s/transactions/trc20?contract_address=%s&limit=%d&only_confirmed=true&min_block_timestamp=%v&max_block_timestamp=%v",
        toAddress, contractAddress, limit, min_timestamp, max_timestamp)

    // 2. 发送 HTTP GET 请求
    resp, err := http.Get(apiURL)
    if err != nil {
        return details, fmt.Errorf("请求 API 失败: %w", err)
    }
    defer resp.Body.Close()

    // 3. 读取响应体
    body, err := io.ReadAll(resp.Body)
    if err != nil {
        return details, fmt.Errorf("读取响应体失败: %w", err)
    }

    // 检查 HTTP 状态码
    if resp.StatusCode != http.StatusOK {
        return details, fmt.Errorf("API 返回错误状态码 %d: %s", resp.StatusCode, string(body))
    }

    // 4. 解析 返回的JSON 数据到结构体
    var apiResponse ApiResponse
    err = json.Unmarshal(body, &apiResponse)
    if err != nil {
        return details, fmt.Errorf("解析 JSON 失败: %w", err)
    }

    // 5. 检查 API 返回是否成功以及是否有数据
    if !apiResponse.Success {
        details.FinalResult = "API request not successful"
        return details, fmt.Errorf("API 报告请求不成功")
    }
    details.FinalResult = "Success" // API 请求成功

    if len(apiResponse.Data) == 0 {
        details.FinalResult = "Success, but no transactions found"
        // 没有找到交易记录,返回空的 details 但没有错误
        return details, fmt.Errorf("没有找到交易记录")
    }
    // 检查block_timestamp    时间是否在指定范围内
    if (apiResponse.Data[0].BlockTimestamp > startTime && apiResponse.Data[0].BlockTimestamp < endTime) && (apiResponse.Data[0].To == toAddress) && (apiResponse.Data[0].TokenInfo.Symbol == "USDT") {

        // 6. 提取第一条交易记录的信息
        transaction := apiResponse.Data[0]

        /* // 7. 转换金额
        valueInt, err := strconv.ParseInt(transaction.Value, 10, 64)
        if err != nil {
            return details, fmt.Errorf("转换交易金额 '%s' 失败: %w", transaction.Value, err)
        }
        // 根据 decimals 计算实际数量
        divisor := math.Pow10(transaction.TokenInfo.Decimals)
        quant := float64(valueInt) / divisor */

        // 8. 填充 TransferDetails 结构体
        // 注意:这里假设 TokenInfo 中包含了 Token 的缩写(代币的缩写USDT)
        details.TokenAbbr = transaction.TokenInfo.Symbol
        // 注意:这里假设 TransactionID 是一个字符串(哈希值)
        details.TransactionID = transaction.TransactionID
        // 注意:这里假设 Quant 是一个浮点数(金额)
        details.Quant = formatAmount(transaction.Value)
        // 转账来源地址
        details.FromAddress = transaction.From
        // 转账目标地址
        details.ToAddress = transaction.To
        // FinalResult 已在前面设置

        return details, nil
        // --- 结束修改 GetTransactions 函数 ---
    } else {
        details.FinalResult = "Success, but no transactions found"
        // 没有找到交易记录,返回空的 details ,和时间不符的错误
        details.FinalResult = "Transaction timestamp not in specified range"
        return details, fmt.Errorf("交易时间戳 %d 不在指定范围内 [%d, %d]",
            apiResponse.Data[0].BlockTimestamp, startTime, endTime)
    }
}

func formatAmount(quant string) float64 {
    // 直接将字符串转为 float64 类型
    amount, err := strconv.ParseFloat(quant, 64)
    if err != nil {
        log.Printf("Error parsing amount: %v", err)
        return 0 // 如果转换失败,返回 0
    }

    // 使用 1e6 计算金额,转换为 float64 类型
    amountFloat := amount / 1e6 // 使用 1e6 来处理精度

    // 保留小数点后2位
    amountFloat = math.Round(amountFloat*100) / 100

    return amountFloat
}

注意事项

  1. 程序目前只返回符合条件的第一条交易记录(limit=1)
  2. 时间戳使用毫秒级 Unix 时间戳
  3. 程序会验证交易的接收地址是否与查询地址匹配
  4. 程序会验证代币类型是否为 USDT
  5. USDT 金额会自动按照 6 位精度进行转换

扩展建议

  1. 增加对多条交易记录的支持
  2. 添加对其他 TRC20 代币的支持
  3. 实现分页查询功能
  4. 添加更多过滤条件(如交易类型、金额范围等)
  5. 增加 API 密钥配置,以提高请求限制
每日更新-免费小火箭账号
不要错过任何机会,探索最新的应用和游戏,就在我们的平台。
立即访问
最后修改:2025 年 04 月 24 日
如果觉得我的文章对你有用,请随意赞赏