1// Package hof is the hall of fame realm.
2// The Hall of Fame is an exhibition that holds items. Users can add their realms to the Hall of Fame by
3// importing the Hall of Fame realm and calling hof.Register() from their init function.
4package hof
5
6import (
7 "std"
8
9 "gno.land/p/demo/avl"
10 "gno.land/p/demo/ownable"
11 "gno.land/p/demo/pausable"
12 "gno.land/p/demo/seqid"
13
14 "gno.land/r/leon/config"
15)
16
17var (
18 exhibition *Exhibition
19
20 // Safe objects
21 Ownable *ownable.Ownable
22 Pausable *pausable.Pausable
23)
24
25type (
26 Exhibition struct {
27 itemCounter seqid.ID
28 description string
29 items *avl.Tree // pkgPath > &Item
30 itemsSorted *avl.Tree // same data but sorted, storing pointers
31 }
32
33 Item struct {
34 id seqid.ID
35 pkgpath string
36 blockNum int64
37 upvote *avl.Tree // std.Addr > struct{}{}
38 downvote *avl.Tree // std.Addr > struct{}{}
39 }
40)
41
42func init() {
43 exhibition = &Exhibition{
44 items: avl.NewTree(),
45 itemsSorted: avl.NewTree(),
46 }
47
48 Ownable = ownable.NewWithAddress(config.OwnableMain.Owner()) // OrigSendOwnable?
49 Pausable = pausable.NewFromOwnable(Ownable)
50}
51
52// Register registers your realm to the Hall of Fame
53// Should be called from within code
54func Register() {
55 if Pausable.IsPaused() {
56 return
57 }
58
59 submission := std.PreviousRealm()
60 pkgpath := submission.PkgPath()
61
62 // Must be called from code
63 if submission.IsUser() {
64 return
65 }
66
67 // Must not yet exist
68 if exhibition.items.Has(pkgpath) {
69 return
70 }
71
72 id := exhibition.itemCounter.Next()
73 i := &Item{
74 id: id,
75 pkgpath: pkgpath,
76 blockNum: std.ChainHeight(),
77 upvote: avl.NewTree(),
78 downvote: avl.NewTree(),
79 }
80
81 exhibition.items.Set(pkgpath, i)
82 exhibition.itemsSorted.Set(id.String(), i)
83
84 std.Emit("Registration")
85}
86
87func Upvote(pkgpath string) {
88 rawItem, ok := exhibition.items.Get(pkgpath)
89 if !ok {
90 panic(ErrNoSuchItem)
91 }
92
93 item := rawItem.(*Item)
94 caller := std.PreviousRealm().Address().String()
95
96 if item.upvote.Has(caller) {
97 panic(ErrDoubleUpvote)
98 }
99
100 item.upvote.Set(caller, struct{}{})
101}
102
103func Downvote(pkgpath string) {
104 rawItem, ok := exhibition.items.Get(pkgpath)
105 if !ok {
106 panic(ErrNoSuchItem)
107 }
108
109 item := rawItem.(*Item)
110 caller := std.PreviousRealm().Address().String()
111
112 if item.downvote.Has(caller) {
113 panic(ErrDoubleDownvote)
114 }
115
116 item.downvote.Set(caller, struct{}{})
117}
118
119func Delete(pkgpath string) {
120 if !Ownable.CallerIsOwner() {
121 panic(ownable.ErrUnauthorized)
122 }
123
124 i, ok := exhibition.items.Get(pkgpath)
125 if !ok {
126 panic(ErrNoSuchItem)
127 }
128
129 if _, removed := exhibition.itemsSorted.Remove(i.(*Item).id.String()); !removed {
130 panic(ErrNoSuchItem)
131 }
132
133 if _, removed := exhibition.items.Remove(pkgpath); !removed {
134 panic(ErrNoSuchItem)
135 }
136}
hof.gno
2.63 Kb ยท 136 lines