cryptocurrency_exchange/contract.go

136 lines
3.2 KiB
Go
Raw Normal View History

2023-12-28 13:24:32 +00:00
package smart_contract_exchange
import (
"encoding/json"
"fmt"
"github.com/go-resty/resty/v2"
"github.com/nspcc-dev/neo-go/pkg/interop"
"github.com/nspcc-dev/neo-go/pkg/interop/native/gas"
"github.com/nspcc-dev/neo-go/pkg/interop/runtime"
"github.com/nspcc-dev/neo-go/pkg/interop/storage"
"strconv"
)
type Wallet struct {
Tokens map[string]int
}
type TickerPrice struct {
Symbol string `json:"symbol"`
Price string `json:"price"`
}
func GetWallet(address interop.Hash160) Wallet {
ctx := storage.GetContext()
walletBytes := storage.Get(ctx, address)
if walletBytes == nil {
return Wallet{
Tokens: make(map[string]int),
}
}
var wallet Wallet
walletBytesAsBytes, _ := walletBytes.([]byte)
err := json.Unmarshal(walletBytesAsBytes, &wallet)
if err != nil {
return Wallet{}
}
return wallet
}
func UpdateWallet(address interop.Hash160, wallet Wallet) {
ctx := storage.GetContext()
serialized, _ := json.Marshal(wallet)
storage.Put(ctx, address, serialized)
}
func GetBalance(address interop.Hash160, token string) int {
wallet := GetWallet(address)
return wallet.Tokens[token]
}
func RequestExchangeRate(fromToken string, toToken string) float64 {
originalString := "https://api.binance.com/api/v3/ticker/price?symbol=%sUSDT"
urlFrom := fmt.Sprintf(originalString, fromToken)
urlTo := fmt.Sprintf(originalString, toToken)
client := resty.New()
responseFrom, errFrom := client.R().Get(urlFrom)
responseTo, errTo := client.R().Get(urlTo)
if errFrom != nil || errTo != nil {
fmt.Println("Error during doing response")
return 0
}
var tickerPriceFrom TickerPrice
var tickerPriceTo TickerPrice
errFrom = json.Unmarshal(responseFrom.Body(), &tickerPriceFrom)
errTo = json.Unmarshal(responseTo.Body(), &tickerPriceTo)
if errFrom != nil || errTo != nil {
fmt.Println("Error during unpacking JSON")
return 0
}
priceFrom, _ := strconv.ParseFloat(tickerPriceFrom.Price, 64)
priceTo, _ := strconv.ParseFloat(tickerPriceTo.Price, 64)
result := priceFrom / priceTo
return result
}
func Transfer(address interop.Hash160, amount int, fromToken string, toToken string) bool {
if amount <= 0 {
runtime.Log("Invalid amount")
return false
}
balance := gas.BalanceOf(address)
if balance < amount {
runtime.Log("Low gas balance for transaction")
return false
}
contractHash := runtime.GetExecutingScriptHash()
result := gas.Transfer(address, contractHash, amount, nil)
if !result {
runtime.Log("Transfer operation failed")
return false
}
wallet := GetWallet(address)
if GetBalance(address, fromToken) < amount {
runtime.Log("Not enough funds to exchange")
return false
}
exchangeRate := RequestExchangeRate(fromToken, toToken)
if exchangeRate == 0 {
return false
}
convertedAmount := float64(amount) * exchangeRate
wallet.Tokens[fromToken] -= amount
wallet.Tokens[toToken] += int(convertedAmount)
UpdateWallet(address, wallet)
2023-12-28 18:16:57 +00:00
runtime.Log("Exchange successful: " + strconv.Itoa(amount) + " " + fromToken +
" exchanged for " + strconv.Itoa(int(convertedAmount)) + " " + toToken)
return true
}
func printBalance(address interop.Hash160) bool {
wallet := GetWallet(address)
2023-12-28 18:19:10 +00:00
fmt.Println("Balance: ")
2023-12-28 18:16:57 +00:00
for key, value := range wallet.Tokens {
2023-12-28 18:19:10 +00:00
fmt.Println(key + ":" + strconv.Itoa(value))
2023-12-28 18:16:57 +00:00
}
2023-12-28 13:24:32 +00:00
return true
}