-
Notifications
You must be signed in to change notification settings - Fork 374
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
feat(examples): hall of fame #2842
base: master
Are you sure you want to change the base?
Changes from all commits
ac0d79e
a17edb2
1a44f35
291b92f
6038562
23db6aa
fa7286b
c0d435d
1cff9f1
04d62c7
b2294ac
2a1093e
903fb48
f1adda0
5d8a12b
538f6f1
7d44835
c8e4e1f
a0be035
5c3524d
17b7ba6
29bb8dc
5393e7b
9a171ff
97794d7
1da8805
e2dcbca
ec2687b
3c21976
fa11b61
48ebe1a
5a5c1b5
2cef5df
54e414b
8f3d796
4a6dad6
5dc3d0f
f0ce5de
943df0c
296f7d8
1c10732
79ffd7d
adf95c0
3754a70
19f7fa9
a646518
94fc361
cde9fe2
84ef0ea
0c9b8a6
d1d60ed
f6d07a9
dd528a5
57fbda6
e14f677
d3de1e1
04061a8
c3ea204
20b6d9a
f32070f
1cecdd5
822ae4b
5b7afc8
b40e128
8a55c2a
edc6915
f31c2e9
7602379
6e0f3c5
8bcf672
3f35e68
2f88736
0352dfc
1cc0a9e
5f1d73a
cd2814e
40ba854
b2155e0
fe9092d
72e5089
3e5a640
80b07e6
68c8ac6
882baf0
a43ccc1
c8803c3
ff06493
4344b56
c685a46
6c35688
7d4f866
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package hof | ||
|
||
import "std" | ||
|
||
// Exposing the ownable & pausable APIs | ||
// Should not be needed as soon as MsgCall supports calling methods on exported variables | ||
|
||
func Pause() error { | ||
return exhibition.Pause() | ||
} | ||
|
||
func Unpause() error { | ||
return exhibition.Unpause() | ||
} | ||
|
||
func GetOwner() std.Address { | ||
return owner.Owner() | ||
} | ||
|
||
func TransferOwnership(newOwner std.Address) { | ||
if err := owner.TransferOwnership(newOwner); err != nil { | ||
panic(err) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package hof | ||
|
||
import ( | ||
"errors" | ||
) | ||
|
||
var ( | ||
ErrNoSuchItem = errors.New("hof: no such item exists") | ||
ErrDoubleUpvote = errors.New("hof: cannot upvote twice") | ||
ErrDoubleDownvote = errors.New("hof: cannot downvote twice") | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
module gno.land/r/demo/hof | ||
|
||
require ( | ||
gno.land/p/demo/avl v0.0.0-latest | ||
gno.land/p/demo/avl/pager v0.0.0-latest | ||
gno.land/p/demo/fqname v0.0.0-latest | ||
gno.land/p/demo/ownable v0.0.0-latest | ||
gno.land/p/demo/pausable v0.0.0-latest | ||
gno.land/p/demo/seqid v0.0.0-latest | ||
gno.land/p/demo/testutils v0.0.0-latest | ||
gno.land/p/demo/uassert v0.0.0-latest | ||
gno.land/p/demo/ufmt v0.0.0-latest | ||
gno.land/p/demo/urequire v0.0.0-latest | ||
gno.land/p/moul/txlink v0.0.0-latest | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
// Package hof is the hall of fame realm. | ||
// The Hall of Fame is an exhibition that holds items. Users can add their realms to the Hall of Fame by | ||
// importing the Hall of Fame realm and calling hof.Register() from their init function. | ||
package hof | ||
|
||
import ( | ||
"std" | ||
|
||
"gno.land/p/demo/avl" | ||
"gno.land/p/demo/ownable" | ||
"gno.land/p/demo/pausable" | ||
"gno.land/p/demo/seqid" | ||
) | ||
|
||
var ( | ||
exhibition *Exhibition | ||
owner *ownable.Ownable | ||
) | ||
|
||
type ( | ||
Exhibition struct { | ||
itemCounter seqid.ID | ||
description string | ||
items *avl.Tree // pkgPath > Item | ||
itemsSorted *avl.Tree // same data but sorted, storing pointers | ||
*pausable.Pausable | ||
} | ||
|
||
Item struct { | ||
id seqid.ID | ||
pkgpath string | ||
blockNum int64 | ||
upvote *avl.Tree // std.Addr > struct{}{} | ||
downvote *avl.Tree // std.Addr > struct{}{} | ||
} | ||
) | ||
|
||
func init() { | ||
exhibition = &Exhibition{ | ||
items: avl.NewTree(), | ||
itemsSorted: avl.NewTree(), | ||
} | ||
|
||
owner = ownable.NewWithAddress(std.Address("g125em6arxsnj49vx35f0n0z34putv5ty3376fg5")) | ||
exhibition.Pausable = pausable.NewFromOwnable(owner) | ||
} | ||
|
||
// Register registers your realm to the Hall of Fame | ||
// Should be called from within code | ||
func Register() { | ||
if exhibition.IsPaused() { | ||
return | ||
} | ||
|
||
submission := std.PrevRealm() | ||
pkgpath := submission.PkgPath() | ||
|
||
// Must be called from code | ||
if submission.IsUser() { | ||
return | ||
} | ||
|
||
// Must not yet exist | ||
if exhibition.items.Has(pkgpath) { | ||
return | ||
} | ||
|
||
id := exhibition.itemCounter.Next() | ||
i := &Item{ | ||
id: id, | ||
pkgpath: pkgpath, | ||
blockNum: std.GetHeight(), | ||
upvote: avl.NewTree(), | ||
downvote: avl.NewTree(), | ||
} | ||
|
||
exhibition.items.Set(pkgpath, i) | ||
exhibition.itemsSorted.Set(id.String(), i) | ||
|
||
std.Emit("Registration") | ||
} | ||
|
||
func Upvote(pkgpath string) { | ||
rawItem, ok := exhibition.items.Get(pkgpath) | ||
if !ok { | ||
panic(ErrNoSuchItem.Error()) | ||
} | ||
|
||
item := rawItem.(*Item) | ||
caller := std.PrevRealm().Addr().String() | ||
|
||
if item.upvote.Has(caller) { | ||
panic(ErrDoubleUpvote.Error()) | ||
} | ||
|
||
item.upvote.Set(caller, struct{}{}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why not just There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't |
||
} | ||
|
||
func Downvote(pkgpath string) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you downvote and upvote the same item? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I thought about leaving it that way, but maybe a better option is to always reset the opposite vote if the user is voting. |
||
rawItem, ok := exhibition.items.Get(pkgpath) | ||
if !ok { | ||
panic(ErrNoSuchItem.Error()) | ||
} | ||
|
||
item := rawItem.(*Item) | ||
caller := std.PrevRealm().Addr().String() | ||
|
||
if item.downvote.Has(caller) { | ||
panic(ErrDoubleDownvote.Error()) | ||
} | ||
|
||
item.downvote.Set(caller, struct{}{}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you can only upvote or downvote, why don't just There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's easier to get the num of upvotes/downvotes if we have two trees and just get their size; otherwise you'd have to iterate and count |
||
} | ||
|
||
func Delete(pkgpath string) { | ||
if err := owner.CallerIsOwner(); err != nil { | ||
panic(err) | ||
} | ||
|
||
i, ok := exhibition.items.Get(pkgpath) | ||
if !ok { | ||
panic(ErrNoSuchItem.Error()) | ||
} | ||
|
||
if _, removed := exhibition.itemsSorted.Remove(i.(*Item).id.String()); !removed { | ||
panic(ErrNoSuchItem.Error()) | ||
} | ||
|
||
if _, removed := exhibition.items.Remove(pkgpath); !removed { | ||
panic(ErrNoSuchItem.Error()) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is not the same as before?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, just thought its better to use the methods available on
std.Address
(showcasing the fact that it exists)