Skip to content

Instantly share code, notes, and snippets.

@alexvanin
Created April 12, 2021 16:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexvanin/8c214dfd6d685d9cf54fa873cfe63c1d to your computer and use it in GitHub Desktop.
Save alexvanin/8c214dfd6d685d9cf54fa873cfe63c1d to your computer and use it in GitHub Desktop.
NeoFS N3 oracle example
package oracleexample
import (
"github.com/nspcc-dev/neo-go/pkg/interop/native/oracle"
"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"
)
// NeoFS URI of object with JSON encoded database of items.
const database = "neofs:6pJtLUnGqDxE2EitZYLsDzsfTDVegD6BrRUn8QAFZWyt/5pHkykmTC6vBpx19y5r26YUBqrEx8J5wVAntCU42bFYQ"
type CallbackDetails struct {
id int
username string
}
func _deploy(_ interface{}, isUpdate bool) {
ctx := storage.GetContext()
storage.Put(ctx, "Marie", 4000) // 4000 coins for Marie
}
func Balance(username string) int {
ctx := storage.GetReadOnlyContext()
return storage.Get(ctx, username).(int)
}
func Purchase(id int, user string) {
url := database
idString := std.Itoa(id, 10)
// JSONPath filter to find price value in item with specified ID, e.g.:
// $..item[?(@.id==1)].price
filter := []byte("$..item[?(@.id==" + idString + ")].price")
details := CallbackDetails{
id: id,
username: user,
}
// Make oracle request. Add extra GAS to process deserialization and storage
// update in callback.
oracle.Request(url, filter, "oracleCallback", std.Serialize(details), oracle.MinimumResponseGas*2)
}
func OracleCallback(url string, data interface{}, code int, res []byte) {
if string(runtime.GetCallingScriptHash()) != oracle.Hash {
panic("not called from oracle contract")
}
if code != oracle.Success {
panic("request failed for " + url + " with code " + std.Itoa(code, 10))
}
// Decode invocation details to get username and current balance.
details := std.Deserialize(data.([]byte)).(CallbackDetails)
currentBalance := Balance(details.username)
// Convert oracle response `[N]` to `N`.
stringPrice := string(res[1:len(res)-1])
price := std.Atoi(stringPrice, 10)
// Check if there are enough assets to make "purchase".
if currentBalance < price {
panic("not enough assets")
}
// Make purchase by updating user's balance.
ctx := storage.GetContext()
storage.Put(ctx, details.username, currentBalance-price)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment