Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Project manager atomic #20

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions contribs/gnodev/cmd/gnodev/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,13 @@ func execDev(cfg *devCfg, args []string, io commands.IO) (err error) {
// Setup gnoweb
webhandler := setupGnoWebServer(logger.WithGroup(WebLogName), cfg, devNode)

mux.HandleFunc("/reset", func(res http.ResponseWriter, req *http.Request) {
if err := devNode.Reset(req.Context()); err != nil {
logger.Error("failed to reset", slog.Any("err", err))
res.WriteHeader(http.StatusInternalServerError)
}
})

// Setup HotReload if needed
if !cfg.noWatch {
evtstarget := fmt.Sprintf("%s/_events", server.Addr)
Expand Down
7 changes: 7 additions & 0 deletions examples/gno.land/p/demo/dao_maker/jsonutil/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module gno.land/p/demo/dao_maker/jsonutil

require (
gno.land/p/demo/avl v0.0.0-latest
gno.land/p/demo/json v0.0.0-latest
gno.land/p/demo/users v0.0.0-latest
)
131 changes: 131 additions & 0 deletions examples/gno.land/p/demo/dao_maker/jsonutil/jsonutil.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package jsonutil

import (
"std"
"strconv"
"time"

"gno.land/p/demo/avl"
"gno.land/p/demo/json"
"gno.land/p/demo/users"
)

func UnionNode(variant string, value *json.Node) *json.Node {
return json.ObjectNode("", map[string]*json.Node{
variant: value,
})
}

func MustUnion(value *json.Node) (string, *json.Node) {
obj := value.MustObject()
for key, value := range obj {
return key, value
}

panic("no variant in union")
}

func TimeNode(value time.Time) *json.Node {
j, err := value.MarshalJSON()
if err != nil {
panic(err)
}

return json.StringNode("", string(j[1:len(j)-1]))
}

func MustTime(value *json.Node) time.Time {
t := time.Time{}
err := t.UnmarshalJSON([]byte(value.String()))
if err != nil {
panic(err)
}

return t
}

func DurationNode(value time.Duration) *json.Node {
return Int64Node(value.Nanoseconds())
}

func MustDurationSeconds(value *json.Node) time.Duration {
return time.Duration(MustInt64(value)) * time.Second
}

func EmptyObjectNode() *json.Node {
return json.ObjectNode("", nil)
}

// int is always 64 bits in gno so we need a string to represent it without loss of precision in a lot of javascript environment, I wish bigint in json was more widely supported
func IntNode(value int) *json.Node {
return json.StringNode("", strconv.Itoa(value))
}

func MustInt(value *json.Node) int {
i, err := strconv.Atoi(value.MustString())
if err != nil {
panic(err)
}

return i
}

func Uint32Node(value uint32) *json.Node {
return json.StringNode("", strconv.FormatUint(uint64(value), 10))
}

func MustUint32(value *json.Node) uint32 {
return uint32(MustInt(value))
}

func Int64Node(value int64) *json.Node {
return json.StringNode("", strconv.FormatInt(value, 10))
}

func MustInt64(value *json.Node) int64 {
return int64(MustInt(value))
}

func Uint64Node(value uint64) *json.Node {
return json.StringNode("", strconv.FormatUint(value, 10))
}

func MustUint64(value *json.Node) uint64 {
return uint64(MustInt(value)) // FIXME: full uint64 range support (currently limited to [-2^63, 2^63-1])
}

func AVLTreeNode(root *avl.Tree, transform func(elem interface{}) *json.Node) *json.Node {
if root == nil {
return EmptyObjectNode()
}

fields := make(map[string]*json.Node)
root.Iterate("", "", func(key string, val interface{}) bool {
fields[key] = transform(val)
return false
})

return json.ObjectNode("", fields)
}

func AddressNode(addr std.Address) *json.Node {
return json.StringNode("", addr.String())
}

func MustAddress(value *json.Node) std.Address {
addr := std.Address(value.MustString())
if !addr.IsValid() {
panic("invalid address")
}

return addr
}

func AddressOrNameNode(aon users.AddressOrName) *json.Node {
return json.StringNode("", string(aon))
}

func MustAddressOrName(value *json.Node) users.AddressOrName {
aon := users.AddressOrName(value.MustString())
return aon
}
3 changes: 3 additions & 0 deletions examples/gno.land/p/demo/stokey/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module gno.land/p/demo/stokey

require gno.land/p/demo/seqid v0.0.0-latest
95 changes: 95 additions & 0 deletions examples/gno.land/p/demo/stokey/storekey.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package stokey

import (
"std"
"strings"

"gno.land/p/demo/seqid"
)

type SubKey interface {
KeyString() string
}

type Key []SubKey

func NewKey(subKeys ...SubKey) Key {
return Key(subKeys)
}

func (k Key) String() string {
b := strings.Builder{}
for _, subKey := range k {
b.WriteString(subKey.KeyString())
}
return b.String()
}

// std.Address

type addrSubKey std.Address

func Address(addr std.Address) SubKey {
return addrSubKey(addr)
}

func (a addrSubKey) KeyString() string {
_, b, ok := std.DecodeBech32(std.Address(a))
if !ok {
panic("invalid address")
}
return string(b[:])
}

type noAddrSubKey struct{}

func NoAddress() SubKey {
return noAddrSubKey{}
}

func (na noAddrSubKey) KeyString() string {
return string(make([]byte, 20))
}

type nextAddrSubKey std.Address

func NextAddress(addr std.Address) SubKey {
return nextAddrSubKey(addr)
}

func (na nextAddrSubKey) KeyString() string {
_, b, ok := std.DecodeBech32(std.Address(na))
if !ok {
panic("invalid address")
}
for i := len(b) - 1; i >= 0; i-- {
if b[i] == 255 {
if i == 0 {
panic("overflow")
}
b[i] = 0
} else {
b[i]++
break
}
}
return string(b[:])
}

// uint64

type uint64SubKey uint64

func Uint64(u uint64) SubKey {
return uint64SubKey(u)
}

func (u uint64SubKey) KeyString() string {
return seqid.ID(u).String()
}

// uint32

func Uint32(u uint32) SubKey {
return uint64SubKey(u)
}
3 changes: 3 additions & 0 deletions examples/gno.land/p/demo/stokey/utils.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package stokey

// TODO: add a KeySchema type to explicitely define keys shape and allow more qol utils
81 changes: 81 additions & 0 deletions examples/gno.land/r/demo/teritori/projects_manager/filter.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package projects_manager

import (
"std"

"gno.land/p/demo/dao_maker/jsonutil"
"gno.land/p/demo/json"
"gno.land/p/demo/ufmt"
)

type Filter interface {
FromJSON(ast *json.Node)
}

func FilterFromJSON(ast *json.Node) Filter {
if ast.IsNull() {
return nil
}
var filter Filter
key, member := jsonutil.MustUnion(ast)
switch key {
case "byCandidatesForFunder":
filter = &FilterByCandidatesForFunder{}
case "byFunder":
filter = &FilterByFunder{}
case "byContractor":
filter = &FilterByContractor{}
case "byContractorAndFunder":
filter = &FilterByContractorAndFunder{}
default:
panic(ufmt.Sprintf("invalid filter kind `%s`", key))
}
filter.FromJSON(member)
return filter
}

type FilterByCandidatesForFunder struct {
Funder std.Address
}

func (f *FilterByCandidatesForFunder) FromJSON(ast *json.Node) {
obj := ast.MustObject()
f.Funder = jsonutil.MustAddress(obj["funder"])
}

var _ Filter = &FilterByCandidatesForFunder{}

type FilterByFunder struct {
Funder std.Address
}

func (f *FilterByFunder) FromJSON(ast *json.Node) {
obj := ast.MustObject()
f.Funder = jsonutil.MustAddress(obj["funder"])
}

var _ Filter = &FilterByFunder{}

type FilterByContractor struct {
Contractor std.Address
}

func (f *FilterByContractor) FromJSON(ast *json.Node) {
obj := ast.MustObject()
f.Contractor = jsonutil.MustAddress(obj["contractor"])
}

var _ Filter = &FilterByContractor{}

type FilterByContractorAndFunder struct {
Contractor std.Address
Funder std.Address
}

func (f *FilterByContractorAndFunder) FromJSON(ast *json.Node) {
obj := ast.MustObject()
f.Contractor = jsonutil.MustAddress(obj["contractor"])
f.Funder = jsonutil.MustAddress(obj["funder"])
}

var _ Filter = &FilterByContractorAndFunder{}
9 changes: 9 additions & 0 deletions examples/gno.land/r/demo/teritori/projects_manager/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module gno.land/r/demo/teritori/projects_manager

require (
gno.land/p/demo/avl v0.0.0-latest
gno.land/p/demo/dao_maker/jsonutil v0.0.0-latest
gno.land/p/demo/json v0.0.0-latest
gno.land/p/demo/seqid v0.0.0-latest
gno.land/p/demo/ufmt v0.0.0-latest
)
Loading
Loading