Skip to content

Commit

Permalink
Merge branch 'main' into refactor-launchpad
Browse files Browse the repository at this point in the history
  • Loading branch information
notJoon authored Dec 27, 2024
2 parents 953f6a3 + e138837 commit 779fb46
Show file tree
Hide file tree
Showing 100 changed files with 5,899 additions and 3,377 deletions.
26 changes: 26 additions & 0 deletions _deploy/r/gnoswap/common/grc20reg_helper.gno
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package common

import (
"regexp"
"std"
"strings"

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

var (
re = regexp.MustCompile(`\[gno\.land/r/[^\]]+\]`)
)

// GetToken returns a grc20.Token instance
// if token is not registered, it will panic
// token instance supports following methods:
Expand Down Expand Up @@ -58,6 +64,26 @@ func MustRegistered(path string) {
}
}

// ListRegisteredTokens returns the list of registered tokens
// NOTE:
// - Unfortunate, grc20reg doesn't support this.
// - We need to parse the rendered grc20reg page to get the list of registered tokens.
func ListRegisteredTokens() []string {
render := grc20reg.Render("")
return extractTokenPathsFromRender(render)
}

func extractTokenPathsFromRender(render string) []string {
matches := re.FindAllString(render, -1)

tokenPaths := make([]string, 0, len(matches))
for _, match := range matches {
tokenPath := strings.Trim(match, "[]") // Remove the brackets
tokenPaths = append(tokenPaths, tokenPath)
}
return tokenPaths
}

// TotalSupply returns the total supply of the token
func TotalSupply(path string) uint64 {
return GetToken(path).TotalSupply()
Expand Down
87 changes: 87 additions & 0 deletions _deploy/r/gnoswap/common/grc20reg_helper_test.gno
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,74 @@ func TestMustRegistered(t *testing.T) {
})
}

func TestListRegisteredTokens(t *testing.T) {
t.Skip("skipping tests -> can not mock grc20reg.Render() || testing extractTokenPathsFromRender() does cover this")
}

func TestExtractTokenPathsFromRender(t *testing.T) {
var (
wugnotPath = "gno.land/r/demo/wugnot"
gnsPath = "gno.land/r/gnoswap/v1/gns"
fooPath = "gno.land/r/onbloc/foo"
quxPath = "gno.land/r/onbloc/qux"
)

// NOTE: following strings are return from grc20reg.Render()
renderList := []string{
// no registered token
`No registered token.`,

// 1 token
`- **wrapped GNOT** - [gno.land/r/demo/wugnot](/r/demo/wugnot) - [info](/r/demo/grc20reg:gno.land/r/demo/wugnot)`,

// 2 tokens
`- **wrapped GNOT** - [gno.land/r/demo/wugnot](/r/demo/wugnot) - [info](/r/demo/grc20reg:gno.land/r/demo/wugnot)
- **Gnoswap** - [gno.land/r/gnoswap/v1/gns](/r/gnoswap/v1/gns) - [info](/r/demo/grc20reg:gno.land/r/gnoswap/v1/gns)
`,

// 4 tokens
`- **wrapped GNOT** - [gno.land/r/demo/wugnot](/r/demo/wugnot) - [info](/r/demo/grc20reg:gno.land/r/demo/wugnot)
- **Gnoswap** - [gno.land/r/gnoswap/v1/gns](/r/gnoswap/v1/gns) - [info](/r/demo/grc20reg:gno.land/r/gnoswap/v1/gns)
- **Baz** - [gno.land/r/onbloc/foo](/r/onbloc/foo) - [info](/r/demo/grc20reg:gno.land/r/onbloc/foo)
- **Qux** - [gno.land/r/onbloc/qux](/r/onbloc/qux) - [info](/r/demo/grc20reg:gno.land/r/onbloc/qux)
`,
}

tests := []struct {
name string
render string
expected []string
}{
{
name: "no registered token",
render: renderList[0],
expected: []string{},
},
{
name: "1 registered token",
render: renderList[1],
expected: []string{wugnotPath},
},
{
name: "2 registered tokens",
render: renderList[2],
expected: []string{wugnotPath, gnsPath},
},
{
name: "4 registered tokens",
render: renderList[3],
expected: []string{wugnotPath, gnsPath, fooPath, quxPath},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
extracted := extractTokenPathsFromRender(tt.render)
uassert.True(t, areSlicesEqual(t, tt.expected, extracted))
})
}
}

func TestTotalSupply(t *testing.T) {
// result from grc2reg and (direct import/call) should be the same
uassert.Equal(t, foo20.TotalSupply(), TotalSupply(tokenPath))
Expand All @@ -172,3 +240,22 @@ func TestAllowance(t *testing.T) {
// result from grc2reg and (direct import/call) should be the same
uassert.Equal(t, foo20.Allowance(AddrToUser(owner), AddrToUser(spender)), Allowance(tokenPath, owner, spender))
}

// areSlicesEqual compares two slices of strings
func areSlicesEqual(t *testing.T, a, b []string) bool {
t.Helper()

// Check if lengths are different
if len(a) != len(b) {
return false
}

// Compare each element
for i := range a {
if a[i] != b[i] {
return false
}
}

return true
}
2 changes: 1 addition & 1 deletion _deploy/r/gnoswap/consts/consts.gno
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const (

TOKEN_REGISTER_NAMESPACE string = "gno.land/r/g1er355fkjksqpdtwmhf5penwa82p0rhqxkkyhk5"

BLOCK_GENERATION_INTERVAL int64 = 1 // seconds
BLOCK_GENERATION_INTERVAL int64 = 2 // seconds
)

// WRAP & UNWRAP
Expand Down
5 changes: 4 additions & 1 deletion _deploy/r/gnoswap/gnft/errors.gno
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import (
)

var (
errNoPermission = errors.New("[GNOSWAP-GNFT-001] caller has no permission")
errNoPermission = errors.New("[GNOSWAP-GNFT-001] caller has no permission")
errCannotSetURI = errors.New("[GNOSWAP-GNFT-002] cannot set URI")
errNoTokenForCaller = errors.New("[GNOSWAP-GNFT-003] no token for caller")
errInvalidAddress = errors.New("[GNOSWAP-GNFT-004] invalid addresss")
)

func addDetailToError(err error, detail string) string {
Expand Down
Loading

0 comments on commit 779fb46

Please sign in to comment.