Swap Client
This commit is contained in:
parent
ddfc1bb8aa
commit
764ad4aa1b
139
README.md
139
README.md
@ -1,139 +0,0 @@
|
|||||||
# Dero Swaps
|
|
||||||
|
|
||||||
## Build from source
|
|
||||||
Clone the repository to your local disk.\
|
|
||||||
Run `go mod tidy` and compile with `go build`.
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
There are no paramters (yet).\
|
|
||||||
Instead, 2 config files are used.\
|
|
||||||
Place the following two config files in the program directory.
|
|
||||||
- **config.json**
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"listen" : (string) IP:Port to listen on,
|
|
||||||
"btc_daemon" : (string) IP:Port of Bitcoin daemon,
|
|
||||||
"btc_dir" : (string) path to Bitcoin directory,
|
|
||||||
"ltc_daemon" : (string) IP:Port of Litecoin daemon,
|
|
||||||
"ltc_dir" : (string) path to Litecoin directory,
|
|
||||||
"arrr_daemon" : (string) IP:Port of Pirate daemon,
|
|
||||||
"arrr_dir" : (string) path to Pirate directory,
|
|
||||||
"monero_wallet" : (string) IP:Port of Monero Wallet,
|
|
||||||
"dero_daemon" : (string) IP:Port of Dero Daemon,
|
|
||||||
"dero_wallet" : (string) IP:Port of Dero Wallet,
|
|
||||||
"pairs" : (string array) enabled pairs
|
|
||||||
}
|
|
||||||
```
|
|
||||||
Example file:
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"listen" : "192.168.177.161:10413",
|
|
||||||
"btc_daemon" : "localhost:8332",
|
|
||||||
"btc_dir" : "/mnt/bitcoin",
|
|
||||||
"ltc_daemon" : "localhost:9332",
|
|
||||||
"ltc_dir" : "/mnt/litecoin",
|
|
||||||
"arrr_daemon" : "localhost:45453",
|
|
||||||
"arrr_dir" : "/mnt/pirate",
|
|
||||||
"monero_wallet" : "localhost:18090",
|
|
||||||
"dero_daemon" : "localhost:10102",
|
|
||||||
"dero_wallet" : "localhost:10103",
|
|
||||||
"pairs" : ["btc-dero","ltc-dero","arrr-dero","dero-ltc","dero-btc","dero-arrr","xmr-dero","dero-xmr"]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
- **fees.json**
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"withdrawal" : {
|
|
||||||
"dero-btc" : (float) Bitcoin withdrawal fee,
|
|
||||||
"dero-ltc" : (float) Litecoin withdrawal fee,
|
|
||||||
"dero-arrr" : (float) Pirate withdrawal fee,
|
|
||||||
"dero-xmr" : (float) Monero withdrawal fee
|
|
||||||
},
|
|
||||||
"swap" : {
|
|
||||||
"bid": (float) in percent, Bid fees
|
|
||||||
"ask": (float) in percent, Ask fees
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
Example file:
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"withdrawal" : {
|
|
||||||
"dero-btc" : 0.00004,
|
|
||||||
"dero-ltc" : 0.0002,
|
|
||||||
"dero-arrr" : 0.001,
|
|
||||||
"dero-xmr" : 0.00006
|
|
||||||
},
|
|
||||||
"swap" : {
|
|
||||||
"bid": 0.75,
|
|
||||||
"ask": 0.75
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The mentioned *withdrawal* fees are recommended and can be adjusted later.
|
|
||||||
### Available Pairs
|
|
||||||
The following Pairs are supported:
|
|
||||||
- btc-dero
|
|
||||||
- ltc-dero
|
|
||||||
- xmr-dero
|
|
||||||
- arrr-dero
|
|
||||||
- dero-btc
|
|
||||||
- dero-ltc
|
|
||||||
- dero-xmr
|
|
||||||
- dero-arrr
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
The swap service starts a *websocket* server.
|
|
||||||
Bitcoin, Litecoin and Pirate swaps require a local node.
|
|
||||||
The easiest way to start is to enable **dero-xmr** and **xmr-dero** swaps.
|
|
||||||
The Monero wallet can be pointed to a public remote node.
|
|
||||||
|
|
||||||
### Methods
|
|
||||||
- **balance** (get pool liquidity)
|
|
||||||
- **market** (get price data)
|
|
||||||
- **swap** (create a swap request)
|
|
||||||
### JSON parameters
|
|
||||||
There are no parameters required for methods *market* and *balance*\
|
|
||||||
|
|
||||||
**swap** params
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"pair" : (string) swap pair,
|
|
||||||
"amount" : (float) swap amount (in Dero),
|
|
||||||
"dero_address" : (string) Destination wallet address
|
|
||||||
}
|
|
||||||
```
|
|
||||||
### JSON responses
|
|
||||||
**balance** response
|
|
||||||
```
|
|
||||||
"result": {
|
|
||||||
"dero" : (float) Dero pool,
|
|
||||||
"ltc" : (float) Litecoin pool,
|
|
||||||
"btc" : (float) Bitcoin pool,
|
|
||||||
"arrr" : (float) Pirate pool,
|
|
||||||
"xmr" : (float) Monero Pool
|
|
||||||
}
|
|
||||||
```
|
|
||||||
**market** response
|
|
||||||
```
|
|
||||||
"result": {
|
|
||||||
"ltcdero" : (float) LTC price for buying 1 Dero,
|
|
||||||
"btcdero" : (float) BTC price for buying 1 Dero,
|
|
||||||
"xmrdero" : (float) XMR price for buying 1 Dero,
|
|
||||||
"arrrdero" : (float) ARRR price for buying 1 Dero,
|
|
||||||
"deroltc" : (float) LTC price for selling 1 Dero
|
|
||||||
"derobtc" : (float) BTC price for selling 1 Dero,
|
|
||||||
"deroxmr" : (float) XMR price for selling 1 Dero,
|
|
||||||
"deroarrr" : (float) ARRR price for selling 1 Dero,
|
|
||||||
}
|
|
||||||
```
|
|
||||||
**swap** response
|
|
||||||
```
|
|
||||||
"id" : (int) Swap ID,,
|
|
||||||
"wallet" : (string) Deposit wallet
|
|
||||||
"deposit" : (float) Deposit amount,
|
|
||||||
"swap" : (float)`Payout value, only used for Dero-* swaps,
|
|
||||||
"error" : (string) error message, if present,
|
|
||||||
"request" : (Swap_Request) Swap JSON parameters
|
|
||||||
```
|
|
@ -1,14 +1,15 @@
|
|||||||
package cfg
|
package cfg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"dero-swap/coin"
|
|
||||||
"dero-swap/dero"
|
|
||||||
"dero-swap/monero"
|
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"log"
|
"log"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"swap-client/coin"
|
||||||
|
"swap-client/dero"
|
||||||
|
"swap-client/monero"
|
||||||
|
|
||||||
"github.com/ybbus/jsonrpc/v3"
|
"github.com/ybbus/jsonrpc/v3"
|
||||||
)
|
)
|
||||||
@ -40,11 +41,9 @@ func LoadConfig() {
|
|||||||
log.Println("Dero Wallet: No RPC authorization specified")
|
log.Println("Dero Wallet: No RPC authorization specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
monero.Monero_Wallet = jsonrpc.NewClient("http://" + Settings.Monero_Wallet + "/json_rpc")
|
Server_URL = url.URL{Scheme: "wss", Host: Settings.ServerAddress, Path: "/ws"}
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
// check if pair is "supported"
|
// check if pair is "supported"
|
||||||
for _, p := range Settings.Pairs {
|
for _, p := range Settings.Pairs {
|
||||||
@ -87,6 +86,11 @@ func LoadFees() {
|
|||||||
// basic config check
|
// basic config check
|
||||||
func CheckConfig() bool {
|
func CheckConfig() bool {
|
||||||
|
|
||||||
|
if Settings.Nickname == "" {
|
||||||
|
log.Println("Please specify a nickname")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
@ -94,27 +98,6 @@ func CheckConfig() bool {
|
|||||||
|
|
||||||
for p := range coin.Pairs {
|
for p := range coin.Pairs {
|
||||||
switch p {
|
switch p {
|
||||||
case coin.BTCDERO, coin.DEROBTC:
|
|
||||||
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
|
|
||||||
}
|
|
||||||
case coin.LTCDERO, coin.DEROLTC:
|
|
||||||
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
|
|
||||||
}
|
|
||||||
case coin.ARRRDERO, coin.DEROARRR:
|
|
||||||
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
|
|
||||||
}
|
|
||||||
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)
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
package cfg
|
package cfg
|
||||||
|
|
||||||
|
import "net/url"
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
ListenAddress string `json:"listen"`
|
ServerAddress string `json:"server"`
|
||||||
BTC_Daemon string `json:"BTC_Daemon"`
|
Nickname string `json:"nickname"`
|
||||||
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_Daemon string `json:"Dero_Daemon"`
|
||||||
Dero_Wallet string `json:"dero_wallet"`
|
Dero_Wallet string `json:"dero_wallet"`
|
||||||
Dero_Login string `json:"dero_login"`
|
Dero_Login string `json:"dero_login"`
|
||||||
@ -48,3 +45,5 @@ type (
|
|||||||
|
|
||||||
var Settings Config
|
var Settings Config
|
||||||
var SwapFees Fees
|
var SwapFees Fees
|
||||||
|
|
||||||
|
var Server_URL url.URL
|
||||||
|
@ -1,24 +1,18 @@
|
|||||||
package clients
|
package clients
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"dero-swap/coin"
|
|
||||||
"log"
|
"log"
|
||||||
|
"swap-client/coin"
|
||||||
|
|
||||||
"github.com/lesismal/nbio/nbhttp/websocket"
|
"github.com/lesismal/nbio/nbhttp/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Swap_External struct {
|
func IsExternalSwapAvailable(pair string, amount float64) (ok bool, client *websocket.Conn) {
|
||||||
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 {
|
Clients.Range(func(key any, value any) bool {
|
||||||
c := value.(ClientInfo)
|
c := value.(ClientInfo)
|
||||||
for _, p := range c.PairInfo {
|
for _, p := range c.PairInfo {
|
||||||
if p.Pair == pair && p.Balance >= amount && user == c.Nickname {
|
if p.Pair == pair && p.Balance >= amount {
|
||||||
ok = true
|
ok = true
|
||||||
client = key.(*websocket.Conn)
|
client = key.(*websocket.Conn)
|
||||||
return false
|
return false
|
||||||
@ -29,7 +23,7 @@ func IsExternalSwapAvailable(user string, pair string, amount float64) (ok bool,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func PrepareExternalSwap(user string, pair string, amount float64) (bool, *websocket.Conn) {
|
func PrepareExternalSwap(pair string, amount float64) (bool, *websocket.Conn) {
|
||||||
|
|
||||||
// only XMR swaps
|
// only XMR swaps
|
||||||
if pair != coin.XMRDERO && pair != coin.DEROXMR {
|
if pair != coin.XMRDERO && pair != coin.DEROXMR {
|
||||||
@ -37,7 +31,7 @@ func PrepareExternalSwap(user string, pair string, amount float64) (bool, *webso
|
|||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ok, conn := IsExternalSwapAvailable(user, pair, amount)
|
ok, conn := IsExternalSwapAvailable(pair, amount)
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Println("No 3rd party swaps available")
|
log.Println("No 3rd party swaps available")
|
||||||
return false, nil
|
return false, nil
|
||||||
@ -81,25 +75,3 @@ func (c *SwapState) GetOrigin(conn *websocket.Conn) *websocket.Conn {
|
|||||||
|
|
||||||
return c.Result[conn]
|
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
|
|
||||||
}
|
|
||||||
|
@ -28,4 +28,4 @@ type SwapState struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var Clients sync.Map
|
var Clients sync.Map
|
||||||
var ActiveClients = SwapState{Client: make(map[*websocket.Conn]bool), Result: make(map[*websocket.Conn]*websocket.Conn)}
|
var ActiveClients = SwapState{Client: make(map[*websocket.Conn]bool)}
|
||||||
|
@ -10,7 +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"`
|
Partner bool `json:"partner,omitempty"`
|
||||||
}
|
}
|
||||||
Swap_Response struct {
|
Swap_Response struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
|
7
config.json
Normal file
7
config.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"server" : "mg25ot4aggt8dprv.myfritz.net:10413",
|
||||||
|
"monero_wallet" : "localhost:18090",
|
||||||
|
"dero_daemon" : "localhost:10102",
|
||||||
|
"dero_wallet" : "localhost:10103",
|
||||||
|
"pairs" : ["xmr-dero","dero-xmr"]
|
||||||
|
}
|
@ -5,7 +5,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"dero-swap/coin"
|
"swap-client/coin"
|
||||||
|
|
||||||
"github.com/deroproject/derohe/cryptography/crypto"
|
"github.com/deroproject/derohe/cryptography/crypto"
|
||||||
"github.com/deroproject/derohe/rpc"
|
"github.com/deroproject/derohe/rpc"
|
||||||
|
12
fees.json
Normal file
12
fees.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"withdrawal" : {
|
||||||
|
"dero-btc" : 0.00004,
|
||||||
|
"dero-ltc" : 0.0002,
|
||||||
|
"dero-arrr" : 0.001,
|
||||||
|
"dero-xmr" : 0.00006
|
||||||
|
},
|
||||||
|
"swap" : {
|
||||||
|
"bid": 0.75,
|
||||||
|
"ask": 0.75
|
||||||
|
}
|
||||||
|
}
|
16
go.mod
16
go.mod
@ -1,11 +1,11 @@
|
|||||||
module dero-swap
|
module swap-client
|
||||||
|
|
||||||
go 1.21.5
|
go 1.21.5
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/deroproject/derohe v0.0.0-20240215152352-a5a0e6a68ada
|
github.com/deroproject/derohe v0.0.0-20240229002921-e9df1205b660
|
||||||
github.com/lesismal/llib v1.1.12
|
github.com/gorilla/websocket v1.5.1
|
||||||
github.com/lesismal/nbio v1.5.3
|
github.com/lesismal/nbio v1.5.6
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/ybbus/jsonrpc/v3 v3.1.5
|
github.com/ybbus/jsonrpc/v3 v3.1.5
|
||||||
)
|
)
|
||||||
@ -18,18 +18,16 @@ require (
|
|||||||
github.com/fxamacker/cbor/v2 v2.6.0 // indirect
|
github.com/fxamacker/cbor/v2 v2.6.0 // indirect
|
||||||
github.com/go-logr/logr v1.4.1 // indirect
|
github.com/go-logr/logr v1.4.1 // indirect
|
||||||
github.com/go-logr/zapr v1.3.0 // indirect
|
github.com/go-logr/zapr v1.3.0 // indirect
|
||||||
github.com/kr/pretty v0.3.0 // indirect
|
github.com/lesismal/llib v1.1.13 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.8.0 // indirect
|
|
||||||
github.com/satori/go.uuid v1.2.0 // indirect
|
github.com/satori/go.uuid v1.2.0 // indirect
|
||||||
github.com/stretchr/testify v1.8.4 // indirect
|
github.com/stretchr/testify v1.8.4 // indirect
|
||||||
github.com/x448/float16 v0.8.4 // indirect
|
github.com/x448/float16 v0.8.4 // indirect
|
||||||
go.uber.org/multierr v1.10.0 // indirect
|
go.uber.org/multierr v1.10.0 // indirect
|
||||||
go.uber.org/zap v1.27.0 // indirect
|
go.uber.org/zap v1.27.0 // indirect
|
||||||
golang.org/x/crypto v0.19.0 // indirect
|
golang.org/x/crypto v0.14.0 // indirect
|
||||||
golang.org/x/net v0.17.0 // indirect
|
golang.org/x/net v0.17.0 // indirect
|
||||||
golang.org/x/sys v0.17.0 // indirect
|
golang.org/x/sys v0.13.0 // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
|
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
10
main.go
10
main.go
@ -4,8 +4,8 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"dero-swap/cfg"
|
"swap-client/cfg"
|
||||||
"dero-swap/coin"
|
"swap-client/coin"
|
||||||
|
|
||||||
"github.com/robfig/cron/v3"
|
"github.com/robfig/cron/v3"
|
||||||
)
|
)
|
||||||
@ -26,17 +26,15 @@ func main() {
|
|||||||
log.Println("Configuration error. Please check config file!")
|
log.Println("Configuration error. Please check config file!")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.LoadWallets()
|
cfg.LoadWallets()
|
||||||
|
|
||||||
coin.Locked.LoadLockedBalance()
|
coin.Locked.LoadLockedBalance()
|
||||||
|
|
||||||
UpdateMarkets()
|
|
||||||
|
|
||||||
c := cron.New()
|
c := cron.New()
|
||||||
c.AddFunc("@every 1m", UpdateMarkets)
|
c.AddFunc("@every 1m", UpdateMarkets)
|
||||||
c.AddFunc("@every 2m", Delay.CheckBackoff)
|
c.AddFunc("@every 2m", Delay.CheckBackoff)
|
||||||
c.Start()
|
c.Start()
|
||||||
|
|
||||||
go Swap_Controller()
|
go Swap_Controller()
|
||||||
StartServer()
|
StartClient(cfg.Server_URL)
|
||||||
}
|
}
|
||||||
|
224
price.go
224
price.go
@ -1,17 +1,16 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"dero-swap/cfg"
|
|
||||||
"dero-swap/clients"
|
|
||||||
"dero-swap/coin"
|
|
||||||
"dero-swap/dero"
|
|
||||||
"dero-swap/monero"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"swap-client/cfg"
|
||||||
|
"swap-client/clients"
|
||||||
|
"swap-client/coin"
|
||||||
|
"swap-client/dero"
|
||||||
|
"swap-client/monero"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -121,186 +120,83 @@ func GetPrice(pair string) (bid float64, ask float64) {
|
|||||||
// TODO: simplify
|
// TODO: simplify
|
||||||
func UpdateMarkets() {
|
func UpdateMarkets() {
|
||||||
|
|
||||||
var btc, ltc, xmr, arrr float64
|
var xmr float64
|
||||||
var derobtc, deroltc, deroxmr, deroarrr float64
|
var deroxmr float64
|
||||||
|
|
||||||
for p := range coin.SimplePairs {
|
for p := range coin.SimplePairs {
|
||||||
switch p {
|
switch p {
|
||||||
case coin.XMRDERO, coin.DEROXMR:
|
case coin.XMRDERO, coin.DEROXMR:
|
||||||
deroxmr, xmr = GetPrice(p)
|
deroxmr, xmr = GetPrice(p)
|
||||||
case coin.ARRRDERO, coin.DEROARRR:
|
}
|
||||||
deroarrr, arrr = GetPrice(p)
|
|
||||||
case coin.LTCDERO, coin.DEROLTC:
|
// sometimes TradeOgre's BID/ASK values are swapped
|
||||||
deroltc, ltc = GetPrice(p)
|
if deroxmr > 0 && xmr > 0 && deroxmr > xmr {
|
||||||
case coin.BTCDERO, coin.DEROBTC:
|
swap := xmr
|
||||||
derobtc, btc = GetPrice(p)
|
xmr = deroxmr
|
||||||
|
deroxmr = swap
|
||||||
|
}
|
||||||
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sometimes TradeOgre's BID/ASK values are swapped
|
balance := UpdatePool()
|
||||||
if derobtc > 0 && btc > 0 && derobtc > btc {
|
|
||||||
swap := btc
|
|
||||||
btc = derobtc
|
|
||||||
derobtc = swap
|
|
||||||
}
|
|
||||||
if deroltc > 0 && ltc > 0 && deroltc > ltc {
|
|
||||||
swap := ltc
|
|
||||||
ltc = deroltc
|
|
||||||
deroltc = swap
|
|
||||||
}
|
|
||||||
if deroarrr > 0 && arrr > 0 && deroarrr > arrr {
|
|
||||||
swap := arrr
|
|
||||||
arrr = deroarrr
|
|
||||||
deroarrr = swap
|
|
||||||
}
|
|
||||||
if deroxmr > 0 && xmr > 0 && deroxmr > xmr {
|
|
||||||
swap := xmr
|
|
||||||
xmr = deroxmr
|
|
||||||
deroxmr = swap
|
|
||||||
}
|
|
||||||
|
|
||||||
mk.Lock()
|
|
||||||
defer mk.Unlock()
|
|
||||||
|
|
||||||
// TODO: simplify
|
|
||||||
if btc > 0 {
|
|
||||||
mk.Pairs.BTC = btc
|
|
||||||
mk.Update[coin.BTCDERO] = time.Now().UnixMilli()
|
|
||||||
IsPairAvailable[coin.BTCDERO] = true
|
|
||||||
} else {
|
|
||||||
t := time.UnixMilli(mk.Update[coin.BTCDERO])
|
|
||||||
if time.Since(t) > time.Minute*2 {
|
|
||||||
IsPairAvailable[coin.BTCDERO] = false
|
|
||||||
log.Println("BTC->DERO disabled")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if arrr > 0 {
|
|
||||||
mk.Pairs.ARRR = arrr
|
|
||||||
mk.Update[coin.ARRRDERO] = time.Now().UnixMilli()
|
|
||||||
IsPairAvailable[coin.ARRRDERO] = true
|
|
||||||
} else {
|
|
||||||
t := time.UnixMilli(mk.Update[coin.ARRRDERO])
|
|
||||||
if time.Since(t) > time.Minute*2 {
|
|
||||||
IsPairAvailable[coin.ARRRDERO] = false
|
|
||||||
log.Println("ARRR->DERO disabled")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if derobtc > 0 {
|
|
||||||
mk.Pairs.DEROBTC = derobtc
|
|
||||||
mk.Update[coin.DEROBTC] = time.Now().UnixMilli()
|
|
||||||
IsPairAvailable[coin.DEROBTC] = true
|
|
||||||
} else {
|
|
||||||
t := time.UnixMilli(mk.Update[coin.DEROBTC])
|
|
||||||
if time.Since(t) > time.Minute*2 {
|
|
||||||
IsPairAvailable[coin.DEROBTC] = false
|
|
||||||
log.Println("DERO->BTC disabled")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if deroarrr > 0 {
|
|
||||||
mk.Pairs.DEROARRR = deroarrr
|
|
||||||
mk.Update[coin.DEROARRR] = time.Now().UnixMilli()
|
|
||||||
IsPairAvailable[coin.DEROARRR] = true
|
|
||||||
} else {
|
|
||||||
t := time.UnixMilli(mk.Update[coin.DEROARRR])
|
|
||||||
if time.Since(t) > time.Minute*2 {
|
|
||||||
IsPairAvailable[coin.DEROARRR] = false
|
|
||||||
log.Println("DERO->ARRR disabled")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var data bytes.Buffer
|
|
||||||
var out WS_Message
|
var out WS_Message
|
||||||
|
|
||||||
out.Method = "market"
|
out.Method = "client"
|
||||||
out.Result = mk.Pairs
|
out.Params = balance
|
||||||
encoder := json.NewEncoder(&data)
|
|
||||||
|
|
||||||
err := encoder.Encode(out)
|
Connection.WriteJSON(out)
|
||||||
if err != nil {
|
|
||||||
log.Printf("Market: %v\n", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
SendWSData(nil, data.Bytes())
|
|
||||||
|
|
||||||
data.Reset()
|
|
||||||
out.Method = "balance"
|
|
||||||
out.Result = UpdatePool()
|
|
||||||
err = encoder.Encode(out)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Balance: %v\n", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
SendWSData(nil, data.Bytes())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: reduce function calls
|
func UpdatePool() clients.ClientInfo {
|
||||||
func UpdatePool() Swap_Balance {
|
|
||||||
|
|
||||||
lock.Lock()
|
lock.Lock()
|
||||||
defer lock.Unlock()
|
defer lock.Unlock()
|
||||||
|
|
||||||
var balance Swap_Balance
|
var info clients.ClientInfo
|
||||||
|
var pair clients.PairInfo
|
||||||
|
|
||||||
balance.Dero = dero.GetBalance()
|
info.Nickname = cfg.Settings.Nickname
|
||||||
|
|
||||||
for p := range coin.SimplePairs {
|
for p := range coin.Pairs {
|
||||||
switch p {
|
switch p {
|
||||||
case coin.XMRDERO, coin.DEROXMR:
|
case coin.DEROXMR:
|
||||||
balance.XMR = monero.GetBalance()
|
pair.Balance = monero.GetBalance() - coin.Locked.GetLockedBalance(p)
|
||||||
case coin.ARRRDERO, coin.DEROARRR:
|
pair.Pair = p
|
||||||
balance.ARRR = coin.XTCGetBalance(p)
|
case coin.XMRDERO:
|
||||||
case coin.LTCDERO, coin.DEROLTC:
|
pair.Balance = dero.GetBalance() - coin.Locked.GetLockedBalance(p)
|
||||||
balance.LTC = coin.XTCGetBalance(p)
|
pair.Pair = p
|
||||||
case coin.BTCDERO, coin.DEROBTC:
|
default:
|
||||||
balance.BTC = coin.XTCGetBalance(p)
|
continue
|
||||||
}
|
}
|
||||||
|
info.PairInfo = append(info.PairInfo, pair)
|
||||||
}
|
}
|
||||||
|
|
||||||
balance.External = clients.GetExternalBalances()
|
return info
|
||||||
|
|
||||||
return balance
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import "sync"
|
||||||
"dero-swap/clients"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Price_Provider struct {
|
Price_Provider struct {
|
||||||
@ -37,12 +34,11 @@ type (
|
|||||||
DEROXMR float64 `json:"deroxmr,omitempty"`
|
DEROXMR float64 `json:"deroxmr,omitempty"`
|
||||||
}
|
}
|
||||||
Swap_Balance struct {
|
Swap_Balance struct {
|
||||||
Dero float64 `json:"dero"`
|
Dero float64 `json:"dero"`
|
||||||
LTC float64 `json:"ltc,omitempty"`
|
LTC float64 `json:"ltc,omitempty"`
|
||||||
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"`
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
293
server.go
293
server.go
@ -1,26 +1,19 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"crypto/tls"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/url"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/lesismal/llib/std/crypto/tls"
|
|
||||||
|
|
||||||
"github.com/deroproject/derohe/globals"
|
"github.com/deroproject/derohe/globals"
|
||||||
"github.com/lesismal/nbio/nbhttp"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/lesismal/nbio/nbhttp/websocket"
|
|
||||||
|
|
||||||
"dero-swap/cfg"
|
"swap-client/cfg"
|
||||||
"dero-swap/clients"
|
"swap-client/coin"
|
||||||
"dero-swap/coin"
|
"swap-client/dero"
|
||||||
"dero-swap/dero"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type WS_Message struct {
|
type WS_Message struct {
|
||||||
@ -30,7 +23,7 @@ type WS_Message struct {
|
|||||||
Result any `json:"result"`
|
Result any `json:"result"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var WSConnections sync.Map
|
var Connection *websocket.Conn
|
||||||
|
|
||||||
// swap other coins to Dero
|
// swap other coins to Dero
|
||||||
func Dero_Swap(request coin.Swap_Request) (response coin.Swap_Response) {
|
func Dero_Swap(request coin.Swap_Request) (response coin.Swap_Response) {
|
||||||
@ -115,242 +108,72 @@ func Reverse_Swap(request coin.Swap_Request) (response coin.Swap_Response) {
|
|||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
func newUpgrader() *websocket.Upgrader {
|
func StartClient(server url.URL) {
|
||||||
u := websocket.NewUpgrader()
|
|
||||||
|
|
||||||
u.CheckOrigin = (func(r *http.Request) bool {
|
var err error
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
u.OnClose(func(c *websocket.Conn, err error) {
|
for {
|
||||||
WSConnections.Delete(c)
|
|
||||||
clients.Clients.Delete(c)
|
|
||||||
})
|
|
||||||
|
|
||||||
u.OnMessage(func(c *websocket.Conn, messageType websocket.MessageType, data []byte) {
|
var in WS_Message
|
||||||
|
|
||||||
var in, out WS_Message
|
dialer := websocket.DefaultDialer
|
||||||
var send bytes.Buffer
|
dialer.TLSClientConfig = &tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
read := bytes.NewReader(data)
|
}
|
||||||
decoder := json.NewDecoder(read)
|
Connection, _, err = websocket.DefaultDialer.Dial(server.String(), nil)
|
||||||
encoder := json.NewEncoder(&send)
|
|
||||||
|
|
||||||
err := decoder.Decode(&in)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
log.Println("Websocket error, re-connect in 10 seconds")
|
||||||
return
|
time.Sleep(time.Second * 10)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
out.ID = in.ID
|
log.Printf("Connected to server %s\n", cfg.Settings.ServerAddress)
|
||||||
|
UpdateMarkets()
|
||||||
|
|
||||||
switch in.Method {
|
for {
|
||||||
case "swap":
|
if err := Connection.ReadJSON(&in); err != nil {
|
||||||
|
break
|
||||||
var request coin.Swap_Request
|
|
||||||
var response coin.Swap_Response
|
|
||||||
|
|
||||||
p := in.Params.(map[string]any)
|
|
||||||
out.Method = "swap"
|
|
||||||
|
|
||||||
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) != "" {
|
var out WS_Message
|
||||||
if ok, conn := clients.PrepareExternalSwap(q.(string), request.Pair, request.Amount); ok {
|
|
||||||
clients.ActiveClients.ChangeClientState(clients.LOCK, conn)
|
out.ID = in.ID
|
||||||
clients.ActiveClients.AddOrigin(conn, c)
|
|
||||||
out.Params = request
|
switch in.Method {
|
||||||
encoder.Encode(out)
|
case "swap":
|
||||||
SendWSData(conn, send.Bytes())
|
|
||||||
} else {
|
var request coin.Swap_Request
|
||||||
response.Error = "External swap not possible"
|
var response coin.Swap_Response
|
||||||
|
|
||||||
|
p := in.Params.(map[string]any)
|
||||||
|
out.Method = "client_ok"
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch request.Pair {
|
||||||
|
case coin.XMRDERO:
|
||||||
|
response = Dero_Swap(request)
|
||||||
|
case coin.DEROXMR:
|
||||||
|
response = Reverse_Swap(request)
|
||||||
|
default:
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
out.Result = response
|
out.Result = response
|
||||||
encoder.Encode(out)
|
|
||||||
SendWSData(c, send.Bytes())
|
|
||||||
|
|
||||||
return
|
Connection.WriteJSON(out)
|
||||||
|
UpdateMarkets()
|
||||||
}
|
}
|
||||||
|
|
||||||
switch request.Pair {
|
|
||||||
case coin.BTCDERO, coin.LTCDERO, coin.ARRRDERO, coin.XMRDERO:
|
|
||||||
response = Dero_Swap(request)
|
|
||||||
case coin.DEROBTC, coin.DEROLTC, coin.DEROARRR, coin.DEROXMR:
|
|
||||||
response = Reverse_Swap(request)
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
defer mk.RUnlock()
|
|
||||||
|
|
||||||
var data bytes.Buffer
|
|
||||||
|
|
||||||
out.Method = "market"
|
|
||||||
inner := mk.Pairs
|
|
||||||
out.Result = inner
|
|
||||||
|
|
||||||
encoder := json.NewEncoder(&data)
|
|
||||||
encoder.Encode(out)
|
|
||||||
|
|
||||||
SendWSData(c, data.Bytes())
|
|
||||||
|
|
||||||
case "balance":
|
|
||||||
|
|
||||||
var data bytes.Buffer
|
|
||||||
|
|
||||||
out.Method = "balance"
|
|
||||||
out.Result = UpdatePool()
|
|
||||||
|
|
||||||
encoder := json.NewEncoder(&data)
|
|
||||||
encoder.Encode(out)
|
|
||||||
|
|
||||||
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:
|
|
||||||
}
|
}
|
||||||
|
log.Println("Websocket error, re-connect in 10 seconds")
|
||||||
})
|
time.Sleep(time.Second * 10)
|
||||||
|
|
||||||
return u
|
|
||||||
}
|
|
||||||
|
|
||||||
func webSocketHandler(w http.ResponseWriter, r *http.Request) {
|
|
||||||
|
|
||||||
upgrader := newUpgrader()
|
|
||||||
conn, err := upgrader.Upgrade(w, r, nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
WSConnections.Store(conn, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SendWSData(c *websocket.Conn, data []byte) {
|
|
||||||
|
|
||||||
if len(data) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if c != nil {
|
|
||||||
err := c.WriteMessage(websocket.TextMessage, data)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
WSConnections.Range(func(k any, v any) bool {
|
|
||||||
|
|
||||||
conn := k.(*websocket.Conn)
|
|
||||||
|
|
||||||
err := conn.WriteMessage(websocket.TextMessage, data)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func StartServer() {
|
|
||||||
|
|
||||||
// cert files
|
|
||||||
// Let's Encrypt:
|
|
||||||
// certFile = fullchain.pem
|
|
||||||
// keyFile = privkey.pem
|
|
||||||
|
|
||||||
// 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,
|
|
||||||
// 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()
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
os.Exit(2)
|
|
||||||
}
|
|
||||||
srv.Wait()
|
|
||||||
}
|
|
||||||
|
8
swap.go
8
swap.go
@ -1,14 +1,14 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"dero-swap/cfg"
|
|
||||||
"dero-swap/coin"
|
|
||||||
"dero-swap/dero"
|
|
||||||
"dero-swap/monero"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"swap-client/cfg"
|
||||||
|
"swap-client/coin"
|
||||||
|
"swap-client/dero"
|
||||||
|
"swap-client/monero"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"dero-swap/coin"
|
|
||||||
"dero-swap/dero"
|
|
||||||
"dero-swap/monero"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"swap-client/coin"
|
||||||
|
"swap-client/dero"
|
||||||
|
"swap-client/monero"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/deroproject/derohe/rpc"
|
"github.com/deroproject/derohe/rpc"
|
||||||
|
Loading…
Reference in New Issue
Block a user