fix update
This commit is contained in:
25
README.md
25
README.md
@@ -12,8 +12,25 @@ TRON USDT TRC20 收款监听服务 - 基于交易记录扫描 + 区块确认数
|
|||||||
## API 使用方式
|
## API 使用方式
|
||||||
|
|
||||||
```go
|
```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) {
|
uman.OnPaymentComplete(func(payment *usdtman.USDTPayment) {
|
||||||
@@ -25,6 +42,10 @@ uman.Start()
|
|||||||
|
|
||||||
// 停止监听
|
// 停止监听
|
||||||
uman.Stop()
|
uman.Stop()
|
||||||
|
|
||||||
|
// 动态添加/移除地址
|
||||||
|
uman.AddAddress("新地址")
|
||||||
|
uman.RemoveAddress("旧地址")
|
||||||
```
|
```
|
||||||
|
|
||||||
## 运行
|
## 运行
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
"usdtman"
|
"usdtman"
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
@@ -34,8 +35,24 @@ func main() {
|
|||||||
apiKey = "da1e77dc-b35b-4458-846a-5a551b9df4b2"
|
apiKey = "da1e77dc-b35b-4458-846a-5a551b9df4b2"
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化 USDTMan (无初始地址)
|
// 初始化 USDTMan
|
||||||
uman = usdtman.NewUSDTMan([]string{}, apiKey)
|
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) {
|
uman.OnPaymentComplete(func(payment *usdtman.USDTPayment) {
|
||||||
|
|||||||
@@ -6,23 +6,38 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"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 监听管理器
|
// USDTMan USDT 监听管理器
|
||||||
type USDTMan struct {
|
type USDTMan struct {
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
addresses []string
|
addresses []string
|
||||||
apiKey string
|
apiKey string
|
||||||
|
queryInterval time.Duration
|
||||||
running bool
|
running bool
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
onPaymentComplete func(*USDTPayment)
|
onPaymentComplete func(*USDTPayment)
|
||||||
minConfirmations int64
|
minConfirmations int64
|
||||||
|
maxHistoryTxns int
|
||||||
processedTxns map[string]bool // 已处理的交易
|
processedTxns map[string]bool // 已处理的交易
|
||||||
txnMutex sync.RWMutex
|
txnMutex sync.RWMutex
|
||||||
|
httpClient *http.Client // HTTP 客户端
|
||||||
}
|
}
|
||||||
|
|
||||||
// USDTPayment USDT 收款信息
|
// USDTPayment USDT 收款信息
|
||||||
@@ -80,14 +95,50 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// NewUSDTMan 创建监听管理器
|
// NewUSDTMan 创建监听管理器
|
||||||
func NewUSDTMan(addresses []string, apiKey string) *USDTMan {
|
func NewUSDTMan(config Config) *USDTMan {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
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{
|
return &USDTMan{
|
||||||
addresses: addresses,
|
addresses: config.Addresses,
|
||||||
apiKey: apiKey,
|
apiKey: config.APIKey,
|
||||||
|
queryInterval: config.QueryInterval,
|
||||||
|
minConfirmations: config.MinConfirmations,
|
||||||
|
maxHistoryTxns: config.MaxHistoryTxns,
|
||||||
|
httpClient: httpClient,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
minConfirmations: 6,
|
|
||||||
processedTxns: make(map[string]bool),
|
processedTxns: make(map[string]bool),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,7 +179,7 @@ func (m *USDTMan) Stop() {
|
|||||||
|
|
||||||
// monitorLoop 监听循环
|
// monitorLoop 监听循环
|
||||||
func (m *USDTMan) monitorLoop() {
|
func (m *USDTMan) monitorLoop() {
|
||||||
ticker := time.NewTicker(5 * time.Second)
|
ticker := time.NewTicker(m.queryInterval)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
@@ -207,8 +258,8 @@ func (m *USDTMan) checkAddress(address string) {
|
|||||||
|
|
||||||
// getUSDTTransactions 获取地址的 USDT 交易
|
// getUSDTTransactions 获取地址的 USDT 交易
|
||||||
func (m *USDTMan) getUSDTTransactions(address string) ([]TronGridTransaction, error) {
|
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",
|
url := fmt.Sprintf("%s/v1/accounts/%s/transactions/trc20?limit=%d&contract_address=%s&only_to=true",
|
||||||
TronGridAPI, address, USDTContractAddress)
|
TronGridAPI, address, m.maxHistoryTxns, USDTContractAddress)
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
if err != 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)
|
req.Header.Set("TRON-PRO-API-KEY", m.apiKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
client := &http.Client{Timeout: 10 * time.Second}
|
resp, err := m.httpClient.Do(req)
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -256,8 +306,7 @@ func (m *USDTMan) getCurrentBlock() (int64, error) {
|
|||||||
req.Header.Set("TRON-PRO-API-KEY", m.apiKey)
|
req.Header.Set("TRON-PRO-API-KEY", m.apiKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
client := &http.Client{Timeout: 10 * time.Second}
|
resp, err := m.httpClient.Do(req)
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user