cryptocurrency_exchange/contract.go

138 lines
3.1 KiB
Go

//go:build !exclude_crypto_ecdsa
package main
import (
"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/native/std"
"github.com/nspcc-dev/neo-go/pkg/interop/runtime"
"github.com/nspcc-dev/neo-go/pkg/interop/storage"
)
type Wallet struct {
Tokens map[string]int
}
func (w Wallet) getTokenBalance(token string) int {
value := getValueFromStringIntMap(w.Tokens, token)
if value == nil {
return 0
}
return value.(int)
}
var prices map[string]int
// Prices are multiplied by 1e14 and rounded to be represented as fixed point int
func init() {
  prices = map[string]int{
    "XMR":  152100000,
    "XRP":  603500,
    "ADA":  579300,
    "AVAX": 39690000,
    "BNB":  308300000,
    "BTC":  46648920000,
    "ETH":  2623000000,
    "SOL":  101180000,
  }
}
func TopUp(address interop.Hash160, token string, amount int) bool {
if !isKnownToken(token) {
runtime.Log("Token " + token + " is unkown")
return false
}
wallet := getWallet(address)
balance := wallet.getTokenBalance(token)
wallet.Tokens[token] = balance + amount
saveWallet(address, wallet)
return true
}
func GetTokenBalance(address interop.Hash160, token string) int {
return getWallet(address).getTokenBalance(token)
}
func Exchange(address interop.Hash160, amount int, fromToken string, toToken string) bool {
if amount <= 0 {
runtime.Log("Invalid amount")
return false
}
wallet := getWallet(address)
fromBalance := wallet.getTokenBalance(fromToken)
if fromBalance < amount {
runtime.Log("Not enough funds to exchange")
return false
}
fromTokenPrice := getPrice(fromToken)
toTokenPrice := getPrice(toToken)
convertedAmount := amount * fromTokenPrice / toTokenPrice
wallet.Tokens[fromToken] -= amount
wallet.Tokens[toToken] = wallet.getTokenBalance(toToken) + convertedAmount
saveWallet(address, wallet)
runtime.Log("Exchange successful: " + std.Itoa10(amount) + " " + fromToken +
" exchanged for " + std.Itoa10(convertedAmount) + " " + toToken)
return true
}
func PrintWallet(address interop.Hash160) {
wallet := getWallet(address)
runtime.Log("Wallet " + ":")
for key, value := range wallet.Tokens {
runtime.Log(key + ":" + std.Itoa10(value))
}
}
func getWallet(address interop.Hash160) Wallet {
ctx := storage.GetContext()
walletBytes := storage.Get(ctx, address)
if walletBytes == nil {
return Wallet{
Tokens: make(map[string]int),
}
}
walletBytesAsBytes := walletBytes.([]byte)
deserialized := std.Deserialize(walletBytesAsBytes)
if deserialized == nil {
return Wallet{}
}
return deserialized.(Wallet)
}
func saveWallet(address interop.Hash160, wallet Wallet) {
ctx := storage.GetContext()
serialized := std.Serialize(wallet)
storage.Put(ctx, address, serialized)
}
func getPrice(token string) int {
if !isKnownToken(token) {
panic("trying to get price for unknown token")
}
return prices[token]
}
func getValueFromStringIntMap(mp map[string]int, key string) any {
defer func() {
recover()
}()
return mp[key]
}
func isKnownToken(token string) bool {
return getValueFromStringIntMap(prices, token) != nil
}