This commit is contained in:
2026-02-03 00:01:41 +08:00
parent 3d3e814879
commit 79c1c710a2
4 changed files with 387 additions and 318 deletions

View File

@@ -13,7 +13,7 @@ import (
)
var (
tronMonitor *usdtman.TronUSDTMonitor
uman *usdtman.USDTMan
paymentEvents []usdtman.USDTPayment
paymentLock sync.RWMutex
upgrader = websocket.Upgrader{
@@ -34,10 +34,13 @@ func main() {
apiKey = "da1e77dc-b35b-4458-846a-5a551b9df4b2"
}
tronMonitor = usdtman.NewTronUSDTMonitor(apiKey)
tronMonitor.SetPaymentCallback(func(payment *usdtman.USDTPayment) {
log.Printf("💰 收到 USDT: %s -> %.6f USDT (TxID: %s)",
payment.From, payment.Amount, payment.TxID)
// 初始化 USDTMan (无初始地址)
uman = usdtman.NewUSDTMan([]string{}, apiKey)
// 设置收款回调
uman.OnPaymentComplete(func(payment *usdtman.USDTPayment) {
log.Printf("💰 收到 USDT: %s -> %.6f USDT (确认数: %d, TxID: %s)",
payment.From, payment.Amount, payment.Confirmations, payment.TxID)
paymentLock.Lock()
paymentEvents = append(paymentEvents, *payment)
@@ -77,7 +80,7 @@ func startMonitor(w http.ResponseWriter, r *http.Request) {
return
}
if err := tronMonitor.Start(); err != nil {
if err := uman.Start(); err != nil {
jsonResponse(w, false, fmt.Sprintf("启动失败: %v", err), nil)
return
}
@@ -91,7 +94,7 @@ func stopMonitor(w http.ResponseWriter, r *http.Request) {
return
}
tronMonitor.Stop()
uman.Stop()
jsonResponse(w, true, "监听已停止", nil)
}
@@ -115,7 +118,7 @@ func addAddress(w http.ResponseWriter, r *http.Request) {
return
}
tronMonitor.AddAddress(req.Address)
uman.AddAddress(req.Address)
jsonResponse(w, true, "地址已添加", map[string]interface{}{
"address": req.Address,
})
@@ -136,7 +139,7 @@ func removeAddress(w http.ResponseWriter, r *http.Request) {
return
}
tronMonitor.RemoveAddress(req.Address)
uman.RemoveAddress(req.Address)
jsonResponse(w, true, "地址已移除", map[string]interface{}{
"address": req.Address,
})
@@ -148,7 +151,7 @@ func listAddresses(w http.ResponseWriter, r *http.Request) {
return
}
addresses := tronMonitor.GetAllAddresses()
addresses := uman.GetAddresses()
jsonResponse(w, true, "success", map[string]interface{}{
"addresses": addresses,
"count": len(addresses),
@@ -200,13 +203,14 @@ func handleWebSocket(w http.ResponseWriter, r *http.Request) {
func broadcastPayment(payment *usdtman.USDTPayment) {
message := map[string]interface{}{
"type": "usdt_payment",
"address": payment.Address,
"amount": payment.Amount,
"from": payment.From,
"txId": payment.TxID,
"block": payment.BlockNumber,
"time": payment.Timestamp,
"type": "usdt_payment",
"address": payment.Address,
"amount": payment.Amount,
"from": payment.From,
"txId": payment.TxID,
"block": payment.BlockNumber,
"time": payment.Timestamp,
"confirmations": payment.Confirmations,
}
clientsLock.RLock()
@@ -218,138 +222,5 @@ func broadcastPayment(payment *usdtman.USDTPayment) {
}
func serveIndex(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Write([]byte(indexHTML))
http.ServeFile(w, r, "index.html")
}
const indexHTML = `<!DOCTYPE html>
<html>
<head>
<title>USDTMan - USDT Monitor</title>
<style>
body { font-family: Arial; max-width: 1000px; margin: 20px auto; padding: 20px; }
h1 { color: #333; }
.section { margin: 20px 0; padding: 15px; border: 1px solid #ddd; border-radius: 5px; }
button { padding: 8px 15px; margin: 5px; cursor: pointer; }
input { padding: 8px; margin: 5px; width: 400px; }
.success { color: green; }
.error { color: red; }
#log { max-height: 300px; overflow-y: auto; background: #f5f5f5; padding: 10px; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 8px; text-align: left; border-bottom: 1px solid #ddd; }
</style>
</head>
<body>
<h1>🚀 USDTMan - USDT Monitor</h1>
<div class="section">
<h3>监听控制</h3>
<button onclick="startMonitor()">启动监听</button>
<button onclick="stopMonitor()">停止监听</button>
<div id="status"></div>
</div>
<div class="section">
<h3>地址管理</h3>
<input type="text" id="address" placeholder="输入 TRON 地址">
<button onclick="addAddress()">添加地址</button>
<button onclick="listAddresses()">刷新列表</button>
<div id="addresses"></div>
</div>
<div class="section">
<h3>收款记录</h3>
<button onclick="getPayments()">刷新</button>
<div id="payments"></div>
</div>
<div class="section">
<h3>实时日志 (WebSocket)</h3>
<div id="log"></div>
</div>
<script>
const ws = new WebSocket('ws://' + location.host + '/ws');
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'usdt_payment') {
addLog('💰 收到 USDT: ' + data.from + ' -> ' + data.amount.toFixed(6) + ' USDT (TxID: ' + data.txId + ')');
getPayments();
}
};
function addLog(msg) {
const log = document.getElementById('log');
const time = new Date().toLocaleTimeString();
log.innerHTML = '[' + time + '] ' + msg + '<br>' + log.innerHTML;
}
async function startMonitor() {
const res = await fetch('/start', { method: 'POST' });
const data = await res.json();
document.getElementById('status').innerHTML = '<span class="success">' + data.message + '</span>';
}
async function stopMonitor() {
const res = await fetch('/stop', { method: 'POST' });
const data = await res.json();
document.getElementById('status').innerHTML = '<span class="error">' + data.message + '</span>';
}
async function addAddress() {
const address = document.getElementById('address').value;
if (!address) return alert('请输入地址');
const res = await fetch('/add-address', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ address })
});
const data = await res.json();
alert(data.message);
listAddresses();
}
async function listAddresses() {
const res = await fetch('/list-addresses');
const data = await res.json();
const html = data.data.addresses.map(addr =>
'<div>' + addr + ' <button onclick="removeAddress(\'' + addr + '\')">移除</button></div>'
).join('');
document.getElementById('addresses').innerHTML = html || '暂无地址';
}
async function removeAddress(addr) {
const res = await fetch('/remove-address', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ address: addr })
});
listAddresses();
}
async function getPayments() {
const res = await fetch('/payments');
const data = await res.json();
if (data.data.payments && data.data.payments.length > 0) {
const html = '<table><tr><th>时间</th><th>地址</th><th>金额</th><th>来源</th><th>TxID</th></tr>' +
data.data.payments.map(p =>
'<tr><td>' + new Date(p.Timestamp).toLocaleString() + '</td>' +
'<td>' + p.Address.substring(0, 10) + '...</td>' +
'<td>' + p.Amount.toFixed(6) + ' USDT</td>' +
'<td>' + p.From.substring(0, 10) + '...</td>' +
'<td><a href="https://tronscan.org/#/transaction/' + p.TxID + '" target="_blank">' +
p.TxID.substring(0, 10) + '...</a></td></tr>'
).join('') + '</table>';
document.getElementById('payments').innerHTML = html;
} else {
document.getElementById('payments').innerHTML = '暂无记录';
}
}
listAddresses();
getPayments();
</script>
</body>
</html>`