Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

grc20reg_test.gno

4.44 Kb · 141 lines
  1package grc20reg
  2
  3import (
  4	"strings"
  5	"testing"
  6
  7	"gno.land/p/demo/tokens/grc20"
  8	"gno.land/p/nt/urequire/v0"
  9)
 10
 11func TestRegistry(cur realm, t *testing.T) {
 12	testing.SetRealm(testing.NewCodeRealm("gno.land/r/demo/foo"))
 13	token, ledger := grc20.NewToken("TestToken", "TST", 4, 0, cur)
 14	ledger.Mint(cur.Address(), 1234567)
 15	// register
 16	key := Register(cross(cur), token, "mySlug")
 17	regToken := Get(key)
 18	urequire.True(t, regToken != nil, "expected to find a token") // fixme: use urequire.NotNil
 19	urequire.Equal(t, regToken.GetSymbol(), "TST")
 20
 21	expected := `- **TestToken** - [gno.land/r/demo/foo](/r/demo/foo).TST - [info](/r/demo/grc20reg:gno.land/r/demo/foo.TST)
 22`
 23	got := Render("")
 24	urequire.True(t, strings.Contains(got, expected))
 25	// 404
 26	invalidToken := Get("0xdeadbeef")
 27	urequire.True(t, invalidToken == nil)
 28
 29	got = Render("")
 30	urequire.True(t, strings.Contains(got, expected))
 31
 32	expected = `# TestToken
 33- symbol: **TST**
 34- realm: [gno.land/r/demo/foo](/r/demo/foo).TST
 35- decimals: 4
 36- total supply: 1234567
 37`
 38	got = Render(key)
 39	urequire.Equal(t, expected, got)
 40
 41	// The registry keys by rlmPath.symbol, so a second token with the same
 42	// symbol in the same realm is rejected even though its Token.ID() differs
 43	// (distinct trailing sequence id). See TestRegisterRejectsOverwrite.
 44	second, _ := grc20.NewToken("Second", "TST", 4, 1, cur)
 45	urequire.NotEqual(t, token.ID(), second.ID()) // ids are decoupled from symbol
 46	urequire.AbortsContains(t, cur, "token already registered", func() {
 47		Register(cross(cur), second, "")
 48	})
 49}
 50
 51func TestRegisterRejectsOverwrite(cur realm, t *testing.T) {
 52	testing.SetRealm(testing.NewCodeRealm("gno.land/r/demo/grc20reg_overwrite"))
 53	token, ledger := grc20.NewToken("Bar", "BAR", 4, 0, cur)
 54	ledger.Mint(cur.Address(), 11)
 55	key := Register(cross(cur), token, "")
 56
 57	urequire.Equal(t, "BAR", Get(key).GetSymbol())
 58	urequire.Equal(t, int64(11), Get(key).BalanceOf(cur.Address()))
 59
 60	replacement, _ := grc20.NewToken("Replacement", "BAR", 6, 0, cur)
 61	urequire.AbortsContains(t, cur, "token already registered", func() {
 62		Register(cross(cur), replacement, "")
 63	})
 64}
 65
 66func TestRegisterRejectsAliasedTokenPaths(cur realm, t *testing.T) {
 67	testing.SetRealm(testing.NewCodeRealm("gno.land/r/demo/grc20reg_alias"))
 68	token, _ := grc20.NewToken("Aliased Token", "ALIAS", 4, 0, cur)
 69	Register(cross(cur), token, "first")
 70
 71	urequire.AbortsContains(t, cur, "token already registered", func() {
 72		Register(cross(cur), token, "second")
 73	})
 74}
 75
 76func TestRegisterRejectsTokenFromDifferentRealm(cur realm, t *testing.T) {
 77	testing.SetRealm(testing.NewCodeRealm("gno.land/r/demo/grc20reg_id_source"))
 78	token, _ := grc20.NewToken("Mismatch Token", "MISMATCH", 4, 0, cur)
 79
 80	testing.SetRealm(testing.NewCodeRealm("gno.land/r/demo/grc20reg_id_target"))
 81	urequire.AbortsContains(t, cur, "token must be registered from its own realm", func() {
 82		Register(cross(cur), token, "")
 83	})
 84}
 85
 86func TestValidateSlug(cur realm, t *testing.T) {
 87	// Valid slugs — should not panic
 88	valid := []string{"mytoken", "my-token", "my_token", "Token123", "a", "A-B_c", strings.Repeat("a", maxSlugLen)}
 89	for _, slug := range valid {
 90		validateSlug(slug) // no panic = pass
 91	}
 92}
 93
 94func TestValidateSlugPanicsOnTooLong(cur realm, t *testing.T) {
 95	defer func() { recover() }()
 96	validateSlug(strings.Repeat("a", maxSlugLen+1))
 97	t.Errorf("should have panicked")
 98}
 99
100func TestValidateSlugPanicsOnSpace(cur realm, t *testing.T) {
101	defer func() { recover() }()
102	validateSlug("has space")
103	t.Errorf("should have panicked")
104}
105
106func TestValidateSlugPanicsOnDot(cur realm, t *testing.T) {
107	defer func() { recover() }()
108	validateSlug("has.dot")
109	t.Errorf("should have panicked")
110}
111
112func TestValidateSlugPanicsOnSlash(cur realm, t *testing.T) {
113	defer func() { recover() }()
114	validateSlug("has/slash")
115	t.Errorf("should have panicked")
116}
117
118func TestValidateSlugPanicsOnBrackets(cur realm, t *testing.T) {
119	defer func() { recover() }()
120	validateSlug("[brackets]")
121	t.Errorf("should have panicked")
122}
123
124func TestValidateSlugPanicsOnParens(cur realm, t *testing.T) {
125	defer func() { recover() }()
126	validateSlug("(parens)")
127	t.Errorf("should have panicked")
128}
129
130func TestValidateSlugPanicsOnInjection(cur realm, t *testing.T) {
131	defer func() { recover() }()
132	validateSlug(`) [Claim](https://evil.com`)
133	t.Errorf("should have panicked")
134}
135
136func TestRegisterRejectsNilToken(cur realm, t *testing.T) {
137	testing.SetRealm(testing.NewCodeRealm("gno.land/r/demo/grc20reg_nil"))
138	urequire.AbortsContains(t, cur, "nil token", func() {
139		Register(cross(cur), nil, "")
140	})
141}