Initial commit
This commit is contained in:
@@ -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()
|
||||
}
|
||||
Reference in New Issue
Block a user