dero-swaps/swap.go

205 lines
4.8 KiB
Go
Raw Normal View History

2024-04-11 13:35:17 +01:00
package main
import (
"dero-swap/cfg"
"dero-swap/coin"
"dero-swap/dero"
"dero-swap/monero"
"encoding/json"
"fmt"
"log"
"os"
"time"
)
func CreateSwap(pair string, wallet string, dest string, amount float64, price float64) int64 {
var entry coin.Swap_Entry
var height uint64
var payout float64 = amount
// get current block height. Ignore transactions < height
switch pair {
case coin.BTCDERO, coin.LTCDERO, coin.ARRRDERO:
height = coin.XTCCheckBlockHeight(pair)
case coin.XMRDERO:
height = monero.GetHeight()
default:
height = dero.CheckBlockHeight()
}
if height == 0 {
return 0
}
entry.Coin = pair
entry.Wallet = wallet
entry.Destination = dest
entry.Price = price
entry.Amount = amount
entry.Created = time.Now().UnixMilli()
entry.Block = height
entry.Status = 0
// create an integrated address for all Dero -> X swaps
if pair == coin.DEROLTC || pair == coin.DEROBTC || pair == coin.DEROARRR || pair == coin.DEROXMR {
if entry.Wallet = dero.MakeIntegratedAddress(entry.Created); entry.Wallet == "" {
return 0
}
payout = entry.Price
}
json_bytes, err := json.Marshal(&entry)
if err != nil {
return 0
}
err = os.WriteFile(fmt.Sprintf("swaps/active/%d", entry.Created), json_bytes, 0644)
if err != nil {
return 0
}
log.Printf("Swap request (%d) of %.8f (%s) successfully created\n", entry.Created, payout, entry.Coin)
return entry.Created
}
// X to Dero Swaps
func XTCSwap(pair string, dst_addr string, amount float64, resp *coin.Swap_Response) (err error) {
// check if Dero address is registered on chain
if !dero.IsDeroAddressRegistered(dst_addr) {
return fmt.Errorf("dero address is not registered")
}
// check balance and include locked swap balance
balance, err := dero.CheckWalletBalance()
if err != nil {
return fmt.Errorf("couldn't check swap balance")
}
if coin.Locked.GetLockedBalance(pair)+amount+dero.TxFee > balance {
return fmt.Errorf("insufficient swap balance")
}
coin.Locked.AddLockedBalance(pair, amount)
// create/get a deposit address
if pair != coin.XMRDERO {
resp.Wallet = coin.XTCGetAddress(pair)
} else {
resp.Wallet = monero.MakeIntegratedAddress()
}
if resp.Wallet == "" {
return fmt.Errorf("no swap deposit address available")
}
var coin_value float64
var atomicUnits uint = 8
switch pair {
case coin.BTCDERO:
coin_value = mk.Pairs.BTC
case coin.LTCDERO:
coin_value = mk.Pairs.LTC
case coin.ARRRDERO:
coin_value = mk.Pairs.ARRR
case coin.XMRDERO:
coin_value = mk.Pairs.XMR
atomicUnits = 12
}
deposit_value := coin_value * amount
var loops int = 5
var isAvailable bool
// if there is a request with the same deposit amount, run in a loop and lower deposit value by 1 Sat
for i := 0; i < loops; i++ {
if coin.IsAmountFree(pair, deposit_value) {
isAvailable = true
break
}
deposit_value -= SATOSHI
}
if !isAvailable || deposit_value == 0 {
return fmt.Errorf("Pre-Check: Couldn't create swap")
}
deposit_value = coin.RoundFloat(deposit_value, atomicUnits)
resp.ID = CreateSwap(pair, resp.Wallet, dst_addr, amount, deposit_value)
if resp.ID == 0 {
return fmt.Errorf("couldn't create swap")
}
resp.Deposit = deposit_value
return nil
}
// Dero to X swaps
func DeroXTCSwap(pair string, dst_addr string, amount float64, resp *coin.Swap_Response) (err error) {
var balance float64
var atomicUnits uint = 8
// validate destination wallet and check for sufficient swap balance
if pair != coin.DEROXMR {
if !coin.XTCValidateAddress(pair, dst_addr) {
return fmt.Errorf("%s address is not valid", pair[5:])
}
balance = coin.XTCGetBalance(pair)
} else {
if !monero.ValidateAddress(dst_addr) {
return fmt.Errorf("XMR address is not valid")
}
balance = monero.GetBalance()
atomicUnits = 12
}
var coin_value float64
var fees float64
// determine fees and current price
switch pair {
case coin.DEROLTC:
coin_value = mk.Pairs.DEROLTC
fees = cfg.SwapFees.Withdrawal.DeroLTC
case coin.DEROARRR:
coin_value = mk.Pairs.DEROARRR
fees = cfg.SwapFees.Withdrawal.DeroARRR
case coin.DEROBTC:
coin_value = mk.Pairs.DEROBTC
fees = cfg.SwapFees.Withdrawal.DeroBTC
case coin.DEROXMR:
coin_value = mk.Pairs.XMR
fees = cfg.SwapFees.Withdrawal.DeroXMR
}
payout_value := coin_value * amount
if payout_value-fees < 0 {
return fmt.Errorf("fees > payout value")
}
if payout_value == 0 {
return fmt.Errorf("couldn't create swap")
}
// check for reserved balance
if coin.Locked.GetLockedBalance(pair)+payout_value+fees > balance {
return fmt.Errorf("insufficient swap balance")
}
coin.Locked.AddLockedBalance(pair, payout_value)
payout_value -= fees
payout_value = coin.RoundFloat(payout_value, atomicUnits)
resp.Swap = payout_value
resp.ID = CreateSwap(pair, "", dst_addr, amount, payout_value)
if resp.ID == 0 {
return fmt.Errorf("couldn't create swap")
}
resp.Wallet = dero.MakeIntegratedAddress(resp.ID)
return nil
}