Fix buying items from merchants

Signed-off-by: Vladimir Domnich <v.domnich@yadro.com>
This commit is contained in:
Vladimir Domnich 2023-11-20 16:05:27 +04:00
parent 9de7e04e0f
commit fdb6e9fa8b
4 changed files with 35 additions and 3 deletions

View file

@ -99,3 +99,7 @@ To create a new player, invoke `newPlayer` function on the player contract and s
neo-go contract invokefunction -r http://localhost:30333 -w ../../wallet.json e7e4910b3a83ce0eff180a3f5462030391fde830 newPlayer string:demo
```
```sh
neo-go contract invokefunction -r http://localhost:30333 -w ../../wallet.json 8d099cb315c03c1f040d8912f1f2a84e569ca50c buyItem string:demo string:Shortbow -- 'NP8wjGz3Wvxe4gUAkTbK2McR95Y4LM2jMW:None'
```

View file

@ -1,6 +1,6 @@
name: "Merchant"
supportedstandards: []
events:
safemethods: ["getItemName"]
safemethods: ["getItemName", "getLotsForSale"]
permissions:
- methods: ["onNEP17Payment", "transfer"]

View file

@ -2,6 +2,7 @@ package player
import (
"github.com/nspcc-dev/neo-go/pkg/interop"
"github.com/nspcc-dev/neo-go/pkg/interop/iterator"
"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"
@ -47,6 +48,18 @@ func GetItemName(lotID int) string {
return getLot(storage.GetReadOnlyContext(), lotID).itemName
}
func GetLotsForSale() []Lot {
lots := make([]Lot, 0)
ctx := storage.GetReadOnlyContext()
it := storage.Find(ctx, lotsPrefix, storage.ValuesOnly|storage.DeserializeValues)
for iterator.Next(it) {
lot := iterator.Value(it).(Lot)
lots = append(lots, lot)
}
return lots
}
func Sell(itemName string, price int) {
ctx := storage.GetContext()
playerHash := storage.Get(ctx, playerHashKey).(interop.Hash160)
@ -63,7 +76,7 @@ func Sell(itemName string, price int) {
gasAmount := price * gasDecimals
success := gas.Transfer(runtime.GetExecutingScriptHash(), runtime.GetScriptContainer().Sender, gasAmount, nil)
if !success {
panic("failed to transfer gas")
panic("failed to transfer gas to seller")
}
}

View file

@ -7,8 +7,11 @@ import (
"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"
"github.com/nspcc-dev/neo-go/pkg/interop/util"
)
const gasDecimals = 1_0000_0000
var itemPrices = map[string]int{
"Sword": 100,
"Shortbow": 50,
@ -94,7 +97,11 @@ func BuyItemForGas(playerName string, lotID int, itemPrice int, merchantHash int
itemName := contract.Call(merchantHash, "getItemName", contract.ReadOnly, lotID).(string)
gas.Transfer(runtime.GetScriptContainer().Sender, merchantHash, itemPrice, lotID)
gasPrice := itemPrice * gasDecimals
success := gas.Transfer(runtime.GetScriptContainer().Sender, merchantHash, gasPrice, lotID)
if !success {
panic("failed to transfer gas to merchant")
}
addItemToInventory(player, itemName)
savePlayer(ctx, playerName, player)
@ -112,7 +119,15 @@ func SellItemForGas(playerName string, itemName string, itemPrice int, merchantH
}
removeItemFromInventory(player, itemName)
balanceBefore := gas.BalanceOf(runtime.GetScriptContainer().Sender)
contract.Call(merchantHash, "sell", contract.All, itemName, itemPrice)
balanceAfter := gas.BalanceOf(runtime.GetScriptContainer().Sender)
gasProfit := (balanceAfter - balanceBefore)
if gasProfit < itemPrice*gasDecimals {
runtime.Log("merchant payment does not cover item price: " + std.Itoa10(gasProfit) + " < " + std.Itoa10(itemPrice*gasDecimals))
util.Abort()
}
savePlayer(ctx, playerName, player)
}