dero-swaps/coin/btc.go
2024-04-11 14:35:17 +02:00

546 lines
12 KiB
Go

package coin
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"log"
"os"
"net/http"
)
func XTCGetCookie(pair string) bool {
var data []byte
var err error
switch pair {
case BTCDERO, DEROBTC:
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 {
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 {
log.Printf("Can't load ARRR auth cookie: %v\n", err)
return false
}
}
XTC_auth = base64.StdEncoding.EncodeToString(data)
data = nil
return true
}
func SetHeaders(request *http.Request, auth string) {
request.Header.Add("Content-Type", "text/plain")
request.Header.Add("Authorization", fmt.Sprintf("Basic %s", auth))
}
func XTCBuildRequest(pair string, method string, options []interface{}) (*http.Request, error) {
json_object := &RPC_Request{Jsonrpc: "1.0", Id: "swap", Method: method, Params: options}
json_bytes, err := json.Marshal(&json_object)
if err != nil {
log.Printf("Can't marshal %s request: %v\n", method, err)
return nil, err
}
req, err := http.NewRequest("POST", XTC_GetURL(pair), bytes.NewBuffer(json_bytes))
if err != nil {
log.Printf("Can't create %s request: %v\n", method, err)
return nil, err
}
XTCGetCookie(pair)
SetHeaders(req, XTC_auth)
return req, nil
}
func XTCNewWallet(pair string) (result bool, message string) {
switch pair {
case DEROARRR, ARRRDERO, DEROXMR, XMRDERO:
return false, ""
}
req, err := XTCBuildRequest(pair, "createwallet", []interface{}{"swap_wallet"})
if err != nil {
log.Printf("Can't build createwallet request: %v\n", err)
return false, ""
}
resp, err := XTC_Daemon.Do(req)
if err != nil {
log.Printf("Can't send createwallet request: %v\n", err)
return false, ""
}
defer resp.Body.Close()
var json_resonse RPC_NewWallet_Response
body, _ := io.ReadAll(resp.Body)
err = json.Unmarshal(body, &json_resonse)
if err != nil {
log.Printf("Can't unmarshal createwallet response: %v\n", err)
return false, ""
}
if json_resonse.Error != (RPC_Error{}) {
message = json_resonse.Error.Message
} else {
result = true
}
return result, message
}
func XTCLoadWallet(pair string) (result bool, message string) {
req, err := XTCBuildRequest(pair, "loadwallet", []interface{}{"swap_wallet"})
if err != nil {
log.Printf("Can't build loadwallet request: %v\n", err)
return false, ""
}
resp, err := XTC_Daemon.Do(req)
if err != nil {
log.Printf("Can't send loadwallet request: %v\n", err)
return false, ""
}
defer resp.Body.Close()
var json_resonse RPC_NewWallet_Response
body, _ := io.ReadAll(resp.Body)
err = json.Unmarshal(body, &json_resonse)
if err != nil {
log.Printf("Can't unmarshal createwallet response: %v\n", err)
return false, ""
}
if json_resonse.Error != (RPC_Error{}) {
message = json_resonse.Error.Message
} else {
result = true
}
return result, message
}
func XTCNewAddress(pair string) string {
req, err := XTCBuildRequest(pair, "getnewaddress", []interface{}{})
if err != nil {
log.Printf("Can't build getnewaddress request: %v\n", err)
return ""
}
resp, err := XTC_Daemon.Do(req)
if err != nil {
log.Printf("Can't send getnewaddress request: %v\n", err)
return ""
}
defer resp.Body.Close()
var json_resonse RPC_NewAddress_Response
body, _ := io.ReadAll(resp.Body)
err = json.Unmarshal(body, &json_resonse)
if err != nil {
log.Printf("Can't unmarshal getnewaddress response: %v\n", err)
return ""
}
log.Println("Successfully created new address")
return json_resonse.Result
}
func XTCGetAddress(pair string) string {
switch pair {
case DEROARRR, ARRRDERO, DEROXMR, XMRDERO:
return ""
}
_, _, address, _ := XTCListReceivedByAddress(pair, "", 0, 0, true)
return address
}
func XTCCheckBlockHeight(pair string) uint64 {
req, err := XTCBuildRequest(pair, "getblockcount", []interface{}{})
if err != nil {
log.Printf("Can't build getblockcount request: %v\n", err)
return 0
}
resp, err := XTC_Daemon.Do(req)
if err != nil {
log.Printf("Can't send getblockcount request: %v\n", err)
return 0
}
defer resp.Body.Close()
var response RPC_GetBlockCount_Response
body, _ := io.ReadAll(resp.Body)
err = json.Unmarshal(body, &response)
if err != nil {
log.Printf("Can't unmarshal getblockcount response: %v\n", err)
return 0
} else {
return response.Result
}
}
func XTCReceivedByAddress(pair string, wallet string) (float64, error) {
req, err := XTCBuildRequest(pair, "getreceivedbyaddress", []interface{}{wallet, 2})
if err != nil {
log.Printf("Can't build getreceivedbyaddress request: %v\n", err)
return 0, err
}
resp, err := XTC_Daemon.Do(req)
if err != nil {
log.Printf("Can't send getreceivedbyaddress request: %v\n", err)
return 0, err
}
defer resp.Body.Close()
var response RPC_ReceivedByAddress_Response
body, _ := io.ReadAll(resp.Body)
err = json.Unmarshal(body, &response)
if err != nil {
log.Printf("Can't unmarshal getreceivedbyaddress response: %v\n", err)
return 0, err
} else {
return response.Result, nil
}
}
func XTCListReceivedByAddress(pair string, wallet string, amount float64, height uint64, get_address bool) (bool, bool, string, error) {
var method string
var options []interface{}
if !get_address {
if pair == DEROARRR {
method = "zs_listreceivedbyaddress"
options = append(options, wallet, 1, 3, height)
} else {
method = "listreceivedbyaddress"
options = append(options, 1, false, false, wallet)
}
} else {
method = "listreceivedbyaddress"
options = append(options, 0, true)
}
req, err := XTCBuildRequest(pair, method, options)
if err != nil {
log.Printf("Can't build listreceivedbyaddress request: %v\n", err)
return false, false, "", err
}
resp, err := XTC_Daemon.Do(req)
if err != nil {
log.Printf("Can't send listreceivedbyaddress request: %v\n", err)
return false, false, "", err
}
defer resp.Body.Close()
if pair != DEROARRR {
var response RPC_ListReceivedByAddress_Response
body, _ := io.ReadAll(resp.Body)
err = json.Unmarshal(body, &response)
if err != nil {
log.Printf("Can't unmarshal listreceivedbyaddress response: %v\n", err)
return false, false, "", err
}
if !get_address {
if len(response.Result) > 0 {
for _, tx := range response.Result[0].Txids {
tx_data, err := XTCGetTransaction(pair, tx)
if err != nil {
log.Printf("Error checking TX: %v\n", err)
continue
}
if tx_data.Result.Amount == amount && tx_data.Result.Blockheight >= height {
if tx_data.Result.Confirmations > 1 {
return true, true, "", nil
} else {
return false, true, "", nil
}
}
}
}
} else {
if len(response.Result) > 0 {
return false, false, response.Result[0].Address, nil
} else {
return false, false, "", nil
}
}
} else {
var response RPC_ARRR_ListReceivedByAddress_Response
body, _ := io.ReadAll(resp.Body)
err = json.Unmarshal(body, &response)
if err != nil {
log.Printf("Can't unmarshal zs_listreceivedbyaddress response: %v\n", err)
return false, false, "", err
}
if len(response.Result) > 0 {
for e := range response.Result {
if response.Result[e].BlockHeight >= height {
for _, tx := range response.Result[e].Received {
if tx.Value == amount {
if response.Result[e].Confirmations > 1 {
return true, true, "", nil
} else {
return false, true, "", nil
}
}
}
}
}
}
}
return false, false, "", nil
}
func XTCGetTransaction(pair string, txid string) (result RPC_GetTransaction_Response, err error) {
req, err := XTCBuildRequest(pair, "gettransaction", []interface{}{txid, false})
if err != nil {
log.Printf("Can't build gettransaction request: %v\n", err)
return result, err
}
resp, err := XTC_Daemon.Do(req)
if err != nil {
log.Printf("Can't send gettransaction request: %v\n", err)
return result, err
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
err = json.Unmarshal(body, &result)
if err != nil {
log.Printf("Can't unmarshal gettransaction response: %v\n", err)
return result, err
}
return result, nil
}
func XTCGetBalance(pair string) float64 {
var method string
var options []interface{}
if pair == DEROARRR || pair == ARRRDERO {
method = "z_getbalance"
options = append(options, ARRR_GetAddress())
} else {
method = "getbalance"
}
req, err := XTCBuildRequest(pair, method, options)
if err != nil {
log.Printf("Can't build getbalance request: %v\n", err)
return 0
}
resp, err := XTC_Daemon.Do(req)
if err != nil {
log.Printf("Can't send getbalance request: %v\n", err)
return 0
}
defer resp.Body.Close()
var result RPC_GetBalance_Result
body, _ := io.ReadAll(resp.Body)
err = json.Unmarshal(body, &result)
if err != nil {
log.Printf("Can't unmarshal getbalance response: %v\n", err)
return 0
}
return RoundFloat(result.Result-Locked.GetLockedBalance(pair), 8)
}
func XTCSend(pair string, wallet string, amount float64) (bool, string) {
var options []interface{}
switch pair {
case DEROLTC:
options = append(options, wallet, amount)
case DEROBTC:
options = append(options, wallet, amount, "", "", false, true, nil, "unset", nil, 14)
}
req, err := XTCBuildRequest(pair, "sendtoaddress", options)
if err != nil {
log.Printf("Can't build sendtoaddress request: %v\n", err)
return false, ""
}
resp, err := XTC_Daemon.Do(req)
if err != nil {
log.Printf("Can't send sendtoaddress request: %v\n", err)
return false, ""
}
defer resp.Body.Close()
var result RPC_Send_Result
body, _ := io.ReadAll(resp.Body)
err = json.Unmarshal(body, &result)
if err != nil {
log.Printf("Can't unmarshal sendtoaddress response: %v\n", err)
return false, ""
}
return true, result.Result
}
func XTCValidateAddress(pair string, address string) bool {
var method string
if pair == DEROARRR || pair == ARRRDERO {
method = "z_validateaddress"
} else {
method = "validateaddress"
}
req, err := XTCBuildRequest(pair, method, []interface{}{address})
if err != nil {
log.Printf("Can't build validateaddress request: %v\n", err)
return false
}
resp, err := XTC_Daemon.Do(req)
if err != nil {
log.Printf("Can't send validateaddress request: %v\n", err)
return false
}
defer resp.Body.Close()
var result RPC_Validate_Address_Result
body, _ := io.ReadAll(resp.Body)
err = json.Unmarshal(body, &result)
if err != nil {
log.Printf("Can't unmarshal validateaddress response: %v\n", err)
return false
}
return result.Result.IsValid
}
func XTC_GetURL(pair string) string {
switch pair {
case BTCDERO, DEROBTC:
return XTC_URL[BTCDERO]
case LTCDERO, DEROLTC:
return XTC_URL[LTCDERO]
case ARRRDERO, DEROARRR:
return XTC_URL[ARRRDERO]
default:
return ""
}
}
func ARRR_Send(wallet string, amount float64) (bool, string) {
var params []RPC_ARRR_SendMany_Params
params = append(params, RPC_ARRR_SendMany_Params{Address: wallet, Amount: amount})
options := []interface{}{ARRR_GetAddress(), params}
req, err := XTCBuildRequest(DEROARRR, "z_sendmany", options)
if err != nil {
log.Printf("Can't build z_sendmany request: %v\n", err)
return false, ""
}
resp, err := XTC_Daemon.Do(req)
if err != nil {
log.Printf("Can't send z_sendmany request: %v\n", err)
return false, ""
}
defer resp.Body.Close()
var result RPC_Send_Result
body, _ := io.ReadAll(resp.Body)
err = json.Unmarshal(body, &result)
if err != nil {
log.Printf("Can't unmarshal z_sendmany response: %v\n", err)
return false, ""
}
return true, result.Result
}
func ARRR_GetAddress() string {
req, err := XTCBuildRequest(DEROARRR, "z_listaddresses", nil)
if err != nil {
log.Printf("Can't build z_listaddresses request: %v\n", err)
return ""
}
resp, err := XTC_Daemon.Do(req)
if err != nil {
log.Printf("Can't send z_listaddresses request: %v\n", err)
return ""
}
defer resp.Body.Close()
var result RPC_ARRR_ListAddresses
body, _ := io.ReadAll(resp.Body)
err = json.Unmarshal(body, &result)
if err != nil {
log.Printf("Can't unmarshal z_listaddresses response: %v\n", err)
return ""
}
if len(result.Result) == 0 {
return ""
} else {
return result.Result[0]
}
}