2024-04-11 14:35:17 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"io"
|
|
|
|
"log"
|
|
|
|
"net/http"
|
|
|
|
"strconv"
|
2024-04-20 22:23:48 +02:00
|
|
|
"swap-client/cfg"
|
|
|
|
"swap-client/clients"
|
|
|
|
"swap-client/coin"
|
|
|
|
"swap-client/dero"
|
|
|
|
"swap-client/monero"
|
2024-04-11 14:35:17 +02:00
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
func GetMarket(pair string, provider int) (prices Swap_Price) {
|
|
|
|
|
|
|
|
resp, err := http.Get(pair)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("Market: HTTP Get: %v\n", err)
|
|
|
|
return Swap_Price{}
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("Market: Read Body: %v\n", err)
|
|
|
|
return Swap_Price{}
|
|
|
|
}
|
|
|
|
|
|
|
|
var market Price_Provider
|
|
|
|
|
|
|
|
if err := json.Unmarshal(body, &market); err != nil {
|
|
|
|
log.Printf("Market: Cannot unmarshal data: %v\n", err)
|
|
|
|
return Swap_Price{}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch provider {
|
|
|
|
case TO:
|
|
|
|
prices.Ask, err = strconv.ParseFloat(market.Ask, 64)
|
|
|
|
prices.Bid, err = strconv.ParseFloat(market.Bid, 64)
|
|
|
|
prices.Median, err = strconv.ParseFloat(market.Price, 64)
|
|
|
|
case XEGGEX:
|
|
|
|
prices.Ask, err = strconv.ParseFloat(market.BestAsk, 64)
|
|
|
|
prices.Bid, err = strconv.ParseFloat(market.BestBid, 64)
|
|
|
|
prices.Median, err = strconv.ParseFloat(market.LastPrice, 64)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("Market: Cannot convert string: %v\n", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get Pair values
|
|
|
|
// TODO: configurable fees; clean-up
|
|
|
|
func GetPrice(pair string) (bid float64, ask float64) {
|
|
|
|
|
|
|
|
var base, base_usd Swap_Price
|
|
|
|
var atomicUnits uint = 8
|
|
|
|
var simple bool
|
|
|
|
|
|
|
|
switch pair {
|
|
|
|
case coin.BTCDERO, coin.DEROBTC:
|
|
|
|
simple = true
|
|
|
|
for i := range DERO_BTC {
|
|
|
|
if base = GetMarket(DERO_BTC[i], i); base.Ask > 0 && base.Bid > 0 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case coin.LTCDERO, coin.DEROLTC:
|
|
|
|
for i := range LTC_USDT {
|
|
|
|
if base = GetMarket(LTC_USDT[i], i); base.Ask > 0 && base.Bid > 0 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case coin.XMRDERO, coin.DEROXMR:
|
|
|
|
atomicUnits = 12
|
|
|
|
for i := range XMR_USDT {
|
|
|
|
if base = GetMarket(XMR_USDT[i], i); base.Ask > 0 && base.Bid > 0 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case coin.ARRRDERO, coin.DEROARRR:
|
|
|
|
base = GetMarket(ARRR_USDT, TO)
|
|
|
|
}
|
|
|
|
|
|
|
|
if base.Ask == 0 || base.Bid == 0 {
|
|
|
|
return 0, 0
|
|
|
|
}
|
|
|
|
|
|
|
|
if simple {
|
|
|
|
bid = base.Bid - (base.Bid * cfg.SwapFees.Swap.Bid / 100)
|
|
|
|
bid = coin.RoundFloat(bid, atomicUnits)
|
|
|
|
ask = base.Ask + (base.Ask * cfg.SwapFees.Swap.Ask / 100)
|
|
|
|
ask = coin.RoundFloat(ask, atomicUnits)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := range DERO_USDT {
|
|
|
|
if base_usd = GetMarket(DERO_USDT[i], i); base_usd.Ask > 0 && base_usd.Bid > 0 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if base_usd.Ask == 0 || base_usd.Bid == 0 {
|
|
|
|
return 0, 0
|
|
|
|
}
|
|
|
|
|
|
|
|
bid = base_usd.Bid - (base_usd.Bid * cfg.SwapFees.Swap.Bid / 100)
|
|
|
|
ask = base_usd.Ask + (base_usd.Ask * cfg.SwapFees.Swap.Ask / 100)
|
|
|
|
|
|
|
|
bid = coin.RoundFloat(bid/base.Bid, atomicUnits)
|
|
|
|
ask = coin.RoundFloat(ask/base.Ask, atomicUnits)
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: simplify
|
|
|
|
func UpdateMarkets() {
|
|
|
|
|
2024-04-23 20:21:35 +02:00
|
|
|
var xmr, ltc float64
|
|
|
|
var deroxmr, deroltc float64
|
2024-04-11 14:35:17 +02:00
|
|
|
|
|
|
|
for p := range coin.SimplePairs {
|
|
|
|
switch p {
|
|
|
|
case coin.XMRDERO, coin.DEROXMR:
|
|
|
|
deroxmr, xmr = GetPrice(p)
|
2024-04-23 20:21:35 +02:00
|
|
|
case coin.LTCDERO, coin.DEROLTC:
|
|
|
|
deroltc, ltc = GetPrice(p)
|
2024-04-11 14:35:17 +02:00
|
|
|
}
|
|
|
|
|
2024-04-20 22:23:48 +02:00
|
|
|
// sometimes TradeOgre's BID/ASK values are swapped
|
|
|
|
if deroxmr > 0 && xmr > 0 && deroxmr > xmr {
|
|
|
|
swap := xmr
|
|
|
|
xmr = deroxmr
|
|
|
|
deroxmr = swap
|
2024-04-11 14:35:17 +02:00
|
|
|
}
|
2024-04-23 20:21:35 +02:00
|
|
|
if deroltc > 0 && ltc > 0 && deroltc > ltc {
|
|
|
|
swap := ltc
|
|
|
|
ltc = deroltc
|
|
|
|
deroltc = swap
|
|
|
|
}
|
2024-04-26 16:05:47 +02:00
|
|
|
}
|
2024-04-20 22:23:48 +02:00
|
|
|
|
2024-04-26 16:05:47 +02:00
|
|
|
mk.Lock()
|
|
|
|
defer mk.Unlock()
|
|
|
|
|
|
|
|
// TODO: simplify
|
|
|
|
if xmr > 0 {
|
|
|
|
mk.Pairs.XMR = xmr
|
|
|
|
mk.Update[coin.XMRDERO] = time.Now().UnixMilli()
|
|
|
|
IsPairAvailable[coin.XMRDERO] = true
|
|
|
|
} else {
|
|
|
|
t := time.UnixMilli(mk.Update[coin.XMRDERO])
|
|
|
|
if time.Since(t) > time.Minute*2 {
|
|
|
|
IsPairAvailable[coin.XMRDERO] = false
|
|
|
|
log.Println("XMR->DERO disabled")
|
2024-04-11 14:35:17 +02:00
|
|
|
}
|
2024-04-26 16:05:47 +02:00
|
|
|
}
|
|
|
|
if deroxmr > 0 {
|
|
|
|
mk.Pairs.DEROXMR = deroxmr
|
|
|
|
mk.Update[coin.DEROXMR] = time.Now().UnixMilli()
|
|
|
|
IsPairAvailable[coin.DEROXMR] = true
|
|
|
|
} else {
|
|
|
|
t := time.UnixMilli(mk.Update[coin.DEROXMR])
|
|
|
|
if time.Since(t) > time.Minute*2 {
|
|
|
|
IsPairAvailable[coin.DEROXMR] = false
|
|
|
|
log.Println("DERO->XMR disabled")
|
2024-04-11 14:35:17 +02:00
|
|
|
}
|
2024-04-26 16:05:47 +02:00
|
|
|
}
|
|
|
|
if ltc > 0 {
|
|
|
|
mk.Pairs.LTC = ltc
|
|
|
|
mk.Update[coin.LTCDERO] = time.Now().UnixMilli()
|
|
|
|
IsPairAvailable[coin.LTCDERO] = true
|
|
|
|
} else {
|
|
|
|
t := time.UnixMilli(mk.Update[coin.LTCDERO])
|
|
|
|
if time.Since(t) > time.Minute*2 {
|
|
|
|
IsPairAvailable[coin.LTCDERO] = false
|
|
|
|
log.Println("LTC->DERO disabled")
|
2024-04-23 20:21:35 +02:00
|
|
|
}
|
2024-04-26 16:05:47 +02:00
|
|
|
}
|
|
|
|
if deroltc > 0 {
|
|
|
|
mk.Pairs.DEROLTC = deroltc
|
|
|
|
mk.Update[coin.DEROLTC] = time.Now().UnixMilli()
|
|
|
|
IsPairAvailable[coin.DEROLTC] = true
|
|
|
|
} else {
|
|
|
|
t := time.UnixMilli(mk.Update[coin.DEROLTC])
|
|
|
|
if time.Since(t) > time.Minute*2 {
|
|
|
|
IsPairAvailable[coin.DEROLTC] = false
|
|
|
|
log.Println("DERO->LTC disabled")
|
2024-04-23 20:21:35 +02:00
|
|
|
}
|
2024-04-11 14:35:17 +02:00
|
|
|
}
|
|
|
|
|
2024-04-20 22:23:48 +02:00
|
|
|
balance := UpdatePool()
|
2024-04-11 14:35:17 +02:00
|
|
|
|
2024-04-20 22:23:48 +02:00
|
|
|
var out WS_Message
|
2024-04-11 14:35:17 +02:00
|
|
|
|
2024-04-20 22:23:48 +02:00
|
|
|
out.Method = "client"
|
|
|
|
out.Params = balance
|
2024-04-11 14:35:17 +02:00
|
|
|
|
2024-04-23 20:21:35 +02:00
|
|
|
if Connection != nil {
|
|
|
|
Connection.WriteJSON(out)
|
|
|
|
} else {
|
|
|
|
log.Println("<nil> server connection")
|
|
|
|
}
|
2024-04-11 14:35:17 +02:00
|
|
|
}
|
|
|
|
|
2024-04-20 22:23:48 +02:00
|
|
|
func UpdatePool() clients.ClientInfo {
|
2024-04-11 14:35:17 +02:00
|
|
|
|
|
|
|
lock.Lock()
|
|
|
|
defer lock.Unlock()
|
|
|
|
|
2024-04-20 22:23:48 +02:00
|
|
|
var info clients.ClientInfo
|
|
|
|
var pair clients.PairInfo
|
2024-04-11 14:35:17 +02:00
|
|
|
|
2024-04-20 22:23:48 +02:00
|
|
|
info.Nickname = cfg.Settings.Nickname
|
2024-04-11 14:35:17 +02:00
|
|
|
|
2024-04-20 22:23:48 +02:00
|
|
|
for p := range coin.Pairs {
|
2024-04-11 14:35:17 +02:00
|
|
|
switch p {
|
2024-04-23 20:21:35 +02:00
|
|
|
case coin.DEROLTC:
|
2024-04-26 16:05:47 +02:00
|
|
|
pair.Balance = coin.XTCGetBalance(p)
|
2024-04-23 20:21:35 +02:00
|
|
|
pair.Pair = p
|
2024-04-20 22:23:48 +02:00
|
|
|
case coin.DEROXMR:
|
2024-04-26 16:05:47 +02:00
|
|
|
pair.Balance = monero.GetBalance()
|
2024-04-20 22:23:48 +02:00
|
|
|
pair.Pair = p
|
2024-04-26 16:05:47 +02:00
|
|
|
case coin.XMRDERO, coin.LTCDERO:
|
|
|
|
pair.Balance = dero.GetBalance()
|
2024-04-20 22:23:48 +02:00
|
|
|
pair.Pair = p
|
|
|
|
default:
|
|
|
|
continue
|
2024-04-11 14:35:17 +02:00
|
|
|
}
|
2024-04-20 22:23:48 +02:00
|
|
|
info.PairInfo = append(info.PairInfo, pair)
|
2024-04-11 14:35:17 +02:00
|
|
|
}
|
|
|
|
|
2024-04-20 22:23:48 +02:00
|
|
|
return info
|
2024-04-11 14:35:17 +02:00
|
|
|
}
|