diff --git a/README.md b/README.md index e192c4e..fdfedce 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,25 @@ TRON USDT TRC20 收款监听服务 - 基于交易记录扫描 + 区块确认数 ## API 使用方式 ```go -// 创建监听器 -uman := usdtman.NewUSDTMan([]string{"地址1", "地址2"}, "API_KEY") +// 创建监听器(配置对象方式) +uman := usdtman.NewUSDTMan(usdtman.Config{ + Addresses: []string{"地址1", "地址2"}, + APIKey: "YOUR_API_KEY", + QueryInterval: 5 * time.Second, // 查询间隔(可选,默认 5 秒) + MinConfirmations: 6, // 最小确认数(可选,默认 6) + MaxHistoryTxns: 20, // 查询历史交易数(可选,默认 20) + ProxyURL: "http://127.0.0.1:7890", // HTTP/SOCKS5 代理(可选) +}) + +// 或者使用自定义 Transport +uman := usdtman.NewUSDTMan(usdtman.Config{ + Addresses: []string{"地址1"}, + APIKey: "YOUR_API_KEY", + Transport: &http.Transport{ + Proxy: http.ProxyURL(proxyURL), + // 其他自定义配置... + }, +}) // 设置收款回调 uman.OnPaymentComplete(func(payment *usdtman.USDTPayment) { @@ -25,6 +42,10 @@ uman.Start() // 停止监听 uman.Stop() + +// 动态添加/移除地址 +uman.AddAddress("新地址") +uman.RemoveAddress("旧地址") ``` ## 运行 diff --git a/cmd/server/main.go b/cmd/server/main.go index e5f48e7..3c5a3d8 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -7,6 +7,7 @@ import ( "net/http" "os" "sync" + "time" "usdtman" "github.com/gorilla/websocket" @@ -34,8 +35,24 @@ func main() { apiKey = "da1e77dc-b35b-4458-846a-5a551b9df4b2" } - // 初始化 USDTMan (无初始地址) - uman = usdtman.NewUSDTMan([]string{}, apiKey) + // 初始化 USDTMan + proxyURL := os.Getenv("PROXY_URL") // 例如: http://127.0.0.1:7890 + + config := usdtman.Config{ + Addresses: []string{}, // 初始无地址,可通过 API 添加 + APIKey: apiKey, + QueryInterval: 5 * time.Second, // 每 5 秒查询一次 + MinConfirmations: 6, // 6 个确认 + MaxHistoryTxns: 20, // 每次查询最多 20 条历史交易 + } + + // 如果设置了代理 + if proxyURL != "" { + config.ProxyURL = proxyURL + log.Printf("✅ 使用代理: %s", proxyURL) + } + + uman = usdtman.NewUSDTMan(config) // 设置收款回调 uman.OnPaymentComplete(func(payment *usdtman.USDTPayment) { diff --git a/tron_usdt_monitor.go b/tron_usdt_monitor.go index af4ee16..7d0f0f1 100644 --- a/tron_usdt_monitor.go +++ b/tron_usdt_monitor.go @@ -6,23 +6,38 @@ import ( "fmt" "io" "net/http" + "net/url" "strings" "sync" "time" ) +// Config USDTMan 配置 +type Config struct { + Addresses []string // 监听地址列表 + APIKey string // TronGrid API Key + QueryInterval time.Duration // 查询间隔(秒),默认 5 秒 + MinConfirmations int64 // 最小确认数,默认 6 + MaxHistoryTxns int // 每次查询的最大历史交易数,默认 20 + ProxyURL string // HTTP/SOCKS5 代理地址,例如 "http://127.0.0.1:7890" 或 "socks5://127.0.0.1:1080" + Transport http.RoundTripper // 自定义 Transport(优先级高于 ProxyURL) +} + // USDTMan USDT 监听管理器 type USDTMan struct { mu sync.RWMutex addresses []string apiKey string + queryInterval time.Duration running bool ctx context.Context cancel context.CancelFunc onPaymentComplete func(*USDTPayment) minConfirmations int64 + maxHistoryTxns int processedTxns map[string]bool // 已处理的交易 txnMutex sync.RWMutex + httpClient *http.Client // HTTP 客户端 } // USDTPayment USDT 收款信息 @@ -80,14 +95,50 @@ const ( ) // NewUSDTMan 创建监听管理器 -func NewUSDTMan(addresses []string, apiKey string) *USDTMan { +func NewUSDTMan(config Config) *USDTMan { ctx, cancel := context.WithCancel(context.Background()) + + // 设置默认值 + if config.QueryInterval == 0 { + config.QueryInterval = 5 * time.Second + } + if config.MinConfirmations == 0 { + config.MinConfirmations = 6 + } + if config.MaxHistoryTxns == 0 { + config.MaxHistoryTxns = 20 + } + + // 创建 HTTP 客户端 + httpClient := &http.Client{ + Timeout: 10 * time.Second, + } + + // 配置代理 + if config.Transport != nil { + // 使用自定义 Transport + httpClient.Transport = config.Transport + } else if config.ProxyURL != "" { + // 使用代理 URL + proxyURL, err := url.Parse(config.ProxyURL) + if err == nil { + httpClient.Transport = &http.Transport{ + Proxy: http.ProxyURL(proxyURL), + } + } else { + fmt.Printf("⚠️ 代理 URL 解析失败: %v,使用直连\n", err) + } + } + return &USDTMan{ - addresses: addresses, - apiKey: apiKey, + addresses: config.Addresses, + apiKey: config.APIKey, + queryInterval: config.QueryInterval, + minConfirmations: config.MinConfirmations, + maxHistoryTxns: config.MaxHistoryTxns, + httpClient: httpClient, ctx: ctx, cancel: cancel, - minConfirmations: 6, processedTxns: make(map[string]bool), } } @@ -128,7 +179,7 @@ func (m *USDTMan) Stop() { // monitorLoop 监听循环 func (m *USDTMan) monitorLoop() { - ticker := time.NewTicker(5 * time.Second) + ticker := time.NewTicker(m.queryInterval) defer ticker.Stop() for { @@ -207,8 +258,8 @@ func (m *USDTMan) checkAddress(address string) { // getUSDTTransactions 获取地址的 USDT 交易 func (m *USDTMan) getUSDTTransactions(address string) ([]TronGridTransaction, error) { - url := fmt.Sprintf("%s/v1/accounts/%s/transactions/trc20?limit=20&contract_address=%s&only_to=true", - TronGridAPI, address, USDTContractAddress) + url := fmt.Sprintf("%s/v1/accounts/%s/transactions/trc20?limit=%d&contract_address=%s&only_to=true", + TronGridAPI, address, m.maxHistoryTxns, USDTContractAddress) req, err := http.NewRequest("GET", url, nil) if err != nil { @@ -219,8 +270,7 @@ func (m *USDTMan) getUSDTTransactions(address string) ([]TronGridTransaction, er req.Header.Set("TRON-PRO-API-KEY", m.apiKey) } - client := &http.Client{Timeout: 10 * time.Second} - resp, err := client.Do(req) + resp, err := m.httpClient.Do(req) if err != nil { return nil, err } @@ -256,8 +306,7 @@ func (m *USDTMan) getCurrentBlock() (int64, error) { req.Header.Set("TRON-PRO-API-KEY", m.apiKey) } - client := &http.Client{Timeout: 10 * time.Second} - resp, err := client.Do(req) + resp, err := m.httpClient.Do(req) if err != nil { return 0, err }