cryptocurrency_exchange/contract.go

136 lines
3.1 KiB
Go
Raw Normal View History

2024-01-12 17:20:37 +00:00
package main
2023-12-28 13:24:32 +00:00
import (
"github.com/nspcc-dev/neo-go/pkg/interop"
"github.com/nspcc-dev/neo-go/pkg/interop/native/gas"
2024-01-12 17:20:37 +00:00
"github.com/nspcc-dev/neo-go/pkg/interop/native/std"
2023-12-28 13:24:32 +00:00
"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
}
2024-01-12 17:20:37 +00:00
func (w Wallet) getTokenBalance(token string) int {
value := getValueFromStringIntMap(w.Tokens, token)
if value == nil {
return 0
}
return value.(int)
2023-12-28 13:24:32 +00:00
}
2024-01-12 17:20:37 +00:00
var prices map[string]int
2024-01-15 21:58:53 +00:00
// Prices are multiplied by 1e14 and rounded to be represented as fixed point int
2024-01-12 17:20:37 +00:00
func init() {
2024-01-15 22:47:51 +00:00
prices = map[string]int{
"XMR": 152100000,
"XRP": 603500,
"ADA": 579300,
"AVAX": 39690000,
"BNB": 308300000,
"BTC": 46648920000,
"ETH": 2623000000,
"SOL": 101180000,
}
2024-01-12 17:20:37 +00:00
}
2023-12-28 13:24:32 +00:00
2024-01-12 17:20:37 +00:00
func TopUp(address interop.Hash160, token string, amount int) bool {
if !isKnownToken(token) {
runtime.Log("Token " + token + " is unkown")
return false
2023-12-28 13:24:32 +00:00
}
2024-01-12 17:20:37 +00:00
wallet := getWallet(address)
balance := wallet.getTokenBalance(token)
wallet.Tokens[token] = balance + amount
saveWallet(address, wallet)
2023-12-28 13:24:32 +00:00
2024-01-12 17:20:37 +00:00
return true
2023-12-28 13:24:32 +00:00
}
2024-01-12 17:20:37 +00:00
func GetTokenBalance(address interop.Hash160, token string) int {
return getWallet(address).getTokenBalance(token)
2023-12-28 13:24:32 +00:00
}
2024-01-12 17:20:37 +00:00
func Exchange(address interop.Hash160, amount int, fromToken string, toToken string) bool {
2023-12-28 13:24:32 +00:00
if amount <= 0 {
runtime.Log("Invalid amount")
return false
}
2024-01-12 17:20:37 +00:00
wallet := getWallet(address)
fromBalance := wallet.getTokenBalance(fromToken)
if fromBalance < amount {
2023-12-28 13:24:32 +00:00
runtime.Log("Not enough funds to exchange")
return false
}
2024-01-12 17:20:37 +00:00
fromTokenPrice := getPrice(fromToken)
toTokenPrice := getPrice(toToken)
convertedAmount := amount * fromTokenPrice / toTokenPrice
2023-12-28 13:24:32 +00:00
wallet.Tokens[fromToken] -= amount
2024-01-12 17:20:37 +00:00
wallet.Tokens[toToken] = wallet.getTokenBalance(toToken) + convertedAmount
2023-12-28 13:24:32 +00:00
2024-01-12 17:20:37 +00:00
saveWallet(address, wallet)
2023-12-28 13:24:32 +00:00
2024-01-12 17:20:37 +00:00
runtime.Log("Exchange successful: " + std.Itoa10(amount) + " " + fromToken +
" exchanged for " + std.Itoa10(convertedAmount) + " " + toToken)
2023-12-28 18:16:57 +00:00
return true
}
2024-01-12 17:20:37 +00:00
func PrintWallet(address interop.Hash160) {
wallet := getWallet(address)
2023-12-28 18:16:57 +00:00
2024-01-12 17:20:37 +00:00
runtime.Log("Wallet " + ":")
2023-12-28 18:16:57 +00:00
for key, value := range wallet.Tokens {
2024-01-12 17:20:37 +00:00
runtime.Log(key + ":" + std.Itoa10(value))
2023-12-28 18:16:57 +00:00
}
2024-01-12 17:20:37 +00:00
}
2023-12-28 13:24:32 +00:00
2024-01-12 17:20:37 +00:00
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
2023-12-28 13:24:32 +00:00
}