swap client support
This commit is contained in:
parent
cfa71f8203
commit
ddfc1bb8aa
@ -4,6 +4,7 @@ import (
|
|||||||
"dero-swap/coin"
|
"dero-swap/coin"
|
||||||
"dero-swap/dero"
|
"dero-swap/dero"
|
||||||
"dero-swap/monero"
|
"dero-swap/monero"
|
||||||
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
@ -26,13 +27,24 @@ func LoadConfig() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dero.Dero_Daemon = jsonrpc.NewClient("http://" + Settings.Dero_daemon + "/json_rpc")
|
dero.Dero_Daemon = jsonrpc.NewClient("http://" + Settings.Dero_Daemon + "/json_rpc")
|
||||||
dero.Dero_Wallet = jsonrpc.NewClient("http://" + Settings.Dero_wallet + "/json_rpc")
|
if Settings.Dero_Login != "" {
|
||||||
monero.Monero_Wallet = jsonrpc.NewClient("http://" + Settings.Monero_wallet + "/json_rpc")
|
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
|
monero.Monero_Wallet = jsonrpc.NewClient("http://" + Settings.Monero_Wallet + "/json_rpc")
|
||||||
coin.XTC_URL[coin.LTCDERO] = "http://" + Settings.LTC_daemon
|
|
||||||
coin.XTC_URL[coin.ARRRDERO] = "http://" + Settings.ARRR_daemon
|
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"
|
// check if pair is "supported"
|
||||||
for _, p := range Settings.Pairs {
|
for _, p := range Settings.Pairs {
|
||||||
@ -75,7 +87,7 @@ func LoadFees() {
|
|||||||
// basic config check
|
// basic config check
|
||||||
func CheckConfig() bool {
|
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")
|
log.Println("Dero Daemon or Dero Wallet is not set")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -83,38 +95,44 @@ func CheckConfig() bool {
|
|||||||
for p := range coin.Pairs {
|
for p := range coin.Pairs {
|
||||||
switch p {
|
switch p {
|
||||||
case coin.BTCDERO, coin.DEROBTC:
|
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)
|
log.Printf("%s pair is set, but daemon or directory is not set\n", p)
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
coin.BTC_dir = Settings.BTC_dir
|
coin.BTC_Dir = Settings.BTC_Dir
|
||||||
}
|
}
|
||||||
case coin.LTCDERO, coin.DEROLTC:
|
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)
|
log.Printf("%s pair is set, but daemon or directory is not set\n", p)
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
coin.LTC_dir = Settings.LTC_dir
|
coin.LTC_Dir = Settings.LTC_Dir
|
||||||
}
|
}
|
||||||
case coin.ARRRDERO, coin.DEROARRR:
|
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)
|
log.Printf("%s pair is set, but daemon or directory is not set\n", p)
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
coin.ARRR_dir = Settings.ARRR_dir
|
coin.ARRR_Dir = Settings.ARRR_Dir
|
||||||
}
|
}
|
||||||
case coin.XMRDERO, coin.DEROXMR:
|
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)
|
log.Printf("%s pair is set, but wallet is not set\n", p)
|
||||||
return false
|
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")
|
log.Println("Dero daemon or wallet is not available")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
log.Printf("%-14s: %s\n", "Dero Wallet", dero_wallet)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -2,16 +2,17 @@ package cfg
|
|||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
ListenAddress string `json:"listen"`
|
ListenAddress string `json:"listen"`
|
||||||
BTC_daemon string `json:"btc_daemon"`
|
BTC_Daemon string `json:"BTC_Daemon"`
|
||||||
BTC_dir string `json:"btc_dir"`
|
BTC_Dir string `json:"BTC_Dir"`
|
||||||
LTC_daemon string `json:"ltc_daemon"`
|
LTC_Daemon string `json:"LTC_Daemon"`
|
||||||
LTC_dir string `json:"ltc_dir"`
|
LTC_Dir string `json:"LTC_Dir"`
|
||||||
ARRR_daemon string `json:"arrr_daemon"`
|
ARRR_Daemon string `json:"ARRR_Daemon"`
|
||||||
ARRR_dir string `json:"arrr_dir"`
|
ARRR_Dir string `json:"ARRR_Dir"`
|
||||||
Dero_daemon string `json:"dero_daemon"`
|
Dero_Daemon string `json:"Dero_Daemon"`
|
||||||
Dero_wallet string `json:"dero_wallet"`
|
Dero_Wallet string `json:"dero_wallet"`
|
||||||
Monero_daemon string `json:"monero_daemon"`
|
Dero_Login string `json:"dero_login"`
|
||||||
Monero_wallet string `json:"monero_wallet"`
|
Monero_Daemon string `json:"monero_daemon"`
|
||||||
|
Monero_Wallet string `json:"Monero_Wallet"`
|
||||||
Pairs []string `json:"pairs"`
|
Pairs []string `json:"pairs"`
|
||||||
//SwapFees float64 `json:"swap_fees"`
|
//SwapFees float64 `json:"swap_fees"`
|
||||||
}
|
}
|
||||||
@ -46,4 +47,4 @@ type (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var Settings Config
|
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
105
clients/clients.go
Normal 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
31
clients/variables.go
Normal 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)}
|
13
coin/btc.go
13
coin/btc.go
@ -8,6 +8,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
@ -19,17 +20,17 @@ func XTCGetCookie(pair string) bool {
|
|||||||
|
|
||||||
switch pair {
|
switch pair {
|
||||||
case BTCDERO, DEROBTC:
|
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)
|
log.Printf("Can't load BTC auth cookie: %v\n", err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case LTCDERO, DEROLTC:
|
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)
|
log.Printf("Can't load LTC auth cookie: %v\n", err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case ARRRDERO, DEROARRR:
|
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)
|
log.Printf("Can't load ARRR auth cookie: %v\n", err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -391,7 +392,11 @@ func XTCGetBalance(pair string) float64 {
|
|||||||
return 0
|
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) {
|
func XTCSend(pair string, wallet string, amount float64) (bool, string) {
|
||||||
|
@ -44,7 +44,7 @@ func (r *Swap) GetLockedBalance(coin string) float64 {
|
|||||||
defer r.RUnlock()
|
defer r.RUnlock()
|
||||||
|
|
||||||
switch coin {
|
switch coin {
|
||||||
case BTCDERO, LTCDERO, ARRRDERO:
|
case BTCDERO, LTCDERO, ARRRDERO, XMRDERO:
|
||||||
return r.Dero_balance
|
return r.Dero_balance
|
||||||
case DEROLTC:
|
case DEROLTC:
|
||||||
return r.LTC_balance
|
return r.LTC_balance
|
||||||
@ -52,6 +52,8 @@ func (r *Swap) GetLockedBalance(coin string) float64 {
|
|||||||
return r.BTC_balance
|
return r.BTC_balance
|
||||||
case DEROARRR:
|
case DEROARRR:
|
||||||
return r.ARRR_balance
|
return r.ARRR_balance
|
||||||
|
case DEROXMR:
|
||||||
|
return r.XMR_balance
|
||||||
default:
|
default:
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -62,7 +64,7 @@ func (r *Swap) AddLockedBalance(coin string, amount float64) {
|
|||||||
defer r.Unlock()
|
defer r.Unlock()
|
||||||
|
|
||||||
switch coin {
|
switch coin {
|
||||||
case BTCDERO, LTCDERO, ARRRDERO:
|
case BTCDERO, LTCDERO, ARRRDERO, XMRDERO:
|
||||||
r.Dero_balance += amount
|
r.Dero_balance += amount
|
||||||
case DEROLTC:
|
case DEROLTC:
|
||||||
r.LTC_balance += amount
|
r.LTC_balance += amount
|
||||||
@ -70,6 +72,8 @@ func (r *Swap) AddLockedBalance(coin string, amount float64) {
|
|||||||
r.BTC_balance += amount
|
r.BTC_balance += amount
|
||||||
case DEROARRR:
|
case DEROARRR:
|
||||||
r.ARRR_balance += amount
|
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()
|
defer r.Unlock()
|
||||||
|
|
||||||
switch coin {
|
switch coin {
|
||||||
case BTCDERO, LTCDERO, ARRRDERO:
|
case BTCDERO, LTCDERO, ARRRDERO, XMRDERO:
|
||||||
r.Dero_balance -= amount
|
r.Dero_balance -= amount
|
||||||
case DEROLTC:
|
case DEROLTC:
|
||||||
r.LTC_balance -= amount
|
r.LTC_balance -= amount
|
||||||
@ -86,6 +90,8 @@ func (r *Swap) RemoveLockedBalance(coin string, amount float64) {
|
|||||||
r.BTC_balance -= amount
|
r.BTC_balance -= amount
|
||||||
case DEROARRR:
|
case DEROARRR:
|
||||||
r.ARRR_balance -= amount
|
r.ARRR_balance -= amount
|
||||||
|
case DEROXMR:
|
||||||
|
r.XMR_balance -= amount
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +103,6 @@ func (r *Swap) LoadLockedBalance() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var swap_e Swap_Entry
|
var swap_e Swap_Entry
|
||||||
var amount float64
|
|
||||||
|
|
||||||
for _, e := range dir_entries {
|
for _, e := range dir_entries {
|
||||||
file_data, err := os.ReadFile("swaps/active/" + e.Name())
|
file_data, err := os.ReadFile("swaps/active/" + e.Name())
|
||||||
@ -110,7 +115,6 @@ func (r *Swap) LoadLockedBalance() {
|
|||||||
}
|
}
|
||||||
switch swap_e.Coin {
|
switch swap_e.Coin {
|
||||||
case LTCDERO, BTCDERO, ARRRDERO, XMRDERO:
|
case LTCDERO, BTCDERO, ARRRDERO, XMRDERO:
|
||||||
amount += swap_e.Amount
|
|
||||||
r.AddLockedBalance(swap_e.Coin, swap_e.Amount)
|
r.AddLockedBalance(swap_e.Coin, swap_e.Amount)
|
||||||
default:
|
default:
|
||||||
r.AddLockedBalance(swap_e.Coin, swap_e.Price)
|
r.AddLockedBalance(swap_e.Coin, swap_e.Price)
|
||||||
|
@ -10,6 +10,7 @@ type (
|
|||||||
Pair string `json:"pair"`
|
Pair string `json:"pair"`
|
||||||
Amount float64 `json:"amount"`
|
Amount float64 `json:"amount"`
|
||||||
DeroAddr string `json:"dero_address"`
|
DeroAddr string `json:"dero_address"`
|
||||||
|
Extern string `json:"extern,omitempty"`
|
||||||
}
|
}
|
||||||
Swap_Response struct {
|
Swap_Response struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
@ -19,6 +20,10 @@ type (
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
Request Swap_Request `json:"request"`
|
Request Swap_Request `json:"request"`
|
||||||
}
|
}
|
||||||
|
Swap_Tracking struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
State uint64 `json:"state"`
|
||||||
|
}
|
||||||
Swap_Entry struct {
|
Swap_Entry struct {
|
||||||
Coin string `json:"coin"`
|
Coin string `json:"coin"`
|
||||||
Wallet string `json:"wallet"`
|
Wallet string `json:"wallet"`
|
||||||
@ -29,6 +34,7 @@ type (
|
|||||||
Block uint64 `json:"block"`
|
Block uint64 `json:"block"`
|
||||||
Balance float64 `json:"balance"`
|
Balance float64 `json:"balance"`
|
||||||
Status uint64 `json:"status"`
|
Status uint64 `json:"status"`
|
||||||
|
Txid string `json:"txid"`
|
||||||
}
|
}
|
||||||
Swap struct {
|
Swap struct {
|
||||||
Dero_balance float64
|
Dero_balance float64
|
||||||
@ -49,4 +55,4 @@ var XTC_Daemon = &http.Client{}
|
|||||||
var XTC_auth string
|
var XTC_auth string
|
||||||
|
|
||||||
var BTC_address, LTC_address, ARRR_address, XMR_address 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
|
||||||
|
@ -15,6 +15,8 @@ import (
|
|||||||
const atomicUnits float64 = 100000
|
const atomicUnits float64 = 100000
|
||||||
const TxFee float64 = 0.0004
|
const TxFee float64 = 0.0004
|
||||||
|
|
||||||
|
var RPC_Login string
|
||||||
|
|
||||||
var Dero_Wallet jsonrpc.RPCClient
|
var Dero_Wallet jsonrpc.RPCClient
|
||||||
|
|
||||||
func AddTX(wallet string, amount float64) rpc.Transfer {
|
func AddTX(wallet string, amount float64) rpc.Transfer {
|
||||||
@ -34,7 +36,7 @@ func GetHeight() uint64 {
|
|||||||
|
|
||||||
err = result.GetObject(&response)
|
err = result.GetObject(&response)
|
||||||
if err != nil {
|
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
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,7 +57,7 @@ func GetBalance() float64 {
|
|||||||
|
|
||||||
err = result.GetObject(&response)
|
err = result.GetObject(&response)
|
||||||
if err != nil {
|
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
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,6 +67,27 @@ func GetBalance() float64 {
|
|||||||
return coin.RoundFloat(balance_fl, 5)
|
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) {
|
func Payout(tx []rpc.Transfer) {
|
||||||
|
|
||||||
var tries uint
|
var tries uint
|
||||||
|
@ -46,11 +46,11 @@ func XMRGetTX(payment string, block uint64) bool {
|
|||||||
|
|
||||||
err = result.GetObject(&response)
|
err = result.GetObject(&response)
|
||||||
if err != nil {
|
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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// placeholder
|
// todo
|
||||||
for _, p := range response.Payments {
|
for _, p := range response.Payments {
|
||||||
if p.UnlockTime > 0 {
|
if p.UnlockTime > 0 {
|
||||||
return false
|
return false
|
||||||
@ -99,7 +99,7 @@ func GetBalance() float64 {
|
|||||||
|
|
||||||
err = result.GetObject(&response)
|
err = result.GetObject(&response)
|
||||||
if err != nil {
|
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
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +119,7 @@ func GetAddress() string {
|
|||||||
|
|
||||||
err = result.GetObject(&response)
|
err = result.GetObject(&response)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error getting XMR wallet address: %v\n", err)
|
log.Printf("Error checking XMR wallet address: %v\n", err)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
price.go
3
price.go
@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"dero-swap/cfg"
|
"dero-swap/cfg"
|
||||||
|
"dero-swap/clients"
|
||||||
"dero-swap/coin"
|
"dero-swap/coin"
|
||||||
"dero-swap/dero"
|
"dero-swap/dero"
|
||||||
"dero-swap/monero"
|
"dero-swap/monero"
|
||||||
@ -299,5 +300,7 @@ func UpdatePool() Swap_Balance {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
balance.External = clients.GetExternalBalances()
|
||||||
|
|
||||||
return balance
|
return balance
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "sync"
|
import (
|
||||||
|
"dero-swap/clients"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Price_Provider struct {
|
Price_Provider struct {
|
||||||
@ -39,17 +42,18 @@ type (
|
|||||||
BTC float64 `json:"btc,omitempty"`
|
BTC float64 `json:"btc,omitempty"`
|
||||||
ARRR float64 `json:"arrr,omitempty"`
|
ARRR float64 `json:"arrr,omitempty"`
|
||||||
XMR float64 `json:"xmr,omitempty"`
|
XMR float64 `json:"xmr,omitempty"`
|
||||||
|
External []clients.Swap_External `json:"external,omitempty"`
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ASK = iota
|
ASK = iota
|
||||||
BID = iota
|
BID
|
||||||
MEDIAN = iota
|
MEDIAN
|
||||||
)
|
)
|
||||||
const (
|
const (
|
||||||
TO = iota
|
TO = iota
|
||||||
XEGGEX = iota
|
XEGGEX
|
||||||
)
|
)
|
||||||
const SATOSHI float64 = 1e-08
|
const SATOSHI float64 = 1e-08
|
||||||
|
|
||||||
|
103
server.go
103
server.go
@ -9,6 +9,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/lesismal/llib/std/crypto/tls"
|
"github.com/lesismal/llib/std/crypto/tls"
|
||||||
|
|
||||||
@ -17,6 +18,7 @@ import (
|
|||||||
"github.com/lesismal/nbio/nbhttp/websocket"
|
"github.com/lesismal/nbio/nbhttp/websocket"
|
||||||
|
|
||||||
"dero-swap/cfg"
|
"dero-swap/cfg"
|
||||||
|
"dero-swap/clients"
|
||||||
"dero-swap/coin"
|
"dero-swap/coin"
|
||||||
"dero-swap/dero"
|
"dero-swap/dero"
|
||||||
)
|
)
|
||||||
@ -122,6 +124,7 @@ func newUpgrader() *websocket.Upgrader {
|
|||||||
|
|
||||||
u.OnClose(func(c *websocket.Conn, err error) {
|
u.OnClose(func(c *websocket.Conn, err error) {
|
||||||
WSConnections.Delete(c)
|
WSConnections.Delete(c)
|
||||||
|
clients.Clients.Delete(c)
|
||||||
})
|
})
|
||||||
|
|
||||||
u.OnMessage(func(c *websocket.Conn, messageType websocket.MessageType, data []byte) {
|
u.OnMessage(func(c *websocket.Conn, messageType websocket.MessageType, data []byte) {
|
||||||
@ -148,10 +151,35 @@ func newUpgrader() *websocket.Upgrader {
|
|||||||
var response coin.Swap_Response
|
var response coin.Swap_Response
|
||||||
|
|
||||||
p := in.Params.(map[string]any)
|
p := in.Params.(map[string]any)
|
||||||
|
out.Method = "swap"
|
||||||
|
|
||||||
request.Pair = p["pair"].(string)
|
if d, ok := p["pair"]; ok {
|
||||||
request.Amount = p["amount"].(float64)
|
request.Pair = d.(string)
|
||||||
request.DeroAddr = p["dero_address"].(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 {
|
switch request.Pair {
|
||||||
case coin.BTCDERO, coin.LTCDERO, coin.ARRRDERO, coin.XMRDERO:
|
case coin.BTCDERO, coin.LTCDERO, coin.ARRRDERO, coin.XMRDERO:
|
||||||
@ -161,11 +189,32 @@ func newUpgrader() *websocket.Upgrader {
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
out.Method = "swap"
|
|
||||||
out.Result = response
|
out.Result = response
|
||||||
encoder.Encode(out)
|
encoder.Encode(out)
|
||||||
|
|
||||||
SendWSData(c, send.Bytes())
|
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":
|
case "market":
|
||||||
|
|
||||||
mk.RLock()
|
mk.RLock()
|
||||||
@ -194,6 +243,37 @@ func newUpgrader() *websocket.Upgrader {
|
|||||||
|
|
||||||
SendWSData(c, data.Bytes())
|
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:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,28 +327,27 @@ func StartServer() {
|
|||||||
// certFile = fullchain.pem
|
// certFile = fullchain.pem
|
||||||
// keyFile = privkey.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")
|
cert, err := tls.LoadX509KeyPair("/etc/letsencrypt/live/mg25ot4aggt8dprv.myfritz.net/fullchain.pem", "/etc/letsencrypt/live/mg25ot4aggt8dprv.myfritz.net/privkey.pem")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
mux.HandleFunc("/ws", webSocketHandler)
|
mux.HandleFunc("/ws", webSocketHandler)
|
||||||
|
//mux.HandleFunc("/api", )
|
||||||
|
|
||||||
srv := nbhttp.NewServer(nbhttp.Config{
|
srv := nbhttp.NewServer(nbhttp.Config{
|
||||||
Network: "tcp",
|
Network: "tcp",
|
||||||
Handler: mux,
|
Handler: mux,
|
||||||
// uncomment the following 2 lines and comment "Addrs" to start server with TLS
|
// comment the following 2 lines and uncomment "Addrs" to start server without TLS
|
||||||
//AddrsTLS: []string{cfg.Settings.ListenAddress},
|
AddrsTLS: []string{cfg.Settings.ListenAddress},
|
||||||
//TLSConfig: &tls.Config{Certificates: []tls.Certificate{cert}},
|
TLSConfig: &tls.Config{Certificates: []tls.Certificate{cert}},
|
||||||
Addrs: []string{cfg.Settings.ListenAddress},
|
//Addrs: []string{cfg.Settings.ListenAddress},
|
||||||
})
|
})
|
||||||
|
|
||||||
err := srv.Start()
|
err = srv.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
|
13
swap.go
13
swap.go
@ -84,10 +84,15 @@ func XTCSwap(pair string, dst_addr string, amount float64, resp *coin.Swap_Respo
|
|||||||
coin.Locked.AddLockedBalance(pair, amount)
|
coin.Locked.AddLockedBalance(pair, amount)
|
||||||
|
|
||||||
// create/get a deposit address
|
// create/get a deposit address
|
||||||
if pair != coin.XMRDERO {
|
switch pair {
|
||||||
resp.Wallet = coin.XTCGetAddress(pair)
|
case coin.BTCDERO:
|
||||||
} else {
|
resp.Wallet = coin.BTC_address
|
||||||
|
case coin.LTCDERO:
|
||||||
|
resp.Wallet = coin.LTC_address
|
||||||
|
case coin.XMRDERO:
|
||||||
resp.Wallet = monero.MakeIntegratedAddress()
|
resp.Wallet = monero.MakeIntegratedAddress()
|
||||||
|
case coin.ARRRDERO:
|
||||||
|
resp.Wallet = coin.ARRR_address
|
||||||
}
|
}
|
||||||
if resp.Wallet == "" {
|
if resp.Wallet == "" {
|
||||||
return fmt.Errorf("no swap deposit address available")
|
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
|
coin_value = mk.Pairs.DEROBTC
|
||||||
fees = cfg.SwapFees.Withdrawal.DeroBTC
|
fees = cfg.SwapFees.Withdrawal.DeroBTC
|
||||||
case coin.DEROXMR:
|
case coin.DEROXMR:
|
||||||
coin_value = mk.Pairs.XMR
|
coin_value = mk.Pairs.DEROXMR
|
||||||
fees = cfg.SwapFees.Withdrawal.DeroXMR
|
fees = cfg.SwapFees.Withdrawal.DeroXMR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,15 @@ import (
|
|||||||
"github.com/deroproject/derohe/rpc"
|
"github.com/deroproject/derohe/rpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SWAP_CREATED = iota
|
||||||
|
SWAP_CONFIRMED
|
||||||
|
SWAP_DONE
|
||||||
|
SWAP_EXPIRED
|
||||||
|
SWAP_TOO_OLD
|
||||||
|
SWAP_UNDEFINED
|
||||||
|
)
|
||||||
|
|
||||||
func Swap_Controller() {
|
func Swap_Controller() {
|
||||||
|
|
||||||
var file_data []byte
|
var file_data []byte
|
||||||
@ -30,6 +39,10 @@ func Swap_Controller() {
|
|||||||
|
|
||||||
time.Sleep(time.Minute)
|
time.Sleep(time.Minute)
|
||||||
dir_entries, err = os.ReadDir("swaps/active")
|
dir_entries, err = os.ReadDir("swaps/active")
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Can't list swap entries")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
expired = 0
|
expired = 0
|
||||||
fails = 0
|
fails = 0
|
||||||
@ -57,7 +70,7 @@ func Swap_Controller() {
|
|||||||
creation_t := time.UnixMilli(swap_e.Created)
|
creation_t := time.UnixMilli(swap_e.Created)
|
||||||
|
|
||||||
// if there was no deposit, mark the request as expired
|
// 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.WriteFile(fmt.Sprintf("swaps/expired/%d", swap_e.Created), file_data, 0644)
|
||||||
os.Remove("swaps/active/" + e.Name())
|
os.Remove("swaps/active/" + e.Name())
|
||||||
switch swap_e.Coin {
|
switch swap_e.Coin {
|
||||||
@ -82,7 +95,7 @@ func Swap_Controller() {
|
|||||||
found_deposit = monero.XMRGetTX(payment_id, swap_e.Block)
|
found_deposit = monero.XMRGetTX(payment_id, swap_e.Block)
|
||||||
visible = found_deposit
|
visible = found_deposit
|
||||||
} else {
|
} else {
|
||||||
log.Println("Can't split intragrated XMR address")
|
log.Println("Can't split integrated XMR address")
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
found_deposit = dero.CheckIncomingTransfers(uint64(swap_e.Created), swap_e.Block)
|
found_deposit = dero.CheckIncomingTransfers(uint64(swap_e.Created), swap_e.Block)
|
||||||
@ -96,7 +109,7 @@ func Swap_Controller() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// mark request as done
|
// 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)
|
err = os.WriteFile(fmt.Sprintf("swaps/done/%d", swap_e.Created), file_data, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Can't mark swap as done, swap %d, err %v\n", swap_e.Created, err)
|
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
|
// start payout if there are at least 2 confirmations
|
||||||
// requests won't be marked as expired, if there is already 1 confirmation
|
// requests won't be marked as expired, if there is already 1 confirmation
|
||||||
if visible {
|
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
|
// 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)
|
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:
|
case coin.DEROLTC, coin.DEROBTC:
|
||||||
log.Println("Starting LTC/BTC payout")
|
log.Println("Starting LTC/BTC payout")
|
||||||
_, txid := coin.XTCSend(swap_e.Coin, swap_e.Destination, swap_e.Price)
|
_, 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)
|
coin.Locked.RemoveLockedBalance(swap_e.Coin, swap_e.Price)
|
||||||
case coin.DEROARRR:
|
case coin.DEROARRR:
|
||||||
log.Println("Starting ARRR payout")
|
log.Println("Starting ARRR payout")
|
||||||
@ -129,18 +143,18 @@ func Swap_Controller() {
|
|||||||
txs = append(txs, dero.AddTX(swap_e.Destination, swap_e.Amount))
|
txs = append(txs, dero.AddTX(swap_e.Destination, swap_e.Amount))
|
||||||
}
|
}
|
||||||
|
|
||||||
swap_e.Status = 2
|
swap_e.Status = SWAP_DONE
|
||||||
sent++
|
sent++
|
||||||
active--
|
active--
|
||||||
} else {
|
} else {
|
||||||
// transaction was confirmed
|
// transaction was confirmed
|
||||||
swap_e.Status = 1
|
swap_e.Status = SWAP_CONFIRMED
|
||||||
}
|
}
|
||||||
|
|
||||||
json_data, _ := json.Marshal(&swap_e)
|
json_data, _ := json.Marshal(&swap_e)
|
||||||
os.WriteFile("swaps/active/"+e.Name(), json_data, 0644)
|
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)
|
err = os.WriteFile(fmt.Sprintf("swaps/done/%d", swap_e.Created), file_data, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Can't mark swap as done, swap %d, err %v\n", swap_e.Created, err)
|
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
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user