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

feat: grc20 registry #1072

Closed
wants to merge 1 commit into from
Closed
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
2 changes: 2 additions & 0 deletions examples/gno.land/r/demo/foo20/foo20.gno
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"gno.land/p/demo/grc/grc20"
"gno.land/p/demo/ufmt"
"gno.land/r/demo/grc20_registry"
"gno.land/r/demo/users"
)

Expand All @@ -16,6 +17,7 @@ var (

func init() {
foo = grc20.NewAdminToken("Foo", "FOO", 4)
grc20_registry.Register(foo.GRC20())
foo.Mint(admin, 1000000*10000) // @administrator (1M)
foo.Mint("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq", 10000*10000) // @manfred (10k)
}
Expand Down
1 change: 1 addition & 0 deletions examples/gno.land/r/demo/foo20/gno.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ require (
"gno.land/p/demo/ufmt" v0.0.0-latest
"gno.land/p/demo/grc/grc20" v0.0.0-latest
"gno.land/r/demo/users" v0.0.0-latest
"gno.land/r/demo/grc20_registry" v0.0.0-latest
)
6 changes: 6 additions & 0 deletions examples/gno.land/r/demo/grc20_registry/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module gno.land/r/demo/grc20_registry

require (
"gno.land/p/demo/avl" v0.0.0-latest
"gno.land/p/demo/grc/grc20" v0.0.0-latest
)
44 changes: 44 additions & 0 deletions examples/gno.land/r/demo/grc20_registry/grc20_registry.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package grc20_registry

import (
"std"
"strings"

"gno.land/p/demo/avl"
"gno.land/p/demo/grc/grc20"
)

var registry = avl.NewTree() // pkg path -> IGRC20

func Register(token grc20.IGRC20) {
caller := std.PrevRealm().PkgPath()
registry.Set(caller, token)
Comment on lines +13 to +15
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func Register(token grc20.IGRC20) {
caller := std.PrevRealm().PkgPath()
registry.Set(caller, token)
func Register(optKey string, token grc20.IGRC20) {
rlmPath := std.PrevRealm().PkgPath()
if optKey != "" {
rlmPath += "." + optKey
}
registry.Set(optKey, token)

To support registering several tokens from the same contract.

}

func Get(pkgPath string) (grc20.IGRC20, bool) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func Get(pkgPath string) (grc20.IGRC20, bool) {
func Get(pkgPath string) grc20.IGRC20 {

bool is not needed, != nil is enough.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func Get(pkgPath string) (grc20.IGRC20, bool) {
func Get(key string) (grc20.IGRC20, bool) {

coinI, ok := registry.Get(pkgPath)
if !ok {
return nil, false
}
coin, ok := coinI.(grc20.IGRC20)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this check is unnecessary, protected by Register.

if !ok {
panic("internal error: registered object is not a GRC20 token")
}
return coin, true
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a MustGet(pkgPath string) grc20.IGRC20 that panics if not found.

func Render(path string) string {
s := "# GRC20 Registry\n\n" +
"## Registered Tokens\n\n"
Comment on lines +31 to +32
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
s := "# GRC20 Registry\n\n" +
"## Registered Tokens\n\n"
s := "# GRC20 Registry\n\n"

concise output.

registry.Iterate("", "", func(pkgPath string, tokenI interface{}) bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a todo comment to add pagination.

token, ok := tokenI.(grc20.IGRC20)
pkgWebPath := strings.TrimPrefix(pkgPath, "gno.land")
if ok {
s += "- [" + token.GetName() + " (" + pkgPath + ")](" + pkgWebPath + ")\n"
} else {
s += "- [internal error: registered object is not a GRC20 token (" + pkgPath + ")](" + pkgWebPath + ")\n"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this check.

}
return false
})
return s
}
55 changes: 55 additions & 0 deletions examples/gno.land/r/demo/grc20_registry/grc20_registry_test.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package grc20_registry

import (
"std"
"testing"

"gno.land/p/demo/grc/grc20"
)

func TestRegistry(t *testing.T) {
coin := &dummyImpl{}
realmAddr := std.CurrentRealm().PkgPath()
Register(coin)
regCoin, ok := Get(realmAddr)
if !ok {
t.Fatal("expected to find coin")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can now use uassert if you want more concise tests :)

}
if coin.GetSymbol() != "TST" {
t.Fatal("expected coin to have symbol TST")
}
expected := `# GRC20 Registry

## Registered Tokens

* [TestToken ()]()
`
got := Render("")
if got != expected {
t.Fatalf("expected `%s`, got `%s`", expected, got)
}

// we test this here because there is more chance to find a bug after a token has been registered
if _, ok := Get("0xdeadbeef"); ok {
t.Fatal("expected not to find coin")
}
}

type dummyImpl struct{}

// FIXME: this should fail.
var _ grc20.IGRC20 = (*dummyImpl)(nil)

func (impl *dummyImpl) GetName() string { return "TestToken" }
func (impl *dummyImpl) GetSymbol() string { return "TST" }
func (impl *dummyImpl) GetDecimals() uint { panic("not implemented") }
func (impl *dummyImpl) TotalSupply() uint64 { panic("not implemented") }
func (impl *dummyImpl) BalanceOf(account std.Address) (uint64, error) { panic("not implemented") }
func (impl *dummyImpl) Transfer(to std.Address, amount uint64) error { panic("not implemented") }
func (impl *dummyImpl) Allowance(owner, spender std.Address) (uint64, error) {
panic("not implemented")
}
func (impl *dummyImpl) Approve(spender std.Address, amount uint64) error { panic("not implemented") }
func (impl *dummyImpl) TransferFrom(from, to std.Address, amount uint64) error {
panic("not implemented")
}
Loading