136 lines
3.2 KiB
Go
136 lines
3.2 KiB
Go
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)
|
|
|
|
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)
|
|
runtime.Log("Balance: ")
|
|
|
|
for key, value := range wallet.Tokens {
|
|
runtime.Log(key + ": " + strconv.Itoa(value))
|
|
}
|
|
|
|
return true
|
|
}
|