swap client support

This commit is contained in:
mmarcel 2024-04-20 22:21:02 +02:00
parent cfa71f8203
commit ddfc1bb8aa
14 changed files with 401 additions and 77 deletions

View File

@ -4,6 +4,7 @@ import (
"dero-swap/coin"
"dero-swap/dero"
"dero-swap/monero"
"encoding/base64"
"encoding/json"
"log"
"os"
@ -26,13 +27,24 @@ func LoadConfig() {
return
}
dero.Dero_Daemon = jsonrpc.NewClient("http://" + Settings.Dero_daemon + "/json_rpc")
dero.Dero_Wallet = jsonrpc.NewClient("http://" + Settings.Dero_wallet + "/json_rpc")
monero.Monero_Wallet = jsonrpc.NewClient("http://" + Settings.Monero_wallet + "/json_rpc")
dero.Dero_Daemon = jsonrpc.NewClient("http://" + Settings.Dero_Daemon + "/json_rpc")
if Settings.Dero_Login != "" {
dero.RPC_Login = base64.StdEncoding.EncodeToString([]byte(Settings.Dero_Login))
dero.Dero_Wallet = jsonrpc.NewClientWithOpts("http://"+Settings.Dero_Wallet+"/json_rpc", &jsonrpc.RPCClientOpts{
CustomHeaders: map[string]string{
"Authorization": "Basic " + dero.RPC_Login,
},
})
} else {
dero.Dero_Wallet = jsonrpc.NewClient("http://" + Settings.Dero_Wallet + "/json_rpc")
log.Println("Dero Wallet: No RPC authorization specified")
}
coin.XTC_URL[coin.BTCDERO] = "http://" + Settings.BTC_daemon
coin.XTC_URL[coin.LTCDERO] = "http://" + Settings.LTC_daemon
coin.XTC_URL[coin.ARRRDERO] = "http://" + Settings.ARRR_daemon
monero.Monero_Wallet = jsonrpc.NewClient("http://" + Settings.Monero_Wallet + "/json_rpc")
coin.XTC_URL[coin.BTCDERO] = "http://" + Settings.BTC_Daemon
coin.XTC_URL[coin.LTCDERO] = "http://" + Settings.LTC_Daemon
coin.XTC_URL[coin.ARRRDERO] = "http://" + Settings.ARRR_Daemon
// check if pair is "supported"
for _, p := range Settings.Pairs {
@ -75,7 +87,7 @@ func LoadFees() {
// basic config check
func CheckConfig() bool {
if Settings.Dero_daemon == "" || Settings.Dero_wallet == "" {
if Settings.Dero_Daemon == "" || Settings.Dero_Wallet == "" {
log.Println("Dero Daemon or Dero Wallet is not set")
return false
}
@ -83,38 +95,44 @@ func CheckConfig() bool {
for p := range coin.Pairs {
switch p {
case coin.BTCDERO, coin.DEROBTC:
if Settings.BTC_daemon == "" || Settings.BTC_dir == "" {
if Settings.BTC_Daemon == "" || Settings.BTC_Dir == "" {
log.Printf("%s pair is set, but daemon or directory is not set\n", p)
return false
} else {
coin.BTC_dir = Settings.BTC_dir
coin.BTC_Dir = Settings.BTC_Dir
}
case coin.LTCDERO, coin.DEROLTC:
if Settings.LTC_daemon == "" || Settings.LTC_dir == "" {
if Settings.LTC_Daemon == "" || Settings.LTC_Dir == "" {
log.Printf("%s pair is set, but daemon or directory is not set\n", p)
return false
} else {
coin.LTC_dir = Settings.LTC_dir
coin.LTC_Dir = Settings.LTC_Dir
}
case coin.ARRRDERO, coin.DEROARRR:
if Settings.ARRR_daemon == "" || Settings.ARRR_dir == "" {
if Settings.ARRR_Daemon == "" || Settings.ARRR_Dir == "" {
log.Printf("%s pair is set, but daemon or directory is not set\n", p)
return false
} else {
coin.ARRR_dir = Settings.ARRR_dir
coin.ARRR_Dir = Settings.ARRR_Dir
}
case coin.XMRDERO, coin.DEROXMR:
if Settings.Monero_wallet == "" {
if Settings.Monero_Wallet == "" {
log.Printf("%s pair is set, but wallet is not set\n", p)
return false
}
}
}
if dero.GetHeight() == 0 || dero.CheckBlockHeight() == 0 {
if dero.RPC_Login != "" {
log.Printf("%-14s: %s\n", "Dero Wallet", "Using RPC authorization")
}
dero_wallet := dero.GetAddress()
if dero.GetHeight() == 0 || dero.CheckBlockHeight() == 0 || dero_wallet == "" {
log.Println("Dero daemon or wallet is not available")
return false
}
log.Printf("%-14s: %s\n", "Dero Wallet", dero_wallet)
return true
}

View File

@ -2,16 +2,17 @@ package cfg
type Config struct {
ListenAddress string `json:"listen"`
BTC_daemon string `json:"btc_daemon"`
BTC_dir string `json:"btc_dir"`
LTC_daemon string `json:"ltc_daemon"`
LTC_dir string `json:"ltc_dir"`
ARRR_daemon string `json:"arrr_daemon"`
ARRR_dir string `json:"arrr_dir"`
Dero_daemon string `json:"dero_daemon"`
Dero_wallet string `json:"dero_wallet"`
Monero_daemon string `json:"monero_daemon"`
Monero_wallet string `json:"monero_wallet"`
BTC_Daemon string `json:"BTC_Daemon"`
BTC_Dir string `json:"BTC_Dir"`
LTC_Daemon string `json:"LTC_Daemon"`
LTC_Dir string `json:"LTC_Dir"`
ARRR_Daemon string `json:"ARRR_Daemon"`
ARRR_Dir string `json:"ARRR_Dir"`
Dero_Daemon string `json:"Dero_Daemon"`
Dero_Wallet string `json:"dero_wallet"`
Dero_Login string `json:"dero_login"`
Monero_Daemon string `json:"monero_daemon"`
Monero_Wallet string `json:"Monero_Wallet"`
Pairs []string `json:"pairs"`
//SwapFees float64 `json:"swap_fees"`
}
@ -46,4 +47,4 @@ type (
)
var Settings Config
var SwapFees = Fees{Withdrawal: Withdrawal_Fees{DeroLTC: 0.0002, DeroBTC: 0.00004, DeroARRR: 0.001, DeroXMR: 0.00006}}
var SwapFees Fees

105
clients/clients.go Normal file
View File

@ -0,0 +1,105 @@
package clients
import (
"dero-swap/coin"
"log"
"github.com/lesismal/nbio/nbhttp/websocket"
)
type Swap_External struct {
Nickname string `json:"nickname"`
Dero float64 `json:"dero"`
XMR float64 `json:"xmr,omitempty"`
}
func IsExternalSwapAvailable(user string, pair string, amount float64) (ok bool, client *websocket.Conn) {
Clients.Range(func(key any, value any) bool {
c := value.(ClientInfo)
for _, p := range c.PairInfo {
if p.Pair == pair && p.Balance >= amount && user == c.Nickname {
ok = true
client = key.(*websocket.Conn)
return false
}
}
return true
})
return
}
func PrepareExternalSwap(user string, pair string, amount float64) (bool, *websocket.Conn) {
// only XMR swaps
if pair != coin.XMRDERO && pair != coin.DEROXMR {
log.Println("Only 3rd party XMR swaps")
return false, nil
}
ok, conn := IsExternalSwapAvailable(user, pair, amount)
if !ok {
log.Println("No 3rd party swaps available")
return false, nil
}
return true, conn
}
func (c *SwapState) ChangeClientState(mode uint, conn *websocket.Conn) {
c.Lock()
defer c.Unlock()
if mode == LOCK {
c.Client[conn] = true
} else {
c.Client[conn] = false
}
}
func (c *SwapState) CheckClientState(conn *websocket.Conn) bool {
c.RLock()
defer c.RUnlock()
return c.Client[conn]
}
func (c *SwapState) AddOrigin(conn *websocket.Conn, target *websocket.Conn) {
c.Lock()
defer c.Unlock()
c.Result[conn] = target
}
func (c *SwapState) GetOrigin(conn *websocket.Conn) *websocket.Conn {
c.RLock()
defer c.RUnlock()
return c.Result[conn]
}
func GetExternalBalances() (list []Swap_External) {
var entry Swap_External
Clients.Range(func(key any, value any) bool {
c := value.(ClientInfo)
entry.Nickname = c.Nickname
for _, p := range c.PairInfo {
switch p.Pair {
case coin.DEROXMR:
entry.XMR = p.Balance
case coin.XMRDERO:
entry.Dero = p.Balance
}
}
list = append(list, entry)
return true
})
return
}

31
clients/variables.go Normal file
View File

@ -0,0 +1,31 @@
package clients
import (
"sync"
"github.com/lesismal/nbio/nbhttp/websocket"
)
const (
LOCK = iota
UNLOCK
)
type (
ClientInfo struct {
PairInfo []PairInfo `json:"pair_info"`
Nickname string `json:"nickname"`
}
PairInfo struct {
Pair string `json:"pair"`
Balance float64 `json:"balance"`
}
)
type SwapState struct {
Client map[*websocket.Conn]bool
Result map[*websocket.Conn]*websocket.Conn
sync.RWMutex
}
var Clients sync.Map
var ActiveClients = SwapState{Client: make(map[*websocket.Conn]bool), Result: make(map[*websocket.Conn]*websocket.Conn)}

View File

@ -8,6 +8,7 @@ import (
"io"
"log"
"os"
"strings"
"net/http"
)
@ -19,17 +20,17 @@ func XTCGetCookie(pair string) bool {
switch pair {
case BTCDERO, DEROBTC:
if data, err = os.ReadFile(BTC_dir + "/.cookie"); err != nil {
if data, err = os.ReadFile(BTC_Dir + "/.cookie"); err != nil {
log.Printf("Can't load BTC auth cookie: %v\n", err)
return false
}
case LTCDERO, DEROLTC:
if data, err = os.ReadFile(LTC_dir + "/.cookie"); err != nil {
if data, err = os.ReadFile(LTC_Dir + "/.cookie"); err != nil {
log.Printf("Can't load LTC auth cookie: %v\n", err)
return false
}
case ARRRDERO, DEROARRR:
if data, err = os.ReadFile(ARRR_dir + "/.cookie"); err != nil {
if data, err = os.ReadFile(ARRR_Dir + "/.cookie"); err != nil {
log.Printf("Can't load ARRR auth cookie: %v\n", err)
return false
}
@ -391,7 +392,11 @@ func XTCGetBalance(pair string) float64 {
return 0
}
return RoundFloat(result.Result-Locked.GetLockedBalance(pair), 8)
if strings.HasPrefix(pair, "dero") {
result.Result -= Locked.GetLockedBalance(pair)
}
return RoundFloat(result.Result, 8)
}
func XTCSend(pair string, wallet string, amount float64) (bool, string) {

View File

@ -44,7 +44,7 @@ func (r *Swap) GetLockedBalance(coin string) float64 {
defer r.RUnlock()
switch coin {
case BTCDERO, LTCDERO, ARRRDERO:
case BTCDERO, LTCDERO, ARRRDERO, XMRDERO:
return r.Dero_balance
case DEROLTC:
return r.LTC_balance
@ -52,6 +52,8 @@ func (r *Swap) GetLockedBalance(coin string) float64 {
return r.BTC_balance
case DEROARRR:
return r.ARRR_balance
case DEROXMR:
return r.XMR_balance
default:
return 0
}
@ -62,7 +64,7 @@ func (r *Swap) AddLockedBalance(coin string, amount float64) {
defer r.Unlock()
switch coin {
case BTCDERO, LTCDERO, ARRRDERO:
case BTCDERO, LTCDERO, ARRRDERO, XMRDERO:
r.Dero_balance += amount
case DEROLTC:
r.LTC_balance += amount
@ -70,6 +72,8 @@ func (r *Swap) AddLockedBalance(coin string, amount float64) {
r.BTC_balance += amount
case DEROARRR:
r.ARRR_balance += amount
case DEROXMR:
r.XMR_balance += amount
}
}
@ -78,7 +82,7 @@ func (r *Swap) RemoveLockedBalance(coin string, amount float64) {
defer r.Unlock()
switch coin {
case BTCDERO, LTCDERO, ARRRDERO:
case BTCDERO, LTCDERO, ARRRDERO, XMRDERO:
r.Dero_balance -= amount
case DEROLTC:
r.LTC_balance -= amount
@ -86,6 +90,8 @@ func (r *Swap) RemoveLockedBalance(coin string, amount float64) {
r.BTC_balance -= amount
case DEROARRR:
r.ARRR_balance -= amount
case DEROXMR:
r.XMR_balance -= amount
}
}
@ -97,7 +103,6 @@ func (r *Swap) LoadLockedBalance() {
}
var swap_e Swap_Entry
var amount float64
for _, e := range dir_entries {
file_data, err := os.ReadFile("swaps/active/" + e.Name())
@ -110,7 +115,6 @@ func (r *Swap) LoadLockedBalance() {
}
switch swap_e.Coin {
case LTCDERO, BTCDERO, ARRRDERO, XMRDERO:
amount += swap_e.Amount
r.AddLockedBalance(swap_e.Coin, swap_e.Amount)
default:
r.AddLockedBalance(swap_e.Coin, swap_e.Price)

View File

@ -10,6 +10,7 @@ type (
Pair string `json:"pair"`
Amount float64 `json:"amount"`
DeroAddr string `json:"dero_address"`
Extern string `json:"extern,omitempty"`
}
Swap_Response struct {
ID int64 `json:"id"`
@ -19,6 +20,10 @@ type (
Error string `json:"error,omitempty"`
Request Swap_Request `json:"request"`
}
Swap_Tracking struct {
ID int64 `json:"id"`
State uint64 `json:"state"`
}
Swap_Entry struct {
Coin string `json:"coin"`
Wallet string `json:"wallet"`
@ -29,6 +34,7 @@ type (
Block uint64 `json:"block"`
Balance float64 `json:"balance"`
Status uint64 `json:"status"`
Txid string `json:"txid"`
}
Swap struct {
Dero_balance float64
@ -49,4 +55,4 @@ var XTC_Daemon = &http.Client{}
var XTC_auth string
var BTC_address, LTC_address, ARRR_address, XMR_address string
var BTC_dir, LTC_dir, ARRR_dir string
var BTC_Dir, LTC_Dir, ARRR_Dir string

View File

@ -15,6 +15,8 @@ import (
const atomicUnits float64 = 100000
const TxFee float64 = 0.0004
var RPC_Login string
var Dero_Wallet jsonrpc.RPCClient
func AddTX(wallet string, amount float64) rpc.Transfer {
@ -34,7 +36,7 @@ func GetHeight() uint64 {
err = result.GetObject(&response)
if err != nil {
log.Printf("Error getting DERO wallet height: %v\n", err)
log.Printf("Error checking DERO wallet height: %v\n", err)
return 0
}
@ -55,7 +57,7 @@ func GetBalance() float64 {
err = result.GetObject(&response)
if err != nil {
log.Printf("Error getting DERO wallet balance: %v\n", err)
log.Printf("Error checking DERO wallet balance: %v\n", err)
return 0
}
@ -65,6 +67,27 @@ func GetBalance() float64 {
return coin.RoundFloat(balance_fl, 5)
}
func GetAddress() string {
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
result, err := Dero_Wallet.Call(ctx, "getaddress")
cancel()
if err != nil {
return ""
}
var response rpc.GetAddress_Result
err = result.GetObject(&response)
if err != nil {
log.Printf("Error checking DERO wallet address: %v\n", err)
return ""
}
return response.Address
}
func Payout(tx []rpc.Transfer) {
var tries uint

View File

@ -46,11 +46,11 @@ func XMRGetTX(payment string, block uint64) bool {
err = result.GetObject(&response)
if err != nil {
log.Printf("Error getting XMR incoming payments: %v\n", err)
log.Printf("Error checking XMR incoming payments: %v\n", err)
return false
}
// placeholder
// todo
for _, p := range response.Payments {
if p.UnlockTime > 0 {
return false
@ -99,7 +99,7 @@ func GetBalance() float64 {
err = result.GetObject(&response)
if err != nil {
log.Printf("Error getting XMR wallet balance: %v\n", err)
log.Printf("Error checking XMR wallet balance: %v\n", err)
return 0
}
@ -119,7 +119,7 @@ func GetAddress() string {
err = result.GetObject(&response)
if err != nil {
log.Printf("Error getting XMR wallet address: %v\n", err)
log.Printf("Error checking XMR wallet address: %v\n", err)
return ""
}

View File

@ -3,6 +3,7 @@ package main
import (
"bytes"
"dero-swap/cfg"
"dero-swap/clients"
"dero-swap/coin"
"dero-swap/dero"
"dero-swap/monero"
@ -299,5 +300,7 @@ func UpdatePool() Swap_Balance {
}
}
balance.External = clients.GetExternalBalances()
return balance
}

View File

@ -1,6 +1,9 @@
package main
import "sync"
import (
"dero-swap/clients"
"sync"
)
type (
Price_Provider struct {
@ -39,17 +42,18 @@ type (
BTC float64 `json:"btc,omitempty"`
ARRR float64 `json:"arrr,omitempty"`
XMR float64 `json:"xmr,omitempty"`
External []clients.Swap_External `json:"external,omitempty"`
}
)
const (
ASK = iota
BID = iota
MEDIAN = iota
BID
MEDIAN
)
const (
TO = iota
XEGGEX = iota
XEGGEX
)
const SATOSHI float64 = 1e-08

103
server.go
View File

@ -9,6 +9,7 @@ import (
"os"
"strings"
"sync"
"time"
"github.com/lesismal/llib/std/crypto/tls"
@ -17,6 +18,7 @@ import (
"github.com/lesismal/nbio/nbhttp/websocket"
"dero-swap/cfg"
"dero-swap/clients"
"dero-swap/coin"
"dero-swap/dero"
)
@ -122,6 +124,7 @@ func newUpgrader() *websocket.Upgrader {
u.OnClose(func(c *websocket.Conn, err error) {
WSConnections.Delete(c)
clients.Clients.Delete(c)
})
u.OnMessage(func(c *websocket.Conn, messageType websocket.MessageType, data []byte) {
@ -148,10 +151,35 @@ func newUpgrader() *websocket.Upgrader {
var response coin.Swap_Response
p := in.Params.(map[string]any)
out.Method = "swap"
request.Pair = p["pair"].(string)
request.Amount = p["amount"].(float64)
request.DeroAddr = p["dero_address"].(string)
if d, ok := p["pair"]; ok {
request.Pair = d.(string)
}
if d, ok := p["amount"]; ok {
request.Amount = d.(float64)
}
if d, ok := p["dero_address"]; ok {
request.DeroAddr = d.(string)
}
if q, ok := p["extern"]; ok && q.(string) != "" {
if ok, conn := clients.PrepareExternalSwap(q.(string), request.Pair, request.Amount); ok {
clients.ActiveClients.ChangeClientState(clients.LOCK, conn)
clients.ActiveClients.AddOrigin(conn, c)
out.Params = request
encoder.Encode(out)
SendWSData(conn, send.Bytes())
} else {
response.Error = "External swap not possible"
}
out.Result = response
encoder.Encode(out)
SendWSData(c, send.Bytes())
return
}
switch request.Pair {
case coin.BTCDERO, coin.LTCDERO, coin.ARRRDERO, coin.XMRDERO:
@ -161,11 +189,32 @@ func newUpgrader() *websocket.Upgrader {
default:
}
out.Method = "swap"
out.Result = response
encoder.Encode(out)
SendWSData(c, send.Bytes())
var track coin.Swap_Tracking
track.ID = response.ID
out.Method = "track"
go func() {
for {
time.Sleep(time.Second * 15)
track.State = SwapTracking(response.ID)
out.Result = track
send.Reset()
encoder.Encode(out)
if _, ok := WSConnections.Load(c); ok {
SendWSData(c, send.Bytes())
} else {
break
}
if track.State == SWAP_DONE || track.State == SWAP_EXPIRED {
break
}
}
}()
case "market":
mk.RLock()
@ -194,6 +243,37 @@ func newUpgrader() *websocket.Upgrader {
SendWSData(c, data.Bytes())
case "client":
var client clients.ClientInfo
p := in.Params.(map[string]any)
client.Nickname = p["nickname"].(string)
q := p["pair_info"].([]any)
for i := range q {
r := q[i].(map[string]any)
client.PairInfo = append(client.PairInfo, clients.PairInfo{Balance: r["balance"].(float64), Pair: r["pair"].(string)})
}
if _, ok := clients.Clients.Load(c); !ok {
log.Printf("Client Hello from %s\n", client.Nickname)
}
clients.Clients.Store(c, client)
case "client_ok":
if clients.ActiveClients.CheckClientState(c) {
clients.ActiveClients.ChangeClientState(clients.UNLOCK, c)
client := clients.ActiveClients.GetOrigin(c)
out.Method = "swap"
out.Result = in.Result
encoder.Encode(out)
SendWSData(client, send.Bytes())
}
default:
}
@ -247,28 +327,27 @@ func StartServer() {
// certFile = fullchain.pem
// keyFile = privkey.pem
// uncomment the following block to enable TLS; edit cert files first
/*
// comment the following block to disable TLS
cert, err := tls.LoadX509KeyPair("/etc/letsencrypt/live/mg25ot4aggt8dprv.myfritz.net/fullchain.pem", "/etc/letsencrypt/live/mg25ot4aggt8dprv.myfritz.net/privkey.pem")
if err != nil {
log.Println(err)
os.Exit(2)
}
*/
mux := http.NewServeMux()
mux.HandleFunc("/ws", webSocketHandler)
//mux.HandleFunc("/api", )
srv := nbhttp.NewServer(nbhttp.Config{
Network: "tcp",
Handler: mux,
// uncomment the following 2 lines and comment "Addrs" to start server with TLS
//AddrsTLS: []string{cfg.Settings.ListenAddress},
//TLSConfig: &tls.Config{Certificates: []tls.Certificate{cert}},
Addrs: []string{cfg.Settings.ListenAddress},
// comment the following 2 lines and uncomment "Addrs" to start server without TLS
AddrsTLS: []string{cfg.Settings.ListenAddress},
TLSConfig: &tls.Config{Certificates: []tls.Certificate{cert}},
//Addrs: []string{cfg.Settings.ListenAddress},
})
err := srv.Start()
err = srv.Start()
if err != nil {
log.Println(err)
os.Exit(2)

13
swap.go
View File

@ -84,10 +84,15 @@ func XTCSwap(pair string, dst_addr string, amount float64, resp *coin.Swap_Respo
coin.Locked.AddLockedBalance(pair, amount)
// create/get a deposit address
if pair != coin.XMRDERO {
resp.Wallet = coin.XTCGetAddress(pair)
} else {
switch pair {
case coin.BTCDERO:
resp.Wallet = coin.BTC_address
case coin.LTCDERO:
resp.Wallet = coin.LTC_address
case coin.XMRDERO:
resp.Wallet = monero.MakeIntegratedAddress()
case coin.ARRRDERO:
resp.Wallet = coin.ARRR_address
}
if resp.Wallet == "" {
return fmt.Errorf("no swap deposit address available")
@ -171,7 +176,7 @@ func DeroXTCSwap(pair string, dst_addr string, amount float64, resp *coin.Swap_R
coin_value = mk.Pairs.DEROBTC
fees = cfg.SwapFees.Withdrawal.DeroBTC
case coin.DEROXMR:
coin_value = mk.Pairs.XMR
coin_value = mk.Pairs.DEROXMR
fees = cfg.SwapFees.Withdrawal.DeroXMR
}

View File

@ -14,6 +14,15 @@ import (
"github.com/deroproject/derohe/rpc"
)
const (
SWAP_CREATED = iota
SWAP_CONFIRMED
SWAP_DONE
SWAP_EXPIRED
SWAP_TOO_OLD
SWAP_UNDEFINED
)
func Swap_Controller() {
var file_data []byte
@ -30,6 +39,10 @@ func Swap_Controller() {
time.Sleep(time.Minute)
dir_entries, err = os.ReadDir("swaps/active")
if err != nil {
log.Println("Can't list swap entries")
continue
}
expired = 0
fails = 0
@ -57,7 +70,7 @@ func Swap_Controller() {
creation_t := time.UnixMilli(swap_e.Created)
// if there was no deposit, mark the request as expired
if swap_e.Status == 0 && time.Since(creation_t) > time.Hour {
if swap_e.Status == SWAP_CREATED && time.Since(creation_t) > time.Hour {
os.WriteFile(fmt.Sprintf("swaps/expired/%d", swap_e.Created), file_data, 0644)
os.Remove("swaps/active/" + e.Name())
switch swap_e.Coin {
@ -82,7 +95,7 @@ func Swap_Controller() {
found_deposit = monero.XMRGetTX(payment_id, swap_e.Block)
visible = found_deposit
} else {
log.Println("Can't split intragrated XMR address")
log.Println("Can't split integrated XMR address")
}
default:
found_deposit = dero.CheckIncomingTransfers(uint64(swap_e.Created), swap_e.Block)
@ -96,7 +109,7 @@ func Swap_Controller() {
}
// mark request as done
if swap_e.Status == 2 {
if swap_e.Status == SWAP_DONE {
err = os.WriteFile(fmt.Sprintf("swaps/done/%d", swap_e.Created), file_data, 0644)
if err != nil {
log.Printf("Can't mark swap as done, swap %d, err %v\n", swap_e.Created, err)
@ -108,7 +121,8 @@ func Swap_Controller() {
// start payout if there are at least 2 confirmations
// requests won't be marked as expired, if there is already 1 confirmation
if visible {
if found_deposit && swap_e.Status <= 1 {
log.Printf("Found TX for ID %d (%s) on chain\n", swap_e.Created, swap_e.Coin)
if found_deposit && swap_e.Status <= SWAP_CONFIRMED {
// create transaction
log.Printf("Found deposit for ID %d (%s): %.8f coins; adding to payout TX\n", swap_e.Created, swap_e.Coin, swap_e.Amount)
@ -116,7 +130,7 @@ func Swap_Controller() {
case coin.DEROLTC, coin.DEROBTC:
log.Println("Starting LTC/BTC payout")
_, txid := coin.XTCSend(swap_e.Coin, swap_e.Destination, swap_e.Price)
log.Printf("LTC TXID: %s\n", txid)
log.Printf("LTC/BTC TXID: %s\n", txid)
coin.Locked.RemoveLockedBalance(swap_e.Coin, swap_e.Price)
case coin.DEROARRR:
log.Println("Starting ARRR payout")
@ -129,18 +143,18 @@ func Swap_Controller() {
txs = append(txs, dero.AddTX(swap_e.Destination, swap_e.Amount))
}
swap_e.Status = 2
swap_e.Status = SWAP_DONE
sent++
active--
} else {
// transaction was confirmed
swap_e.Status = 1
swap_e.Status = SWAP_CONFIRMED
}
json_data, _ := json.Marshal(&swap_e)
os.WriteFile("swaps/active/"+e.Name(), json_data, 0644)
if swap_e.Status == 2 {
if swap_e.Status == SWAP_DONE {
err = os.WriteFile(fmt.Sprintf("swaps/done/%d", swap_e.Created), file_data, 0644)
if err != nil {
log.Printf("Can't mark swap as done, swap %d, err %v\n", swap_e.Created, err)
@ -171,3 +185,29 @@ func Swap_Controller() {
}
}
}
func SwapTracking(session int64) uint64 {
if time.Since(time.UnixMilli(int64(session))) > time.Hour*24*3 {
return SWAP_TOO_OLD
}
if _, err := os.ReadFile("swaps/expired/" + fmt.Sprintf("%d", session)); err == nil {
return SWAP_EXPIRED
}
if _, err := os.ReadFile("swaps/done/" + fmt.Sprintf("%d", session)); err == nil {
return SWAP_DONE
}
var swap coin.Swap_Entry
if fd, err := os.ReadFile("swaps/active/" + fmt.Sprintf("%d", session)); err == nil {
if err = json.Unmarshal(fd, &swap); err == nil {
return swap.Status
} else {
log.Println(err)
}
} else {
log.Println(err)
}
return SWAP_UNDEFINED
}