Initial commit

This commit is contained in:
jackyu66git
2026-05-03 16:54:36 +08:00
commit 719f0a061d
22 changed files with 2436 additions and 0 deletions
+79
View File
@@ -0,0 +1,79 @@
package exchange
import (
"encoding/json"
"fmt"
"log"
"strconv"
"strings"
"time"
)
type BinanceWS struct {
Tracked []string
}
func NewBinanceWS(tracked []string) *BinanceWS {
return &BinanceWS{Tracked: tracked}
}
// Run connects to Binance WS and streams bookTicker data.
func (b *BinanceWS) Run(updateFn func(coin string, price, bid, ask float64)) error {
streams := ""
for i, sym := range b.Tracked {
if i > 0 {
streams += "/"
}
streams += fmt.Sprintf("%s@bookTicker", strings.ToLower(sym))
}
url := fmt.Sprintf("wss://fstream.binance.com/stream?streams=%s", streams)
conn := NewPriceConnector(url, "Binance", 120*time.Second, 30*time.Second)
conn.PingInterval = 45 * time.Second
conn.OnConnect = func() {
log.Printf("[Binance WS] Connected")
}
conn.OnMessage = func(msg []byte) {
// Combined stream: {"stream":"...","data":{...}}
// Navigate through "data" using map to avoid field name conflicts
var raw map[string]json.RawMessage
if err := json.Unmarshal(msg, &raw); err != nil {
return
}
dataRaw, ok := raw["data"]
if !ok {
return
}
// Parse data object as flat map to extract fields by exact name
var dataMap map[string]interface{}
if err := json.Unmarshal(dataRaw, &dataMap); err != nil {
return
}
symbol, _ := dataMap["s"].(string)
bidStr, _ := dataMap["b"].(string)
askStr, _ := dataMap["a"].(string)
if symbol == "" || bidStr == "" || askStr == "" {
return
}
bid, err1 := strconv.ParseFloat(bidStr, 64)
ask, err2 := strconv.ParseFloat(askStr, 64)
if err1 != nil || err2 != nil || bid <= 0 || ask <= 0 {
return
}
// Extract coin name (e.g., "BTCUSDT" -> "BTC")
coin := symbolToCoin(symbol, "USDT")
if coin == "" {
return
}
mid := (bid + ask) / 2.0
updateFn(coin, mid, bid, ask)
}
return conn.Run()
}