From 2869189d28d7284a084ab061ada76db03929472d Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 26 Sep 2023 23:17:55 -0700 Subject: [PATCH 01/21] chore: dynamic homepage Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/system/home/home.gno | 5 +++++ examples/gno.land/r/system/home/home_filetest.gno | 10 ++++++++++ 2 files changed, 15 insertions(+) create mode 100644 examples/gno.land/r/system/home/home.gno create mode 100644 examples/gno.land/r/system/home/home_filetest.gno diff --git a/examples/gno.land/r/system/home/home.gno b/examples/gno.land/r/system/home/home.gno new file mode 100644 index 00000000000..9feb5d3ad7e --- /dev/null +++ b/examples/gno.land/r/system/home/home.gno @@ -0,0 +1,5 @@ +package home + +func Render(_ string) string { + return "Hello World!" +} diff --git a/examples/gno.land/r/system/home/home_filetest.gno b/examples/gno.land/r/system/home/home_filetest.gno new file mode 100644 index 00000000000..652b3175181 --- /dev/null +++ b/examples/gno.land/r/system/home/home_filetest.gno @@ -0,0 +1,10 @@ +package main + +import "gno.land/r/system/home" + +func main() { + println(home.Render("")) +} + +// Output: +// Hello World! From 0d0221647853585dbb297b5610e27f6d0a602448 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 26 Sep 2023 23:22:10 -0700 Subject: [PATCH 02/21] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/system/home/home.gno | 54 ++++++++++++++++++- .../gno.land/r/system/home/home_filetest.gno | 51 +++++++++++++++++- 2 files changed, 103 insertions(+), 2 deletions(-) diff --git a/examples/gno.land/r/system/home/home.gno b/examples/gno.land/r/system/home/home.gno index 9feb5d3ad7e..ca6f5d028a5 100644 --- a/examples/gno.land/r/system/home/home.gno +++ b/examples/gno.land/r/system/home/home.gno @@ -1,5 +1,57 @@ package home +var body = `# Welcome to **Gno.land** + +- [About Gno.land](/about) +- [Blogs](/r/gnoland/blog) +- [Install ` + "`" + `gnokey` + "`" + `](https://github.com/gnolang/gno/tree/master/gno.land/cmd/gnokey) +- [Acquire testnet tokens](/faucet) +- [Game of Realms](/game-of-realms) - An open worldwide competition for developers to build the best Gnolang smart-contracts. + +# Explore new packages. + +- r/gnoland + - [/r/gnoland/blog](/r/gnoland/blog) + - [/r/gnoland/faucet](/r/gnoland/faucet) +- r/system + - [/r/system/names](/r/system/names) + - [/r/system/rewards](/r/system/rewards) + - [/r/system/validators](/r/system/validators) +- r/demo + - [/r/demo/banktest](/r/demo/banktest) + - [/r/demo/boards](/r/demo/boards) + - [/r/demo/foo20](/r/demo/foo20) + - [/r/demo/nft](/r/demo/nft) + - [/r/demo/types](/r/demo/types) + - [/r/demo/users](/r/demo/users) + - [/r/demo/groups](/r/demo/groups) +- p/demo + - [/p/demo/avl](/p/demo/avl) + - [/p/demo/blog](/p/demo/blog) + - [/p/demo/flow](/p/demo/flow) + - [/p/demo/gnode](/p/demo/gnode) + - [/p/demo/grc/exts](/p/demo/grc/exts) + - [/p/demo/grc/grc20](/p/demo/grc/grc20) + - [/p/demo/grc/grc721](/p/demo/grc/grc721) + +# Other Testnets + +- **[staging.gno.land](https://staging.gno.land) (wiped every commit to master)** +- _[test3.gno.land](https://test3.gno.land) (latest)_ +- _[test2.gno.land](https://test2.gno.land) (archive)_ +- _[test1.gno.land](https://test1.gno.land) (archive)_ + +**This is a testnet.** +Package names are not guaranteed to be available for production. + +# Social + +Check out our [community projects](https://github.com/gnolang/awesome-gno). + +Official channel: [Discord](https://discord.gg/S8nKUqwkPn)
+Other channels: [Telegram](https://t.me/gnoland) [Twitter](https://twitter.com/_gnoland) [Youtube](https://www.youtube.com/@_gnoland) +` + func Render(_ string) string { - return "Hello World!" + return body } diff --git a/examples/gno.land/r/system/home/home_filetest.gno b/examples/gno.land/r/system/home/home_filetest.gno index 652b3175181..a01f08f8ab2 100644 --- a/examples/gno.land/r/system/home/home_filetest.gno +++ b/examples/gno.land/r/system/home/home_filetest.gno @@ -7,4 +7,53 @@ func main() { } // Output: -// Hello World! +// # Welcome to **Gno.land** +// +// - [About Gno.land](/about) +// - [Blogs](/r/gnoland/blog) +// - [Install `gnokey`](https://github.com/gnolang/gno/tree/master/gno.land/cmd/gnokey) +// - [Acquire testnet tokens](/faucet) +// - [Game of Realms](/game-of-realms) - An open worldwide competition for developers to build the best Gnolang smart-contracts. +// +// # Explore new packages. +// +// - r/gnoland +// - [/r/gnoland/blog](/r/gnoland/blog) +// - [/r/gnoland/faucet](/r/gnoland/faucet) +// - r/system +// - [/r/system/names](/r/system/names) +// - [/r/system/rewards](/r/system/rewards) +// - [/r/system/validators](/r/system/validators) +// - r/demo +// - [/r/demo/banktest](/r/demo/banktest) +// - [/r/demo/boards](/r/demo/boards) +// - [/r/demo/foo20](/r/demo/foo20) +// - [/r/demo/nft](/r/demo/nft) +// - [/r/demo/types](/r/demo/types) +// - [/r/demo/users](/r/demo/users) +// - [/r/demo/groups](/r/demo/groups) +// - p/demo +// - [/p/demo/avl](/p/demo/avl) +// - [/p/demo/blog](/p/demo/blog) +// - [/p/demo/flow](/p/demo/flow) +// - [/p/demo/gnode](/p/demo/gnode) +// - [/p/demo/grc/exts](/p/demo/grc/exts) +// - [/p/demo/grc/grc20](/p/demo/grc/grc20) +// - [/p/demo/grc/grc721](/p/demo/grc/grc721) +// +// # Other Testnets +// +// - **[staging.gno.land](https://staging.gno.land) (wiped every commit to master)** +// - _[test3.gno.land](https://test3.gno.land) (latest)_ +// - _[test2.gno.land](https://test2.gno.land) (archive)_ +// - _[test1.gno.land](https://test1.gno.land) (archive)_ +// +// **This is a testnet.** +// Package names are not guaranteed to be available for production. +// +// # Social +// +// Check out our [community projects](https://github.com/gnolang/awesome-gno). +// +// Official channel: [Discord](https://discord.gg/S8nKUqwkPn)
+// Other channels: [Telegram](https://t.me/gnoland) [Twitter](https://twitter.com/_gnoland) [Youtube](https://www.youtube.com/@_gnoland) From 6ab3e903c368d6d8d85b9b86fbfe2664c3da7527 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Wed, 27 Sep 2023 11:14:42 -0700 Subject: [PATCH 03/21] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/cmd/gnoweb/main.go | 39 ++++++++++++++++++------ gno.land/cmd/gnoweb/pages/HOME.md | 50 ------------------------------- 2 files changed, 30 insertions(+), 59 deletions(-) delete mode 100644 gno.land/cmd/gnoweb/pages/HOME.md diff --git a/gno.land/cmd/gnoweb/main.go b/gno.land/cmd/gnoweb/main.go index e8a2feac0d7..f5bcb0d6d27 100644 --- a/gno.land/cmd/gnoweb/main.go +++ b/gno.land/cmd/gnoweb/main.go @@ -95,16 +95,37 @@ func main() { } func handlerHome(app gotuna.App) http.Handler { - md := filepath.Join(flags.pagesDir, "HOME.md") - homeContent := osm.MustReadFile(md) + rlmpath := "gno.land/r/system/home" + querystr := "" + qpath := "vm/qrender" + rlmName := "home" + data := []byte(fmt.Sprintf("%s\n%s", rlmpath, querystr)) + res, err := makeRequest(qpath, data) + if err != nil { + // XXX: better default handler. + writeError(w, err) + } + // Render template. + tmpl := app.NewTemplatingEngine() + tmpl.Set("RealmName", rlmname) + tmpl.Set("RealmPath", rlmpath) + tmpl.Set("Query", querystr) + tmpl.Set("Contents", string(res.Data)) + // XXX: home + tmpl.Render(w, r, "realm_render.html", "funcs.html") - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - app.NewTemplatingEngine(). - Set("Title", "Gno.land Smart Contract Platform Using Gnolang (Gno)"). - Set("Description", "Gno.land is the only smart contract platform using the Gnolang (Gno) programming language, an interpretation of the widely-used Golang (Go)."). - Set("HomeContent", string(homeContent)). - Render(w, r, "home.html", "funcs.html") - }) + /* + md := filepath.Join(flags.pagesDir, "HOME.md") + homeContent := osm.MustReadFile(md) + + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + app.NewTemplatingEngine(). + Set("Title", "Gno.land Smart Contract Platform Using Gnolang (Gno)"). + Set("Description", "Gno.land is the only smart contract platform using the Gnolang (Gno) programming language, an interpretation of the widely-used Golang (Go)."). + Set("HomeContent", string(homeContent)). + Render(w, r, "home.html", "funcs.html") + }) + */ } func handlerAbout(app gotuna.App) http.Handler { diff --git a/gno.land/cmd/gnoweb/pages/HOME.md b/gno.land/cmd/gnoweb/pages/HOME.md deleted file mode 100644 index 0f3bfaec685..00000000000 --- a/gno.land/cmd/gnoweb/pages/HOME.md +++ /dev/null @@ -1,50 +0,0 @@ -# Welcome to **Gno.land** - -- [About Gno.land](/about) -- [Blogs](/r/gnoland/blog) -- [Install `gnokey`](https://github.com/gnolang/gno/tree/master/gno.land/cmd/gnokey) -- [Acquire testnet tokens](/faucet) -- [Game of Realms](/game-of-realms) - An open worldwide competition for developers to build the best Gnolang smart-contracts. - -# Explore new packages. - -- r/gnoland - - [/r/gnoland/blog](/r/gnoland/blog) - - [/r/gnoland/faucet](/r/gnoland/faucet) -- r/system - - [/r/system/names](/r/system/names) - - [/r/system/rewards](/r/system/rewards) - - [/r/system/validators](/r/system/validators) -- r/demo - - [/r/demo/banktest](/r/demo/banktest) - - [/r/demo/boards](/r/demo/boards) - - [/r/demo/foo20](/r/demo/foo20) - - [/r/demo/nft](/r/demo/nft) - - [/r/demo/types](/r/demo/types) - - [/r/demo/users](/r/demo/users) - - [/r/demo/groups](/r/demo/groups) -- p/demo - - [/p/demo/avl](/p/demo/avl) - - [/p/demo/blog](/p/demo/blog) - - [/p/demo/flow](/p/demo/flow) - - [/p/demo/gnode](/p/demo/gnode) - - [/p/demo/grc/exts](/p/demo/grc/exts) - - [/p/demo/grc/grc20](/p/demo/grc/grc20) - - [/p/demo/grc/grc721](/p/demo/grc/grc721) - -# Other Testnets - -- **[staging.gno.land](https://staging.gno.land) (wiped every commit to master)** -- _[test3.gno.land](https://test3.gno.land) (latest)_ -- _[test2.gno.land](https://test2.gno.land) (archive)_ -- _[test1.gno.land](https://test1.gno.land) (archive)_ - -**This is a testnet.** -Package names are not guaranteed to be available for production. - -# Social - -Check out our [community projects](https://github.com/gnolang/awesome-gno). - -Official channel: [Discord](https://discord.gg/S8nKUqwkPn)
-Other channels: [Telegram](https://t.me/gnoland) [Twitter](https://twitter.com/_gnoland) [Youtube](https://www.youtube.com/@_gnoland) From 329e1cf7fc1d13e65bc2a71f4da611eb8eb098a7 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Wed, 27 Sep 2023 15:39:41 -0700 Subject: [PATCH 04/21] chore: wip Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/system/home/home.gno | 30 +++++++++++++ gno.land/Makefile | 3 ++ gno.land/cmd/gnoweb/main.go | 55 +++++++++++------------- 3 files changed, 57 insertions(+), 31 deletions(-) diff --git a/examples/gno.land/r/system/home/home.gno b/examples/gno.land/r/system/home/home.gno index ca6f5d028a5..8b46a4d418c 100644 --- a/examples/gno.land/r/system/home/home.gno +++ b/examples/gno.land/r/system/home/home.gno @@ -52,6 +52,36 @@ Official channel: [Discord](https://discord.gg/S8nKUqwkPn)
Other channels: [Telegram](https://t.me/gnoland) [Twitter](https://twitter.com/_gnoland) [Youtube](https://www.youtube.com/@_gnoland) ` +var adminAddr std.Address = std.Address("") + func Render(_ string) string { + // highest level == highest responsibility + // teams are responsible for components they don't owne + // flag : realm maintainers VS facilitators + // teams + // committee of trustees to create the directory + // each directory is a name, has a parent and have groups + // homepage team - blocks aggregating events + ` +# Directory + +* gno.land (owned by group) + * +* gnovm + * gnolang (language) + * gnovm + - current challenges / concerns / issues +* tm2 + * amino + * + +## Contributors +`` + + + // XXX: dynamic content: contributions + // XXX: + // XXX: community curated picks + // XXX: return body } diff --git a/gno.land/Makefile b/gno.land/Makefile index 117de18fc46..49620ac552a 100644 --- a/gno.land/Makefile +++ b/gno.land/Makefile @@ -5,6 +5,9 @@ help: rundep=go run -modfile ../misc/devdeps/go.mod +.PHONY: gnoland.start +gnoland.start:; go run ./cmd/gnoland start + .PHONY: build build: build.gnoland build.gnokey build.gnoweb build.gnofaucet build.gnotxsync diff --git a/gno.land/cmd/gnoweb/main.go b/gno.land/cmd/gnoweb/main.go index f5bcb0d6d27..34519c1111e 100644 --- a/gno.land/cmd/gnoweb/main.go +++ b/gno.land/cmd/gnoweb/main.go @@ -95,37 +95,22 @@ func main() { } func handlerHome(app gotuna.App) http.Handler { - rlmpath := "gno.land/r/system/home" - querystr := "" - qpath := "vm/qrender" - rlmName := "home" - data := []byte(fmt.Sprintf("%s\n%s", rlmpath, querystr)) - res, err := makeRequest(qpath, data) - if err != nil { - // XXX: better default handler. - writeError(w, err) - } - // Render template. - tmpl := app.NewTemplatingEngine() - tmpl.Set("RealmName", rlmname) - tmpl.Set("RealmPath", rlmpath) - tmpl.Set("Query", querystr) - tmpl.Set("Contents", string(res.Data)) - // XXX: home - tmpl.Render(w, r, "realm_render.html", "funcs.html") - - /* - md := filepath.Join(flags.pagesDir, "HOME.md") - homeContent := osm.MustReadFile(md) - - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - app.NewTemplatingEngine(). - Set("Title", "Gno.land Smart Contract Platform Using Gnolang (Gno)"). - Set("Description", "Gno.land is the only smart contract platform using the Gnolang (Gno) programming language, an interpretation of the widely-used Golang (Go)."). - Set("HomeContent", string(homeContent)). - Render(w, r, "home.html", "funcs.html") - }) - */ + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + rlmpath := "gno.land/r/system/home" + querystr := "?from-home" + qpath := "vm/qrender" + data := []byte(fmt.Sprintf("%s\n%s", rlmpath, querystr)) + res, err := makeRequest(qpath, data) + if err != nil { + writeError(w, fmt.Errorf("gnoweb failed to query gnoland: %w", err)) + return + } + tmpl := app.NewTemplatingEngine() + tmpl.Set("HomeContent", string(res.Data)) + tmpl.Set("Title", "Gno.land Smart Contract Platform Using Gnolang (Gno)") + tmpl.Set("Description", "Gno.land is the only smart contract platform using the Gnolang (Gno) programming language, an interpretation of the widely-used Golang (Go).") + tmpl.Render(w, r, "home.html", "funcs.html") + }) } func handlerAbout(app gotuna.App) http.Handler { @@ -457,7 +442,15 @@ func handleNotFound(app gotuna.App, path string, w http.ResponseWriter, r *http. } func writeError(w http.ResponseWriter, err error) { + // XXX: writeError should return an error page template. w.WriteHeader(500) + + details := errors.Unwrap(err).Error() + main := err.Error() + + fmt.Println("main", main) + fmt.Println("details", details) + w.Write([]byte(err.Error())) } From 0bc437593e5ed67d1f7b43fa7474299f418d2e46 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Wed, 27 Sep 2023 16:14:53 -0700 Subject: [PATCH 05/21] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/system/home/gno.mod | 1 + 1 file changed, 1 insertion(+) create mode 100644 examples/gno.land/r/system/home/gno.mod diff --git a/examples/gno.land/r/system/home/gno.mod b/examples/gno.land/r/system/home/gno.mod new file mode 100644 index 00000000000..6c404af1980 --- /dev/null +++ b/examples/gno.land/r/system/home/gno.mod @@ -0,0 +1 @@ +module gno.land/r/system/home \ No newline at end of file From dcc62813f1fd87905911b752188c99d58e3083d7 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 17 Oct 2023 11:05:57 +0200 Subject: [PATCH 06/21] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/gnoland/home/gno.mod | 1 + .../r/{system => gnoland}/home/home.gno | 32 ++++++++++--------- .../home/home_filetest.gno | 2 +- examples/gno.land/r/system/home/gno.mod | 1 - 4 files changed, 19 insertions(+), 17 deletions(-) create mode 100644 examples/gno.land/r/gnoland/home/gno.mod rename examples/gno.land/r/{system => gnoland}/home/home.gno (91%) rename examples/gno.land/r/{system => gnoland}/home/home_filetest.gno (98%) delete mode 100644 examples/gno.land/r/system/home/gno.mod diff --git a/examples/gno.land/r/gnoland/home/gno.mod b/examples/gno.land/r/gnoland/home/gno.mod new file mode 100644 index 00000000000..a943194ae5d --- /dev/null +++ b/examples/gno.land/r/gnoland/home/gno.mod @@ -0,0 +1 @@ +module gno.land/r/gnoland/home \ No newline at end of file diff --git a/examples/gno.land/r/system/home/home.gno b/examples/gno.land/r/gnoland/home/home.gno similarity index 91% rename from examples/gno.land/r/system/home/home.gno rename to examples/gno.land/r/gnoland/home/home.gno index 8b46a4d418c..569ad7671a0 100644 --- a/examples/gno.land/r/system/home/home.gno +++ b/examples/gno.land/r/gnoland/home/home.gno @@ -1,5 +1,7 @@ package home +import "std" + var body = `# Welcome to **Gno.land** - [About Gno.land](/about) @@ -62,26 +64,26 @@ func Render(_ string) string { // committee of trustees to create the directory // each directory is a name, has a parent and have groups // homepage team - blocks aggregating events - ` -# Directory -* gno.land (owned by group) - * -* gnovm - * gnolang (language) - * gnovm - - current challenges / concerns / issues -* tm2 - * amino - * + /*` + # Directory -## Contributors -`` + * gno.land (owned by group) + * + * gnovm + * gnolang (language) + * gnovm + - current challenges / concerns / issues + * tm2 + * amino + * + ## Contributors + ``*/ // XXX: dynamic content: contributions - // XXX: + // XXX: // XXX: community curated picks - // XXX: + // XXX: return body } diff --git a/examples/gno.land/r/system/home/home_filetest.gno b/examples/gno.land/r/gnoland/home/home_filetest.gno similarity index 98% rename from examples/gno.land/r/system/home/home_filetest.gno rename to examples/gno.land/r/gnoland/home/home_filetest.gno index a01f08f8ab2..d087837e983 100644 --- a/examples/gno.land/r/system/home/home_filetest.gno +++ b/examples/gno.land/r/gnoland/home/home_filetest.gno @@ -1,6 +1,6 @@ package main -import "gno.land/r/system/home" +import "gno.land/r/gnoland/home" func main() { println(home.Render("")) diff --git a/examples/gno.land/r/system/home/gno.mod b/examples/gno.land/r/system/home/gno.mod deleted file mode 100644 index 6c404af1980..00000000000 --- a/examples/gno.land/r/system/home/gno.mod +++ /dev/null @@ -1 +0,0 @@ -module gno.land/r/system/home \ No newline at end of file From a503ea72c8b9e2ccece7daada405462ebb4a4554 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 17 Oct 2023 11:06:45 +0200 Subject: [PATCH 07/21] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/cmd/gnoweb/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gno.land/cmd/gnoweb/main.go b/gno.land/cmd/gnoweb/main.go index 34519c1111e..de8d6c14bfe 100644 --- a/gno.land/cmd/gnoweb/main.go +++ b/gno.land/cmd/gnoweb/main.go @@ -96,7 +96,7 @@ func main() { func handlerHome(app gotuna.App) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - rlmpath := "gno.land/r/system/home" + rlmpath := "gno.land/r/gnoland/home" querystr := "?from-home" qpath := "vm/qrender" data := []byte(fmt.Sprintf("%s\n%s", rlmpath, querystr)) From f437c8e11e2ac88d599a1df4e11958b31aacf5f4 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 17 Oct 2023 19:28:52 +0200 Subject: [PATCH 08/21] chore: add redirects for famous urls Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/gnoland/home/home.gno | 2 +- .../gno.land/r/gnoland/home/home_filetest.gno | 2 +- examples/gno.land/r/gnoland/pages/pages.gno | 4 +++- gno.land/cmd/gnoweb/main.go | 22 ++++++++++++++----- gno.land/cmd/gnoweb/main_test.go | 5 ++++- 5 files changed, 25 insertions(+), 10 deletions(-) diff --git a/examples/gno.land/r/gnoland/home/home.gno b/examples/gno.land/r/gnoland/home/home.gno index 569ad7671a0..99d01b886c6 100644 --- a/examples/gno.land/r/gnoland/home/home.gno +++ b/examples/gno.land/r/gnoland/home/home.gno @@ -4,7 +4,7 @@ import "std" var body = `# Welcome to **Gno.land** -- [About Gno.land](/about) +- [About Gno.land](/r/gnoland/pages:about) - [Blogs](/r/gnoland/blog) - [Install ` + "`" + `gnokey` + "`" + `](https://github.com/gnolang/gno/tree/master/gno.land/cmd/gnokey) - [Acquire testnet tokens](/faucet) diff --git a/examples/gno.land/r/gnoland/home/home_filetest.gno b/examples/gno.land/r/gnoland/home/home_filetest.gno index d087837e983..56dccef2dbb 100644 --- a/examples/gno.land/r/gnoland/home/home_filetest.gno +++ b/examples/gno.land/r/gnoland/home/home_filetest.gno @@ -9,7 +9,7 @@ func main() { // Output: // # Welcome to **Gno.land** // -// - [About Gno.land](/about) +// - [About Gno.land](/r/gnoland/pages:about) // - [Blogs](/r/gnoland/blog) // - [Install `gnokey`](https://github.com/gnolang/gno/tree/master/gno.land/cmd/gnokey) // - [Acquire testnet tokens](/faucet) diff --git a/examples/gno.land/r/gnoland/pages/pages.gno b/examples/gno.land/r/gnoland/pages/pages.gno index dbc3d855880..9ad5a212c95 100644 --- a/examples/gno.land/r/gnoland/pages/pages.gno +++ b/examples/gno.land/r/gnoland/pages/pages.gno @@ -10,10 +10,12 @@ var b = &blog.Blog{ } func init() { - _ = b.NewPost("", "gor", "Game of Realms", "Lorem Ipsum", nil) + _ = b.NewPost("", "game-of-realms", "Game of Realms", "Lorem Ipsum", nil) _ = b.NewPost("", "events", "Events", "Lorem Ipsum", nil) _ = b.NewPost("", "tokenomics", "Tokenomics", "Lorem Ipsum", nil) _ = b.NewPost("", "start", "Getting Started", "Lorem Ipsum", nil) + _ = b.NewPost("", "about", "About Page", "Lorem Ipsum", nil) + _ = b.NewPost("", "language", "About Gnolang, the Gno Language", "Lorem Ipsum", nil) } func Render(path string) string { diff --git a/gno.land/cmd/gnoweb/main.go b/gno.land/cmd/gnoweb/main.go index de8d6c14bfe..f2a8ca3fb78 100644 --- a/gno.land/cmd/gnoweb/main.go +++ b/gno.land/cmd/gnoweb/main.go @@ -68,7 +68,20 @@ func makeApp() gotuna.App { app.Router.Handle("/about", handlerAbout(app)) app.Router.Handle("/game-of-realms", handlerGor(app)) app.Router.Handle("/faucet", handlerFaucet(app)) - app.Router.Handle("/r/demo/boards:gnolang/6", handlerRedirect(app)) + // Redirects + redirects := map[string]string{ + "/r/demo/boards:gnolang/6": "/r/demo/boards:gnolang/3", // XXX: temporary + "/blog": "/r/gnoland/blog", + "/gor": "/r/gnoland/gor", + "/game-of-realms": "/r/gnoland/gor", + "/language": "/r/gnoland/pages:gnolang", + "/gnolang": "/r/gnoland/pages:gnolang", + "/start": "/r/gnoland/pages:start", + "/events": "/r/gnoland/events", + } + for from, to := range redirects { + app.Router.Handle(from, handlerRedirect(app, to)) + } // NOTE: see rePathPart. app.Router.Handle("/r/{rlmname:[a-z][a-z0-9_]*(?:/[a-z][a-z0-9_]*)+}/{filename:(?:.*\\.(?:gno|md|txt)$)?}", handlerRealmFile(app)) app.Router.Handle("/r/{rlmname:[a-z][a-z0-9_]*(?:/[a-z][a-z0-9_]*)+}", handlerRealmMain(app)) @@ -198,12 +211,9 @@ func handlerStatusJSON(app gotuna.App) http.Handler { }) } -// XXX temporary. -func handlerRedirect(app gotuna.App) http.Handler { +func handlerRedirect(app gotuna.App, to string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - http.Redirect(w, r, "/r/boards:gnolang/3", http.StatusFound) - app.NewTemplatingEngine(). - Render(w, r, "home.html", "funcs.html") + http.Redirect(w, r, to, http.StatusFound) }) } diff --git a/gno.land/cmd/gnoweb/main_test.go b/gno.land/cmd/gnoweb/main_test.go index 579e1bcd06b..1cc4d32b3a2 100644 --- a/gno.land/cmd/gnoweb/main_test.go +++ b/gno.land/cmd/gnoweb/main_test.go @@ -13,6 +13,7 @@ import ( func TestRoutes(t *testing.T) { ok := http.StatusOK + found := http.StatusFound routes := []struct { route string status int @@ -32,6 +33,8 @@ func TestRoutes(t *testing.T) { {"/r/demo/deep/very/deep?help", ok, "exposed"}, {"/r/demo/deep/very/deep/", ok, "render.gno"}, {"/r/demo/deep/very/deep/render.gno", ok, "func Render("}, + {"/gor", found, "/r/gnoland/gor"}, + {"/blog", found, "/r/gnoland/blog"}, } if wd, err := os.Getwd(); err == nil { if strings.HasSuffix(wd, "cmd/gnoweb") { @@ -49,7 +52,7 @@ func TestRoutes(t *testing.T) { app.Router.ServeHTTP(response, request) assert.Equal(t, r.status, response.Code) assert.Equal(t, strings.Contains(response.Body.String(), r.substring), true) - println(response.Body.String()) + // println(response.Body.String()) }) } } From f773a71367f22535a2a195f3835babeb213d4d1e Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 17 Oct 2023 23:19:09 +0200 Subject: [PATCH 09/21] chore: refactor static pages to use realms; add aliase, add redirects, add analytics, refactor content Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/p/demo/blog/blog.gno | 39 ++-- examples/gno.land/r/demo/boards/README.md | 149 ------------ examples/gno.land/r/gnoland/home/home.gno | 105 ++++++++- .../gno.land/r/gnoland/home/home_filetest.gno | 139 +++++++---- .../gno.land/r/gnoland/pages/page_about.gno | 12 +- .../r/gnoland/pages/page_ecosystem.gno | 35 +++ .../gno.land/r/gnoland/pages/page_events.gno | 151 ++++++++++++ .../gno.land/r/gnoland/pages/page_gnolang.gno | 43 ++++ .../gno.land/r/gnoland/pages/page_gor.gno | 215 ++++++++++++++++++ .../gno.land/r/gnoland/pages/page_start.gno | 21 ++ .../r/gnoland/pages/page_testnets.gno | 19 ++ .../r/gnoland/pages/page_tokenomics.gno | 11 + examples/gno.land/r/gnoland/pages/pages.gno | 16 +- .../gno.land/r/gnoland/pages/pages_test.gno | 74 +++--- gno.land/cmd/gnoweb/main.go | 173 ++++++++------ gno.land/cmd/gnoweb/main_test.go | 70 +++++- gno.land/cmd/gnoweb/pages/GOR.md | 30 --- gno.land/cmd/gnoweb/views/404.html | 4 +- gno.land/cmd/gnoweb/views/faucet.html | 2 +- gno.land/cmd/gnoweb/views/funcs.html | 52 +++-- gno.land/cmd/gnoweb/views/generic.html | 5 +- gno.land/cmd/gnoweb/views/home.html | 21 -- gno.land/cmd/gnoweb/views/package_dir.html | 13 +- gno.land/cmd/gnoweb/views/package_file.html | 6 +- gno.land/cmd/gnoweb/views/realm_help.html | 24 +- gno.land/cmd/gnoweb/views/realm_render.html | 9 +- gno.land/cmd/gnoweb/views/redirect.html | 16 ++ 27 files changed, 1011 insertions(+), 443 deletions(-) delete mode 100644 examples/gno.land/r/demo/boards/README.md rename gno.land/cmd/gnoweb/pages/ABOUT.md => examples/gno.land/r/gnoland/pages/page_about.gno (73%) create mode 100644 examples/gno.land/r/gnoland/pages/page_ecosystem.gno create mode 100644 examples/gno.land/r/gnoland/pages/page_events.gno create mode 100644 examples/gno.land/r/gnoland/pages/page_gnolang.gno create mode 100644 examples/gno.land/r/gnoland/pages/page_gor.gno create mode 100644 examples/gno.land/r/gnoland/pages/page_start.gno create mode 100644 examples/gno.land/r/gnoland/pages/page_testnets.gno create mode 100644 examples/gno.land/r/gnoland/pages/page_tokenomics.gno delete mode 100644 gno.land/cmd/gnoweb/pages/GOR.md delete mode 100644 gno.land/cmd/gnoweb/views/home.html create mode 100644 gno.land/cmd/gnoweb/views/redirect.html diff --git a/examples/gno.land/p/demo/blog/blog.gno b/examples/gno.land/p/demo/blog/blog.gno index 62103b52885..5f6db1dfa0f 100644 --- a/examples/gno.land/p/demo/blog/blog.gno +++ b/examples/gno.land/p/demo/blog/blog.gno @@ -13,13 +13,16 @@ import ( ) type Blog struct { - Title string - Prefix string // i.e. r/gnoland/blog: - Posts avl.Tree // slug -> Post + Title string + Prefix string // i.e. r/gnoland/blog: + Posts avl.Tree // slug -> Post + NoBreadcrumb bool } func (b Blog) RenderHome(res *mux.ResponseWriter, req *mux.Request) { - res.Write(breadcrumb([]string{b.Title})) + if !b.NoBreadcrumb { + res.Write(breadcrumb([]string{b.Title})) + } if b.Posts.Size() == 0 { res.Write("No posts.") @@ -47,12 +50,14 @@ func (b Blog) RenderPost(res *mux.ResponseWriter, req *mux.Request) { } p := post.(*Post) - breadStr := breadcrumb([]string{ - ufmt.Sprintf("[%s](%s)", b.Title, b.Prefix), - "p", - p.Title, - }) - res.Write(breadStr) + if !b.NoBreadcrumb { + breadStr := breadcrumb([]string{ + ufmt.Sprintf("[%s](%s)", b.Title, b.Prefix), + "p", + p.Title, + }) + res.Write(breadStr) + } // output += ufmt.Sprintf("## [%s](%s)\n", p.Title, p.URL()) res.Write(p.Body + "\n\n") @@ -75,12 +80,14 @@ func (b Blog) RenderTag(res *mux.ResponseWriter, req *mux.Request) { return } - breadStr := breadcrumb([]string{ - ufmt.Sprintf("[%s](%s)", b.Title, b.Prefix), - "t", - slug, - }) - res.Write(breadStr) + if !b.NoBreadcrumb { + breadStr := breadcrumb([]string{ + ufmt.Sprintf("[%s](%s)", b.Title, b.Prefix), + "t", + slug, + }) + res.Write(breadStr) + } nb := 0 b.Posts.Iterate("", "", func(key string, value interface{}) bool { diff --git a/examples/gno.land/r/demo/boards/README.md b/examples/gno.land/r/demo/boards/README.md deleted file mode 100644 index 2729df055b1..00000000000 --- a/examples/gno.land/r/demo/boards/README.md +++ /dev/null @@ -1,149 +0,0 @@ -This is a demo of Gno smart contract programming. This document was -constructed by Gno onto a smart contract hosted on the data Realm -name ["gno.land/r/demo/boards"](https://gno.land/r/demo/boards/) -([github](https://github.com/gnolang/gno/tree/master/examples/gno.land/r/demo/boards)). - - - -## Build `gnokey`, create your account, and interact with Gno. - -NOTE: Where you see `-remote localhost:26657` here, that flag can be replaced -with `-remote test3.gno.land:36657` if you have $GNOT on the testnet. -(To use the testnet, also replace `-chainid dev` with `-chainid testchain` .) - -### Build `gnokey` (and other tools). - -```bash -git clone git@github.com:gnolang/gno.git -cd gno/gno.land -make build -``` - -### Generate a seed/mnemonic code. - -```bash -./build/gnokey generate -``` - -NOTE: You can generate 24 words with any good bip39 generator. - -### Create a new account using your mnemonic. - -```bash -./build/gnokey add -recover KEYNAME -``` - -NOTE: `KEYNAME` is your key identifier, and should be changed. - -### Verify that you can see your account locally. - -```bash -./build/gnokey list -``` - -Take note of your `addr` which looks something like `g17sphqax3kasjptdkmuqvn740u8dhtx4kxl6ljf` . -You will use this as your `ACCOUNT_ADDR`. - -## Interact with the blockchain. - -### Add $GNOT for your account. - -Before starting the `gnoland` node for the first time, your new account can be given $GNOT in the node genesis. -Edit the file `gno.land/genesis/genesis_balances.txt` and add the following line (simlar to the others), using -your `ACCOUNT_ADDR` and `KEYNAME` - -`ACCOUNT_ADDR=10000000000ugnot # @KEYNAME` - -### Alternative: Run a faucet to add $GNOT. - -Instead of editing `gno.land/genesis/genesis_balances.txt`, a more general solution (with more steps) -is to run a local "faucet" and use the web browser to add $GNOT. (This can be done at any time.) -See this page: https://github.com/gnolang/gno/blob/master/gno.land/cmd/gnofaucet/README.md - -### Start the `gnoland` node. - -```bash -./build/gnoland start -``` - -NOTE: The node already has the "boards" realm. - -Leave this running in the terminal. In a new terminal, cd to the same folder `gno/gno.land` . - -### Get your current balance, account number, and sequence number. - -```bash -./build/gnokey query auth/accounts/ACCOUNT_ADDR -remote localhost:26657 -``` - -### Register a board username with a smart contract call. - -The `USERNAME` for posting can different than your `KEYNAME`. It is internally linked to your `ACCOUNT_ADDR`. It must be at least 6 characters, lowercase alphanumeric with underscore. - -```bash -./build/gnokey maketx call -pkgpath "gno.land/r/demo/users" -func "Register" -args "" -args "USERNAME" -args "Profile description" -gas-fee "10000000ugnot" -gas-wanted "2000000" -send "200000000ugnot" -broadcast -chainid dev -remote 127.0.0.1:26657 KEYNAME -``` - -Interactive documentation: https://test3.gno.land/r/demo/users?help&__func=Register - -### Create a board with a smart contract call. - -```bash -./build/gnokey maketx call -pkgpath "gno.land/r/demo/boards" -func "CreateBoard" -args "BOARDNAME" -gas-fee "1000000ugnot" -gas-wanted "10000000" -broadcast -chainid dev -remote localhost:26657 KEYNAME -``` - -Interactive documentation: https://test3.gno.land/r/demo/boards?help&__func=CreateBoard - -Next, query for the permanent board ID by querying (you need this to create a new post): - -```bash -./build/gnokey query "vm/qeval" -data "gno.land/r/demo/boards -GetBoardIDFromName(\"BOARDNAME\")" -remote localhost:26657 -``` - -### Create a post of a board with a smart contract call. - -NOTE: If a board was created successfully, your SEQUENCE_NUMBER would have increased. - -```bash -./build/gnokey maketx call -pkgpath "gno.land/r/demo/boards" -func "CreateThread" -args BOARD_ID -args "Hello gno.land" -args "Text of the post" -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid dev -remote localhost:26657 KEYNAME -``` - -Interactive documentation: https://test3.gno.land/r/demo/boards?help&__func=CreateThread - -### Create a comment to a post. - -```bash -./build/gnokey maketx call -pkgpath "gno.land/r/demo/boards" -func "CreateReply" -args BOARD_ID -args "1" -args "1" -args "Nice to meet you too." -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid dev -remote localhost:26657 KEYNAME -``` - -Interactive documentation: https://test3.gno.land/r/demo/boards?help&__func=CreateReply - -```bash -./build/gnokey query "vm/qrender" -data "gno.land/r/demo/boards -BOARDNAME/1" -remote localhost:26657 -``` - -### Render page with optional path expression. - -The contents of `https://gno.land/r/demo/boards:` and `https://gno.land/r/demo/boards:gnolang` are rendered by calling -the `Render(path string)` function like so: - -```bash -./build/gnokey query "vm/qrender" -data "gno.land/r/demo/boards -gnolang" -``` -## View the board in the browser. - -### Start the web server. - -```bash -./build/gnoweb -``` - -This should print something like `Running on http://127.0.0.1:8888` . Leave this running in the terminal. - -### View in the browser - -In your browser, navigate to the printed address http://127.0.0.1:8888 . -To see you post, click on the package `/r/demo/boards` . diff --git a/examples/gno.land/r/gnoland/home/home.gno b/examples/gno.land/r/gnoland/home/home.gno index 99d01b886c6..2a30fb75d25 100644 --- a/examples/gno.land/r/gnoland/home/home.gno +++ b/examples/gno.land/r/gnoland/home/home.gno @@ -2,7 +2,97 @@ package home import "std" -var body = `# Welcome to **Gno.land** +var body = `# Welcome to Gno.land + +--- + +## An interpretation of the Golang (Go) programming language for advanced developers and intrepid pioneers to build succinct, composable smart contracts for social coordination. + +If you’re concerned about information censorship and want to contribute to the #GnoWorldOrder, follow our socials to find out how. + +Gno.land is in building mode. If you want to help lay the foundations of a fairer and freer world through innovative ideas and exceptional code, join us today. + +
+ +[About Gno.land](/about) +[Explore Github repo](https://github.com/gnolang) + +
+
+ +### Game of Realms + +The first high-stakes contest will see participants compete for tiered membership to co-own the Gno.land blockchain. A series of complex technical and non-technical tasks will challenge contributors to create innovative patterns that push the chain to new limits. Start building the foundation for tomorrow through key smart contracts and other contributions that change our understanding of the world. + +
+ +[Join Game Of Realms](/game-of-realms) + +
+
+ +### Fund and Grants Program + +Are you a builder, tinkerer, or researcher? If you’re looking to create awesome dApps, tooling, infrastructure, or smart contract libraries on Gno.land, you can apply for a grant. The Gno.land Ecosystem Fund and Grants program provides financial contributions for individuals and teams to innovate on the platform. + +
+ +[More information here](https://github.com/gnolang/ecosystem-fund-grants) + +
+ +
+
+ +### Learn about Gno.land + +- [About](/about) +- [Subscribe](#subscribe) +- [Tokenomics (soon)](#) +- [Blog](/blog) +- [Events](/events) +- [Partners (soon)](#) + +
+ +
+ +### Build with Gnolang + +- [Gno dev with CLI (soon)](#) +- [Explore the Universe](/ecosystem) +- [Test in the browser (soon)](#) +- [About the Gnolang Language](/gnolang) +- [Docs/ Tutorials](https://github.com/gnolang) +- [Gno by example](https://gno-by-example.com/) +- [Getting started video (soon)](#) + +
+
+ +### Explore the universe + +- [Discover demo packages](https://github.com/gnolang/gno/tree/master/examples) +- [Install Gno Key instructions](/r/demo/boards:testboard/5) +- [Testnets 3](https://test3.gno.land/) +- [Testnets 2](https://test2.gno.land/) +- [Explorer links(soon)](#) +- [Testnet Tokens (faucet)](https://test3.gno.land/faucet) + +
+
+ +--- + +### Socials + +- ![Discord](static/img/ico-discord.svg) [Discord](https://discord.gg/S8nKUqwkPn) +- ![Twitter](static/img/ico-twitter.svg) [Twitter](https://twitter.com/_gnoland) +- ![Youtube](static/img/ico-youtube.svg) [Youtube](https://www.youtube.com/@_gnoland) +- ![Telegram](static/img/ico-telegram.svg) [Telegram](https://t.me/gnoland) +` + +var body2 = `# Welcome to **Gno.land** - [About Gno.land](/r/gnoland/pages:about) - [Blogs](/r/gnoland/blog) @@ -85,5 +175,18 @@ func Render(_ string) string { // XXX: // XXX: community curated picks // XXX: + body += randomBanner() return body } + +func randomBanner() string { + // not sure to keep this... + banners := []string{ + "Gno is for Truth.", + "Gno is for Social Coordination.", + "Gno is _not only_ for DeFi.", + } + height := std.GetHeight() + idx := int(height) % len(banners) + return banners[idx] +} diff --git a/examples/gno.land/r/gnoland/home/home_filetest.gno b/examples/gno.land/r/gnoland/home/home_filetest.gno index 56dccef2dbb..a38a41eb437 100644 --- a/examples/gno.land/r/gnoland/home/home_filetest.gno +++ b/examples/gno.land/r/gnoland/home/home_filetest.gno @@ -7,53 +7,92 @@ func main() { } // Output: -// # Welcome to **Gno.land** -// -// - [About Gno.land](/r/gnoland/pages:about) -// - [Blogs](/r/gnoland/blog) -// - [Install `gnokey`](https://github.com/gnolang/gno/tree/master/gno.land/cmd/gnokey) -// - [Acquire testnet tokens](/faucet) -// - [Game of Realms](/game-of-realms) - An open worldwide competition for developers to build the best Gnolang smart-contracts. -// -// # Explore new packages. -// -// - r/gnoland -// - [/r/gnoland/blog](/r/gnoland/blog) -// - [/r/gnoland/faucet](/r/gnoland/faucet) -// - r/system -// - [/r/system/names](/r/system/names) -// - [/r/system/rewards](/r/system/rewards) -// - [/r/system/validators](/r/system/validators) -// - r/demo -// - [/r/demo/banktest](/r/demo/banktest) -// - [/r/demo/boards](/r/demo/boards) -// - [/r/demo/foo20](/r/demo/foo20) -// - [/r/demo/nft](/r/demo/nft) -// - [/r/demo/types](/r/demo/types) -// - [/r/demo/users](/r/demo/users) -// - [/r/demo/groups](/r/demo/groups) -// - p/demo -// - [/p/demo/avl](/p/demo/avl) -// - [/p/demo/blog](/p/demo/blog) -// - [/p/demo/flow](/p/demo/flow) -// - [/p/demo/gnode](/p/demo/gnode) -// - [/p/demo/grc/exts](/p/demo/grc/exts) -// - [/p/demo/grc/grc20](/p/demo/grc/grc20) -// - [/p/demo/grc/grc721](/p/demo/grc/grc721) -// -// # Other Testnets -// -// - **[staging.gno.land](https://staging.gno.land) (wiped every commit to master)** -// - _[test3.gno.land](https://test3.gno.land) (latest)_ -// - _[test2.gno.land](https://test2.gno.land) (archive)_ -// - _[test1.gno.land](https://test1.gno.land) (archive)_ -// -// **This is a testnet.** -// Package names are not guaranteed to be available for production. -// -// # Social -// -// Check out our [community projects](https://github.com/gnolang/awesome-gno). -// -// Official channel: [Discord](https://discord.gg/S8nKUqwkPn)
-// Other channels: [Telegram](https://t.me/gnoland) [Twitter](https://twitter.com/_gnoland) [Youtube](https://www.youtube.com/@_gnoland) +// # Welcome to Gno.land +// +// --- +// +// ## An interpretation of the Golang (Go) programming language for advanced developers and intrepid pioneers to build succinct, composable smart contracts for social coordination. +// +// If you’re concerned about information censorship and want to contribute to the #GnoWorldOrder, follow our socials to find out how. +// +// Gno.land is in building mode. If you want to help lay the foundations of a fairer and freer world through innovative ideas and exceptional code, join us today. +// +//
+// +// [About Gno.land](/about) +// [Explore Github repo](https://github.com/gnolang) +// +//
+//
+// +// ### Game of Realms +// +// The first high-stakes contest will see participants compete for tiered membership to co-own the Gno.land blockchain. A series of complex technical and non-technical tasks will challenge contributors to create innovative patterns that push the chain to new limits. Start building the foundation for tomorrow through key smart contracts and other contributions that change our understanding of the world. +// +//
+// +// [Join Game Of Realms](/game-of-realms) +// +//
+//
+// +// ### Fund and Grants Program +// +// Are you a builder, tinkerer, or researcher? If you’re looking to create awesome dApps, tooling, infrastructure, or smart contract libraries on Gno.land, you can apply for a grant. The Gno.land Ecosystem Fund and Grants program provides financial contributions for individuals and teams to innovate on the platform. +// +//
+// +// [More information here](https://github.com/gnolang/ecosystem-fund-grants) +// +//
+// +//
+//
+// +// ### Learn about Gno.land +// +// - [About](/about) +// - [Subscribe](#subscribe) +// - [Tokenomics (soon)](#) +// - [Blog](/blog) +// - [Events](/events) +// - [Partners (soon)](#) +// +//
+// +//
+// +// ### Build with Gnolang +// +// - [Gno dev with CLI (soon)](#) +// - [Explore the Universe](/ecosystem) +// - [Test in the browser (soon)](#) +// - [About the Gnolang Language](/gnolang) +// - [Docs/ Tutorials](https://github.com/gnolang) +// - [Gno by example](https://gno-by-example.com/) +// - [Getting started video (soon)](#) +// +//
+//
+// +// ### Explore the universe +// +// - [Discover demo packages](https://github.com/gnolang/gno/tree/master/examples) +// - [Install Gno Key instructions](/r/demo/boards:testboard/5) +// - [Testnets 3](https://test3.gno.land/) +// - [Testnets 2](https://test2.gno.land/) +// - [Explorer links(soon)](#) +// - [Testnet Tokens (faucet)](https://test3.gno.land/faucet) +// +//
+//
+// +// --- +// +// ### Socials +// +// - ![Discord](static/img/ico-discord.svg) [Discord](https://discord.gg/S8nKUqwkPn) +// - ![Twitter](static/img/ico-twitter.svg) [Twitter](https://twitter.com/_gnoland) +// - ![Youtube](static/img/ico-youtube.svg) [Youtube](https://www.youtube.com/@_gnoland) +// - ![Telegram](static/img/ico-telegram.svg) [Telegram](https://t.me/gnoland) +// Gno is for Truth. diff --git a/gno.land/cmd/gnoweb/pages/ABOUT.md b/examples/gno.land/r/gnoland/pages/page_about.gno similarity index 73% rename from gno.land/cmd/gnoweb/pages/ABOUT.md rename to examples/gno.land/r/gnoland/pages/page_about.gno index a5678a7349a..9aba4e39f76 100644 --- a/gno.land/cmd/gnoweb/pages/ABOUT.md +++ b/examples/gno.land/r/gnoland/pages/page_about.gno @@ -1,4 +1,10 @@ -# About Gno.land +package gnopages + +func init() { + path := "about" + title := "Gno.land Is A Platform To Write Smart Contracts In Gnolang (Gno)" + // XXX: description := "On Gno.land, developers write smart contracts and other blockchain apps using Gnolang (Gno) without learning a language that’s exclusive to a single ecosystem." + body := `# About Gno.land Gno.land is a platform to write smart contracts in Gnolang (Gno). Using an interpreted version of the general-purpose programming language Golang (Go), developers can write smart contracts and other blockchain apps without having to learn a language that’s exclusive to a single ecosystem. @@ -9,4 +15,6 @@ Proof of Contribution rewards contributors from technical and non-technical back This consensus mechanism also achieves higher security with fewer validators, optimizing resources for a greener, more sustainable, and enduring blockchain ecosystem. Any blockchain using Gnolang achieves succinctness, composability, expressivity, and completeness not found in any other smart contract platform. -By observing a minimal structure, the design can endure over time and challenge the regime of information censorship we’re living in today. +By observing a minimal structure, the design can endure over time and challenge the regime of information censorship we’re living in today.` + _ = b.NewPost("", path, title, body, nil) +} diff --git a/examples/gno.land/r/gnoland/pages/page_ecosystem.gno b/examples/gno.land/r/gnoland/pages/page_ecosystem.gno new file mode 100644 index 00000000000..68969c44529 --- /dev/null +++ b/examples/gno.land/r/gnoland/pages/page_ecosystem.gno @@ -0,0 +1,35 @@ +package gnopages + +func init() { + var ( + path = "ecosystem" + title = "Discover Gno.land Ecosystem Projects & Initiatives" + // XXX: description = "Dive further into the Gno.land ecosystem and discover the core infrastructure, projects, smart contracts, and tooling we’re building." + body = `# Gno Ecosystem + +## Gno.land Space + +For the best onboarding experience, head over to [Gno.land Space](https://www.gnoland.space/) open ecosystem. Here you can set up your Gno wallet, explore existing community-written Gno smart contracts (realms), and become part of our vibrant community by joining [Gno.land Discord](https://discord.com/invite/x76qK4ttHC). + +## Gno Studio (IDE) + +Gno IDE is a web-based application helping builders quickly spin up Gno realms and packages right on their browsers. Offering a smooth and intuitive UX for building on Gno, you’ll find multiple modes for customizability with all the features you’d expect from an IDE, such as auto compilation in the editor, debugging, and extensive testing capability. + +## Gnoscan + +Developed by the Onbloc team, Gnoscan is Gno.land’s blockchain explorer. Anyone can use Gnoscan to easily find information that resides on the Gno.land blockchain, such as wallet addresses, TX hashes, blocks, and contracts. Gnoscan makes our on-chain data easy to read and intuitive to discover. [Go to Gnoscan.](https://gnoscan.io/) + +## Adena + +Adena is a user-friendly non-custodial wallet for Gno.land. Open-source and developed by Onbloc, Adena currently powers all transactions on Gno.land, allowing gnomes to interact easily with the chain. With an emphasis on UX, Adena is built to handle millions of realms and tokens with a high-quality interface, support for NFTs and custom tokens, and seamless integration. [Get started here.](https://adena.app/) + +## Gnoswap + +Gnoswap is currently under development and led by the Onbloc team. Gnoswap will be the first DEX on Gno.land and is an automated market maker (AMM) protocol written in Gnolang that allows for permissionless token exchanges on the platform. + +## Gno.land Developer Portal + +Through the Gno.land Developer Portal, new developers can explore the exciting world of Gnolang (Gno), a novel programming language that powers the Gno.land blockchain. If you want to interact with Gno.land, start writing a realm, build a dApp, or even port a Solidity contract to a Gnolang realm, you’ll find the resources to [get started here](https://docs.onbloc.xyz/).` + ) + _ = b.NewPost("", path, title, body, nil) +} diff --git a/examples/gno.land/r/gnoland/pages/page_events.gno b/examples/gno.land/r/gnoland/pages/page_events.gno new file mode 100644 index 00000000000..18e7faeb3d3 --- /dev/null +++ b/examples/gno.land/r/gnoland/pages/page_events.gno @@ -0,0 +1,151 @@ +package gnopages + +func init() { + var ( + path = "events" + title = "Gno.land Core Team Attends Industry Events & Meetups" + // XXX: description = "If you’re interested in learning more about Gno.land, you can join us at major blockchain industry events throughout the year either in person or virtually." + body = `# Events + +If you’re interested in building web3 with us, catch up with Gno.land in person at one of our industry events. We’re looking to connect with developers and like-minded thinkers who can contribute to the growth of our platform. + +--- + +## Upcoming Events + +
+
+ +### EthCC + +- **Come Meet Us at our Booth** +- Paris, July 17 - 20, 2023 +- Manfred Touron + +[Learn more](https://www.ethcc.io/) + +
+
+ +### Nebular Summit Gno.land for Developers + +- Paris, July 24 - 25, 2023 +- Manfred Touron + +[Learn more](https://www.nebular.builders/) + +
+
+ +### GopherCon EU + +- **Come Meet Us at our Booth** +- Berlin, July 26 - 29, 2023 + +[Learn more](https://gophercon.eu/) + +
+ +
+ +### GopherCon US + +- **Come Meet Us at our Booth** +- San Diego, September 26 - 29, 2023 + +[Learn more](https://www.gophercon.com/) + +
+
+ +--- + +## Past Events + +
+ +
+ +### Eth Seoul + +- **The Evolution of Smart Contracts: A Journey into Gno.land** +- Seoul, June 3, 2023 +- Manfred Touron + +[Learn more](https://2023.ethseoul.org/) + +
+
+ +### BUIDL Asia + +- **Proof of Contribution in Gno.land** +- Seoul, June 6, 2023 +- Manfred Touron + +[Learn more](https://www.buidl.asia/) + +
+
+ +### Game Developer Conference + +- **Side Event: Web3 Gaming Apps Powered by Gno** +- San Francisco, Mach 23, 2023 +- Jae Kwon + +[Watch the talk](https://www.youtube.com/watch?v=IJ0xel8lr4c) + +
+
+ +### EthDenver + +- **Side Event: Discover Gno.land** +- Denver, Feb 24 - Mar 5, 2023 +- Jae Kwon + +[Watch the talk](https://www.youtube.com/watch?v=IJ0xel8lr4c) + +
+
+ +### Istanbul Blockchain Week + +- Istanbul, Nov 14 - 17, 2022 +- Manfred Touron + +[Watch the talk](https://www.youtube.com/watch?v=JX0gdWT0Cg4) + +
+
+ +### Web Summit Buckle Up and Build with Cosmos + +- Lisbon, Nov 1 - 4, 2022 +- Manfred Touron + +
+
+ +### Cosmoverse + +- Medallin, Sept 26 - 28, 2022 +- Manfred Touron + +[Watch the talk](https://www.youtube.com/watch?v=6s1zG7hgxMk) + +
+
+ +### Berlin Blockchain Week Buckle Up and Build with Cosmos + +- Berlin, Sept 11 - 18, 2022 + +[Watch the talk](https://www.youtube.com/watch?v=hCLErPgnavI) + +
+
` + ) + _ = b.NewPost("", path, title, body, nil) +} diff --git a/examples/gno.land/r/gnoland/pages/page_gnolang.gno b/examples/gno.land/r/gnoland/pages/page_gnolang.gno new file mode 100644 index 00000000000..f0c2bfe276d --- /dev/null +++ b/examples/gno.land/r/gnoland/pages/page_gnolang.gno @@ -0,0 +1,43 @@ +package gnopages + +func init() { + var ( + path = "gnolang" + title = "Gnolang (Gno) Is a Complete Language for Blockchain" + // XXX: description = "Gnolang (Gno) is an interpretation of the popular Golang (Go) language for blockchain created by Tendermint and Cosmos founder Jae Kwon." + body = `# About the Gnolang, the Gno Language + +[Gnolang](https://github.com/gnolang/gno/blob/master/LICENSE.md) (Gno) is an interpretation of the widely-used Golang (Go) programming language for blockchain created by Cosmos co-founder Jae Kwon in 2022 to mark a new era in smart contracting. Gno is ~99% identical to Go, so Go programmers can start coding in Gno right away, with a minimal learning curve. For example, Gno comes with blockchain-specific standard libraries, but any code that doesn’t use blockchain-specific logic can run in Go with minimal processing. Libraries that don’t make sense in the blockchain context, such as network or operating-system access, are not available in Gno. Otherwise, Gno loads and uses many standard libraries that power Go, so most of the parsing of the source code is the same. + +Under the hood, the Gno code is parsed into an abstract syntax tree (AST) and the AST itself is used in the interpreter, rather than bytecode as in many virtual machines such as Java, Python, or Wasm. This makes even the GnoVM accessible to any Go programmer. The novel design of the intuitive GnoVM interpreter allows Gno to freeze and resume the program by persisting and loading the entire memory state. Gno is deterministic, auto-persisted, and auto-Merkle-ized, allowing (smart contract) programs to be succinct, as the programmer doesn’t have to serialize and deserialize objects to persist them into a database (unlike programming applications with the Cosmos SDK). + +## How Gno Differs from Go + +![Gno and Go differences](static/img/gno-language/go-and-gno.jpg) + +The composable nature of Go/Gno allows for type-checked interactions between contracts, making Gno.land safer and more powerful, as well as operationally cheaper and faster. Smart contracts on Gno.land are light, simple, more focused, and easily interoperable—a network of interconnected contracts rather than siloed monoliths that limit interactions with other contracts. + +![Example of Gno code](static/img/gno-language/code-example.jpg) + +## Gno Inherits Go’s Built-in Security Features + +Go supports secure programming through exported/non-exported fields, enabling a “least-authority” design. It is easy to create objects and APIs that expose only what should be accessible to callers while hiding what should not be simply by the capitalization of letters, thus allowing a succinct representation of secure logic that can be called by multiple users. + +Another major advantage of Go is that the language comes with an ecosystem of great tooling, like the compiler and third-party tools that statically analyze code. Gno inherits these advantages from Go directly to create a smart contract programming language that provides embedding, composability, type-check safety, and garbage collection, helping developers to write secure code relying on the compiler, parser, and interpreter to give warning alerts for common mistakes. + +## Gno vs Solidity + +The most widely-adopted smart contract language today is Ethereum’s EVM-compatible Solidity. With bytecode built from the ground up and Turing complete, Solidity opened up a world of possibilities for decentralized applications (dApps) and there are currently more than 10 million contracts deployed on Ethereum. However, Solidity provides limited tooling and its EVM has a stack limit and computational inefficiencies. + +Solidity is designed for one purpose only (writing smart contracts) and is bound by the limitations of the EVM. In addition, developers have to learn several languages if they want to understand the whole stack or work across different ecosystems. Gno aspires to exceed Solidity on multiple fronts (and other smart contract languages like CosmWasm or Substrate) as every part of the stack is written in Gno. It’s easy for developers to understand the entire system just by studying a relatively small code base. + +## Gno Is Essential for the Wider Adoption of Web3 + +Gno makes imports as easy as they are in web2 with runtime-based imports for seamless dependency flow comprehension, and support for complex structs, beyond primitive types. Gno is ultimately cost-effective as dependencies are loaded once, enabling remote function calls as local, and providing automatic and independent per-realm state persistence. + +Using Gno, developers can rapidly accelerate application development and adopt a modular structure by reusing and reassembling existing modules without building from scratch. They can embed one structure inside another in an intuitive way while preserving localism, and the language specification is simple, successfully balancing practicality and minimalism. + +The Go language is so well designed that the Gno smart contract system will become the new gold standard for smart contract development and other blockchain applications. As a programming language that is universally adopted, secure, composable, and complete, Gno is essential for the broader adoption of web3 and its sustainable growth.` + ) + _ = b.NewPost("", path, title, body, nil) +} diff --git a/examples/gno.land/r/gnoland/pages/page_gor.gno b/examples/gno.land/r/gnoland/pages/page_gor.gno new file mode 100644 index 00000000000..6c9e46b4062 --- /dev/null +++ b/examples/gno.land/r/gnoland/pages/page_gor.gno @@ -0,0 +1,215 @@ +package gnopages + +func init() { + var ( + path = "gor" + title = "Game of Realms Content For The Best Contributors" + // XXX: description = "Game of Realms is the first high-stakes competition held in two phases to find the best contributors to the Gno.land platform with a 133,700 ATOM prize pool." + body = `# Game of Realms + +The worldwide competition to find the best contributors to Gno.land is currently in phase one – for advanced developers only. + +Once the necessary tools to start phase two are ready, we’ll open up the competition to newer devs and non-technical contributors. + +If you want to stack ATOM rewards and play a key role in the success of Gno.land and web3, read more about Game of Realms or open a [PR](https://github.com/gnolang/gno/) today. + +
+ +
+
+
+ +## Phase I. (ongoing) + +- + +- + +- + +
+
+ +## Phase II. (Locked) + +
+
+
+ +
+ +
+ +## Evaluation DAO + +This complex challenge seeks your skills in DAO development and implementation and is one of the most important challenges of phase one. The Evaluation DAO will ensure that contributions in Game of Realms and the Gno.land platform are fairly rewarded. + +
+ + + + + + + +
+ +Game of Realms participants and core contributors are still in discussions, proposing additional ideas, and seeing how the proposal for the Evaluation DAO evolves over time. + +
+ + + +
+ +See [GitHub issue 519](https://github.com/gnolang/gno/issues/519) for the most up-to-date discussion so far on how voting should work for the DAO, what the responsibilities are, how to join, etc. + +
+ + + + + + + + + + + + + + + + + +
+
+ +
+ +## Tutorials + +To progress to phase two of the competition, we need high-quality tutorials, guides, and documentation from phase one participants. Help to create materials that will onboard more contributors to Gno.land. + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +## Governance Module + +Can you define and implement a governance contract suite that rivals existing ones, such as the Cosmos Hub? Show us how! We’re looking for the fairest and most efficient governance solution possible. + +
+ + + + + + + +
+ +Game of Realms participants and core contributors have made significant progress teaming up to complete this challenge but discussions and additional ideas are still ongoing. + +
+ + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +## Register Now + + +
+
+ +
+
+ + +
+ +
+ + +
+ + +
+
+
+ +` + ) + _ = b.NewPost("", path, title, body, nil) +} diff --git a/examples/gno.land/r/gnoland/pages/page_start.gno b/examples/gno.land/r/gnoland/pages/page_start.gno new file mode 100644 index 00000000000..a36ec6e52b1 --- /dev/null +++ b/examples/gno.land/r/gnoland/pages/page_start.gno @@ -0,0 +1,21 @@ +package gnopages + +func init() { + path := "start" + title := "Getting Started with Gno" + // XXX: description := "" + + // TODO: codegen to use README files here + + /* TODO: port previous message: This is a demo of Gno smart contract programming. This document was + constructed by Gno onto a smart contract hosted on the data Realm + name ["gno.land/r/demo/boards"](https://gno.land/r/demo/boards/) + ([github](https://github.com/gnolang/gno/tree/master/examples/gno.land/r/demo/boards)). + */ + body := `## Getting Started with Gno + +- [Install Gno Key](/r/demo/boards:testboard/5) +- TODO: add more links +` + _ = b.NewPost("", path, title, body, nil) +} diff --git a/examples/gno.land/r/gnoland/pages/page_testnets.gno b/examples/gno.land/r/gnoland/pages/page_testnets.gno new file mode 100644 index 00000000000..b6c09ab71ee --- /dev/null +++ b/examples/gno.land/r/gnoland/pages/page_testnets.gno @@ -0,0 +1,19 @@ +package gnopages + +func init() { + path := "testnets" + title := "Gno.land Testnets" + // XXX: description := """ + body := `## Other testnets + +- **[staging.gno.land](https://staging.gno.land) (wiped every commit to master)** +- _[test3.gno.land](https://test3.gno.land) (latest)_ +- _[test2.gno.land](https://test2.gno.land) (archive)_ +- _[test1.gno.land](https://test1.gno.land) (archive)_ + +## Local devnet + +See CONTRIBUTING.md on GitHub. +` + _ = b.NewPost("", path, title, body, nil) +} diff --git a/examples/gno.land/r/gnoland/pages/page_tokenomics.gno b/examples/gno.land/r/gnoland/pages/page_tokenomics.gno new file mode 100644 index 00000000000..de899ae0a70 --- /dev/null +++ b/examples/gno.land/r/gnoland/pages/page_tokenomics.gno @@ -0,0 +1,11 @@ +package gnopages + +func init() { + var ( + path = "tokenomics" + title = "Gno.land Tokenomics" + // XXX: description = """ + body = `Lorem Ipsum` + ) + _ = b.NewPost("", path, title, body, nil) +} diff --git a/examples/gno.land/r/gnoland/pages/pages.gno b/examples/gno.land/r/gnoland/pages/pages.gno index 9ad5a212c95..6e1f117d1d5 100644 --- a/examples/gno.land/r/gnoland/pages/pages.gno +++ b/examples/gno.land/r/gnoland/pages/pages.gno @@ -4,18 +4,12 @@ import ( "gno.land/p/demo/blog" ) -var b = &blog.Blog{ - Title: "Gnoland's Pages", - Prefix: "/r/gnoland/pages:", -} +// TODO: switch from p/blog to p/pages -func init() { - _ = b.NewPost("", "game-of-realms", "Game of Realms", "Lorem Ipsum", nil) - _ = b.NewPost("", "events", "Events", "Lorem Ipsum", nil) - _ = b.NewPost("", "tokenomics", "Tokenomics", "Lorem Ipsum", nil) - _ = b.NewPost("", "start", "Getting Started", "Lorem Ipsum", nil) - _ = b.NewPost("", "about", "About Page", "Lorem Ipsum", nil) - _ = b.NewPost("", "language", "About Gnolang, the Gno Language", "Lorem Ipsum", nil) +var b = &blog.Blog{ + Title: "Gnoland's Pages", + Prefix: "/r/gnoland/pages:", + NoBreadcrumb: true, } func Render(path string) string { diff --git a/examples/gno.land/r/gnoland/pages/pages_test.gno b/examples/gno.land/r/gnoland/pages/pages_test.gno index 1a43153e2c8..1389e5b5463 100644 --- a/examples/gno.land/r/gnoland/pages/pages_test.gno +++ b/examples/gno.land/r/gnoland/pages/pages_test.gno @@ -6,48 +6,42 @@ import ( "testing" ) -func TestPackage(t *testing.T) { - std.TestSetOrigCaller(std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq")) - - author := std.GetOrigCaller() - - // by default, lorem ipsum posts - { - got := Render("") - expected := ` -# Gnoland's Pages - -
- -## [Events](/r/gnoland/pages:p/events) -**[Learn More](/r/gnoland/pages:p/events)** - -
- -## [Game of Realms](/r/gnoland/pages:p/gor) -**[Learn More](/r/gnoland/pages:p/gor)** - -
- -## [Getting Started](/r/gnoland/pages:p/start) -**[Learn More](/r/gnoland/pages:p/start)** - -
- -## [Tokenomics](/r/gnoland/pages:p/tokenomics) -**[Learn More](/r/gnoland/pages:p/tokenomics)** - -
-` - assertMDEquals(t, got, expected) +func TestHome(t *testing.T) { + printedOnce := false + got := Render("") + expectedSubtrings := []string{ + "/r/gnoland/pages:p/events", + "/r/gnoland/pages:p/tokenomics", + "/r/gnoland/pages:p/start", + "/r/gnoland/pages:p/gor", + "/r/gnoland/pages:p/about", + "/r/gnoland/pages:p/language", + } + for _, substring := range expectedSubtrings { + if !strings.Contains(got, substring) { + if !printedOnce { + println(got) + printedOnce = true + } + t.Errorf("expected %q, but not found.", substring) + } } } -func assertMDEquals(t *testing.T, got, expected string) { - t.Helper() - expected = strings.TrimSpace(expected) - got = strings.TrimSpace(got) - if expected != got { - t.Errorf("invalid render output.\nexpected %q.\ngot %q.", expected, got) +func TestAbout(t *testing.T) { + printedOnce := false + got := Render("p/about") + expectedSubtrings := []string{ + "# About Gno.land", + "Gno.land is a platform to write smart contracts in Gnolang (Gno).", + } + for _, substring := range expectedSubtrings { + if !strings.Contains(got, substring) { + if !printedOnce { + println(got) + printedOnce = true + } + t.Errorf("expected %q, but not found.", substring) + } } } diff --git a/gno.land/cmd/gnoweb/main.go b/gno.land/cmd/gnoweb/main.go index f2a8ca3fb78..3b9f6f5fec3 100644 --- a/gno.land/cmd/gnoweb/main.go +++ b/gno.land/cmd/gnoweb/main.go @@ -18,7 +18,6 @@ import ( "github.com/gnolang/gno/tm2/pkg/amino" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" - osm "github.com/gnolang/gno/tm2/pkg/os" "github.com/gnolang/gno/tm2/pkg/std" "github.com/gorilla/mux" "github.com/gotuna/gotuna" @@ -32,72 +31,91 @@ const ( qFileStr = "vm/qfile" ) +var startedAt time.Time + var flags struct { - bindAddr string - remoteAddr string - captchaSite string - faucetURL string - viewsDir string - pagesDir string - helpChainID string - helpRemote string + BindAddr string + RemoteAddr string + CaptchaSite string + FaucetURL string + ViewsDir string + HelpChainID string + HelpRemote string + WithAnalytics bool } -var startedAt time.Time - func init() { - flag.StringVar(&flags.remoteAddr, "remote", "127.0.0.1:26657", "remote gnoland node address") - flag.StringVar(&flags.bindAddr, "bind", "127.0.0.1:8888", "server listening address") - flag.StringVar(&flags.captchaSite, "captcha-site", "", "recaptcha site key (if empty, captcha are disabled)") - flag.StringVar(&flags.faucetURL, "faucet-url", "http://localhost:5050", "faucet server URL") - flag.StringVar(&flags.viewsDir, "views-dir", "./cmd/gnoweb/views", "views directory location") - flag.StringVar(&flags.pagesDir, "pages-dir", "./cmd/gnoweb/pages", "pages directory location") - flag.StringVar(&flags.helpChainID, "help-chainid", "dev", "help page's chainid") - flag.StringVar(&flags.helpRemote, "help-remote", "127.0.0.1:26657", "help page's remote addr") + flag.StringVar(&flags.RemoteAddr, "remote", "127.0.0.1:26657", "remote gnoland node address") + flag.StringVar(&flags.BindAddr, "bind", "127.0.0.1:8888", "server listening address") + flag.StringVar(&flags.CaptchaSite, "captcha-site", "", "recaptcha site key (if empty, captcha are disabled)") + flag.StringVar(&flags.FaucetURL, "faucet-url", "http://localhost:5050", "faucet server URL") + flag.StringVar(&flags.ViewsDir, "views-dir", "./cmd/gnoweb/views", "views directory location") // XXX: replace with goembed + flag.StringVar(&flags.HelpChainID, "help-chainid", "dev", "help page's chainid") + flag.StringVar(&flags.HelpRemote, "help-remote", "127.0.0.1:26657", "help page's remote addr") + flag.BoolVar(&flags.WithAnalytics, "with-analytics", false, "enable privacy-first analytics") startedAt = time.Now() } func makeApp() gotuna.App { app := gotuna.App{ - ViewFiles: os.DirFS(flags.viewsDir), + ViewFiles: os.DirFS(flags.ViewsDir), Router: gotuna.NewMuxRouter(), Static: static.EmbeddedStatic, // StaticPrefix: "static/", } - app.Router.Handle("/", handlerHome(app)) - app.Router.Handle("/about", handlerAbout(app)) - app.Router.Handle("/game-of-realms", handlerGor(app)) - app.Router.Handle("/faucet", handlerFaucet(app)) - // Redirects + + // realm aliases + aliases := map[string]string{ + "/": "/r/gnoland/home", + "/about": "/r/gnoland/pages:p/about", + "/gnolang": "/r/gnoland/pages:p/gnolang", + "/ecosystem": "/r/gnoland/pages:p/ecosystem", + "/testnets": "/r/gnoland/pages:p/testnets", + "/start": "/r/gnoland/pages:p/start", + "/game-of-realms": "/r/gnoland/pages:p/gor", // XXX: replace with gor realm + "/events": "/r/gnoland/pages:p/events", // XXX: replace with events realm + } + for from, to := range aliases { + app.Router.Handle(from, handlerRealmAlias(app, to)) + } + // http redirects redirects := map[string]string{ "/r/demo/boards:gnolang/6": "/r/demo/boards:gnolang/3", // XXX: temporary "/blog": "/r/gnoland/blog", - "/gor": "/r/gnoland/gor", - "/game-of-realms": "/r/gnoland/gor", - "/language": "/r/gnoland/pages:gnolang", - "/gnolang": "/r/gnoland/pages:gnolang", - "/start": "/r/gnoland/pages:start", - "/events": "/r/gnoland/events", + "/gor": "/game-of-realms", + "/language": "/gnolang", + "/getting-started": "/start", } for from, to := range redirects { app.Router.Handle(from, handlerRedirect(app, to)) } + // realm routes // NOTE: see rePathPart. app.Router.Handle("/r/{rlmname:[a-z][a-z0-9_]*(?:/[a-z][a-z0-9_]*)+}/{filename:(?:.*\\.(?:gno|md|txt)$)?}", handlerRealmFile(app)) app.Router.Handle("/r/{rlmname:[a-z][a-z0-9_]*(?:/[a-z][a-z0-9_]*)+}", handlerRealmMain(app)) app.Router.Handle("/r/{rlmname:[a-z][a-z0-9_]*(?:/[a-z][a-z0-9_]*)+}:{querystr:.*}", handlerRealmRender(app)) app.Router.Handle("/p/{filepath:.*}", handlerPackageFile(app)) + + // other + app.Router.Handle("/faucet", handlerFaucet(app)) app.Router.Handle("/static/{path:.+}", handlerStaticFile(app)) app.Router.Handle("/favicon.ico", handlerFavicon(app)) + + // api app.Router.Handle("/status.json", handlerStatusJSON(app)) + + app.Router.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + path := r.RequestURI + handleNotFound(app, path, w, r) + }) return app } func main() { flag.Parse() - fmt.Printf("Running on http://%s\n", flags.bindAddr) + fmt.Printf("Running on http://%s\n", flags.BindAddr) server := &http.Server{ - Addr: flags.bindAddr, + Addr: flags.BindAddr, ReadHeaderTimeout: 60 * time.Second, Handler: makeApp().Router, } @@ -107,56 +125,59 @@ func main() { } } -func handlerHome(app gotuna.App) http.Handler { +// handlerRealmAlias is used to render official pages from realms. +// url is intended to be shorter. +// UX is intended to be more minimalistic. +// A link to the realm realm is added. +func handlerRealmAlias(app gotuna.App, rlmpath string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - rlmpath := "gno.land/r/gnoland/home" - querystr := "?from-home" + rlmfullpath := "gno.land" + rlmpath + querystr := "" // XXX: "?gnoweb-alias=1" + parts := strings.Split(rlmpath, ":") + switch len(parts) { + case 1: // continue + case 2: // r/realm:querystr + rlmfullpath = "gno.land" + parts[0] + querystr = parts[1] + querystr + default: + panic("should not happen") + } + rlmname := strings.TrimPrefix(rlmfullpath, "gno.land/r/") qpath := "vm/qrender" - data := []byte(fmt.Sprintf("%s\n%s", rlmpath, querystr)) + data := []byte(fmt.Sprintf("%s\n%s", rlmfullpath, querystr)) res, err := makeRequest(qpath, data) if err != nil { writeError(w, fmt.Errorf("gnoweb failed to query gnoland: %w", err)) return } - tmpl := app.NewTemplatingEngine() - tmpl.Set("HomeContent", string(res.Data)) - tmpl.Set("Title", "Gno.land Smart Contract Platform Using Gnolang (Gno)") - tmpl.Set("Description", "Gno.land is the only smart contract platform using the Gnolang (Gno) programming language, an interpretation of the widely-used Golang (Go).") - tmpl.Render(w, r, "home.html", "funcs.html") - }) -} - -func handlerAbout(app gotuna.App) http.Handler { - md := filepath.Join(flags.pagesDir, "ABOUT.md") - mainContent := osm.MustReadFile(md) - - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - app.NewTemplatingEngine(). - Set("Title", "Gno.land Is A Platform To Write Smart Contracts In Gnolang (Gno)"). - Set("Description", "On Gno.land, developers write smart contracts and other blockchain apps using Gnolang (Gno) without learning a language that’s exclusive to a single ecosystem."). - Set("MainContent", string(mainContent)). - Render(w, r, "generic.html", "funcs.html") - }) -} -func handlerGor(app gotuna.App) http.Handler { - md := filepath.Join(flags.pagesDir, "GOR.md") - mainContent := osm.MustReadFile(md) + queryParts := strings.Split(querystr, "/") + pathLinks := []pathLink{} + for i, part := range queryParts { + pathLinks = append(pathLinks, pathLink{ + URL: "/r/" + rlmname + ":" + strings.Join(queryParts[:i+1], "/"), + Text: part, + }) + } - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - app.NewTemplatingEngine(). - Set("MainContent", string(mainContent)). - Set("Title", "Game of Realms Content For The Best Contributors "). - Set("Description", "Game of Realms is the first high-stakes competition held in two phases to find the best contributors to the Gno.land platform with a 133,700 ATOM prize pool."). - Render(w, r, "generic.html", "funcs.html") + tmpl := app.NewTemplatingEngine() + // XXX: extract title from realm's output + // XXX: extract description from realm's output + tmpl.Set("RealmName", rlmname) + tmpl.Set("RealmPath", rlmpath) + tmpl.Set("Query", querystr) + tmpl.Set("PathLinks", pathLinks) + tmpl.Set("Contents", string(res.Data)) + tmpl.Set("Flags", flags) + tmpl.Set("IsAlias", true) + tmpl.Render(w, r, "realm_render.html", "funcs.html") }) } func handlerFaucet(app gotuna.App) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { app.NewTemplatingEngine(). - Set("captchaSite", flags.captchaSite). - Set("faucetURL", flags.faucetURL). + Set("Flags", flags). Render(w, r, "faucet.html", "funcs.html") }) } @@ -214,6 +235,10 @@ func handlerStatusJSON(app gotuna.App) http.Handler { func handlerRedirect(app gotuna.App, to string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, to, http.StatusFound) + tmpl := app.NewTemplatingEngine() + tmpl.Set("To", to) + tmpl.Set("Flags", flags) + tmpl.Render(w, r, "redirect.html", "funcs.html") }) } @@ -248,10 +273,9 @@ func handlerRealmMain(app gotuna.App) http.Handler { tmpl := app.NewTemplatingEngine() tmpl.Set("FuncName", funcName) tmpl.Set("RealmPath", rlmpath) - tmpl.Set("Remote", flags.helpRemote) - tmpl.Set("ChainID", flags.helpChainID) tmpl.Set("DirPath", pathOf(rlmpath)) tmpl.Set("FunctionSignatures", fsigs) + tmpl.Set("Flags", flags) tmpl.Render(w, r, "realm_help.html", "funcs.html") } else { // Ensure realm exists. TODO optimize. @@ -313,12 +337,14 @@ func handleRealmRender(app gotuna.App, w http.ResponseWriter, r *http.Request) { } // Render template. tmpl := app.NewTemplatingEngine() - + // XXX: extract title from realm's output + // XXX: extract description from realm's output tmpl.Set("RealmName", rlmname) tmpl.Set("RealmPath", rlmpath) tmpl.Set("Query", querystr) tmpl.Set("PathLinks", pathLinks) tmpl.Set("Contents", string(res.Data)) + tmpl.Set("Flags", flags) tmpl.Render(w, r, "realm_render.html", "funcs.html") } @@ -361,6 +387,7 @@ func renderPackageFile(app gotuna.App, w http.ResponseWriter, r *http.Request, d tmpl.Set("DirURI", diruri) tmpl.Set("DirPath", pathOf(diruri)) tmpl.Set("Files", files) + tmpl.Set("Flags", flags) tmpl.Render(w, r, "package_dir.html", "funcs.html") } else { // Request is for a file. @@ -378,6 +405,7 @@ func renderPackageFile(app gotuna.App, w http.ResponseWriter, r *http.Request, d tmpl.Set("DirPath", pathOf(diruri)) tmpl.Set("FileName", filename) tmpl.Set("FileContents", string(res.Data)) + tmpl.Set("Flags", flags) tmpl.Render(w, r, "package_file.html", "funcs.html") } } @@ -387,7 +415,7 @@ func makeRequest(qpath string, data []byte) (res *abci.ResponseQuery, err error) // Height: height, XXX // Prove: false, XXX } - remote := flags.remoteAddr + remote := flags.RemoteAddr cli := client.NewHTTP(remote, "/websocket") qres, err := cli.ABCIQueryWithOptions( qpath, data, opts2) @@ -448,6 +476,7 @@ func handleNotFound(app gotuna.App, path string, w http.ResponseWriter, r *http. app.NewTemplatingEngine(). Set("title", "Not found"). Set("path", path). + Set("Flags", flags). Render(w, r, "404.html", "funcs.html") } diff --git a/gno.land/cmd/gnoweb/main_test.go b/gno.land/cmd/gnoweb/main_test.go index 1cc4d32b3a2..974d3f987b7 100644 --- a/gno.land/cmd/gnoweb/main_test.go +++ b/gno.land/cmd/gnoweb/main_test.go @@ -12,8 +12,11 @@ import ( ) func TestRoutes(t *testing.T) { - ok := http.StatusOK - found := http.StatusFound + const ( + ok = http.StatusOK + found = http.StatusFound + notFound = http.StatusNotFound + ) routes := []struct { route string status int @@ -33,8 +36,10 @@ func TestRoutes(t *testing.T) { {"/r/demo/deep/very/deep?help", ok, "exposed"}, {"/r/demo/deep/very/deep/", ok, "render.gno"}, {"/r/demo/deep/very/deep/render.gno", ok, "func Render("}, - {"/gor", found, "/r/gnoland/gor"}, + {"/game-of-realms", ok, "/r/gnoland/pages:p/gor"}, + {"/gor", found, "/game-of-realms"}, {"/blog", found, "/r/gnoland/blog"}, + {"/404-not-found", notFound, "/404-not-found"}, } if wd, err := os.Getwd(); err == nil { if strings.HasSuffix(wd, "cmd/gnoweb") { @@ -43,6 +48,14 @@ func TestRoutes(t *testing.T) { } else { panic("os.Getwd() -> err: " + err.Error()) } + + // configure default values + flags.RemoteAddr = "127.0.0.1:26657" + flags.HelpRemote = "127.0.0.1:26657" + flags.HelpChainID = "dev" + flags.CaptchaSite = "" + flags.ViewsDir = "./cmd/gnoweb/views" + flags.WithAnalytics = false app := makeApp() for _, r := range routes { @@ -51,8 +64,57 @@ func TestRoutes(t *testing.T) { response := httptest.NewRecorder() app.Router.ServeHTTP(response, request) assert.Equal(t, r.status, response.Code) - assert.Equal(t, strings.Contains(response.Body.String(), r.substring), true) + assert.Contains(t, response.Body.String(), r.substring) // println(response.Body.String()) }) } } + +func TestAnalytics(t *testing.T) { + routes := []string{ + // special realms + "/", // home + "/about", + "/start", + + // redirects + "/game-of-realms", + "/getting-started", + "/blog", + "/boards", + + // realm, source, help page + "/r/gnoland/blog", + "/r/gnoland/blog/admin.gno", + "/r/demo/users:administrator", + "/r/gnoland/blog?help", + + // special pages + "/404-not-found", + } + + t.Run("with", func(t *testing.T) { + for _, route := range routes { + t.Run(route, func(t *testing.T) { + flags.WithAnalytics = true + app := makeApp() + request := httptest.NewRequest(http.MethodGet, route, nil) + response := httptest.NewRecorder() + app.Router.ServeHTTP(response, request) + assert.Contains(t, response.Body.String(), "simpleanalytics") + }) + } + }) + t.Run("without", func(t *testing.T) { + for _, route := range routes { + t.Run(route, func(t *testing.T) { + flags.WithAnalytics = false + app := makeApp() + request := httptest.NewRequest(http.MethodGet, route, nil) + response := httptest.NewRecorder() + app.Router.ServeHTTP(response, request) + assert.Equal(t, strings.Contains(response.Body.String(), "simpleanalytics"), false) + }) + } + }) +} diff --git a/gno.land/cmd/gnoweb/pages/GOR.md b/gno.land/cmd/gnoweb/pages/GOR.md deleted file mode 100644 index 95a155319fb..00000000000 --- a/gno.land/cmd/gnoweb/pages/GOR.md +++ /dev/null @@ -1,30 +0,0 @@ -# Game of Realms - -The first high-stakes contest will see participants compete for the tiered membership to co-own the Gno.land blockchain. -A series of complex technical and non-technical tasks will challenge contributors to create innovative patterns that push the chain to new limits. -Start building the foundation for tomorrow through key smart contracts and other contributions that change our understanding of the world. - -You can start participating in the co-creation of the Game of Realms now by adding your contributions on the dedicated [GitHub page](https://github.com/gnolang/gno/issues/357) to help us formulate the challenges. We want to release the final challenges from your contributions. - -## Register Now - - -
-
- -
-
- - -
- -
- - -
- - -
-
-
- diff --git a/gno.land/cmd/gnoweb/views/404.html b/gno.land/cmd/gnoweb/views/404.html index c51543ca1cd..fee4fff8689 100644 --- a/gno.land/cmd/gnoweb/views/404.html +++ b/gno.land/cmd/gnoweb/views/404.html @@ -2,8 +2,7 @@ - - + {{ template "html_head" . }} 404 - Not Found @@ -13,6 +12,7 @@

{{.Data.path}}

+ {{ template "analytics" .}} {{- end -}} diff --git a/gno.land/cmd/gnoweb/views/faucet.html b/gno.land/cmd/gnoweb/views/faucet.html index 84bcc6f34e5..85d3d6780c5 100644 --- a/gno.land/cmd/gnoweb/views/faucet.html +++ b/gno.land/cmd/gnoweb/views/faucet.html @@ -2,8 +2,8 @@ + {{ template "html_head" . }} Gno.land - {{ template "html_head" }}
diff --git a/gno.land/cmd/gnoweb/views/funcs.html b/gno.land/cmd/gnoweb/views/funcs.html index 8ac2fe6328b..1f8b7a265dd 100644 --- a/gno.land/cmd/gnoweb/views/funcs.html +++ b/gno.land/cmd/gnoweb/views/funcs.html @@ -1,4 +1,4 @@ -{{ define "header_buttons" }} +{{- define "header_buttons" -}}
-{{ end }} {{ define "html_head" }} +{{- end -}} + +{{- define "html_head" -}} + +{{if .Data.Description}}{{end}} -{{ end }} {{ define "header_logo" }} +{{- end -}} + +{{- define "header_logo" -}} -{{ end }} {{ define "footer" }} +{{- end -}} + +{{- define "footer" -}} -{{ end }} {{ define "js" }} +{{- end -}} + +{{- define "js" -}} + -{{ end }} {{ define "subscribe" }} +{{ template "analytics" .}} +{{- end -}} + +{{- define "analytics" -}} +{{- if .Data.Flags.WithAnalytics -}} + + + +{{- end -}} +{{- end -}} + +{{- define "subscribe" -}}
-{{ end }} +{{- end -}} diff --git a/gno.land/cmd/gnoweb/views/generic.html b/gno.land/cmd/gnoweb/views/generic.html index 117ea9d59fe..e671625e26a 100644 --- a/gno.land/cmd/gnoweb/views/generic.html +++ b/gno.land/cmd/gnoweb/views/generic.html @@ -3,8 +3,7 @@ Gno.land - {{ .Data.Title }} - - {{ template "html_head" }} + {{ template "html_head" . }}
@@ -16,7 +15,7 @@
{{ template "footer" }}
- {{ template "js" }} + {{ template "js" .}} {{- end -}} diff --git a/gno.land/cmd/gnoweb/views/home.html b/gno.land/cmd/gnoweb/views/home.html deleted file mode 100644 index a2bf78adb96..00000000000 --- a/gno.land/cmd/gnoweb/views/home.html +++ /dev/null @@ -1,21 +0,0 @@ -{{- define "app" -}} - - - - Gno.land - {{ .Data.Title }} - - {{ template "html_head" }} - - -
- -
-
{{ .Data.HomeContent }}
-
-
{{ template "subscribe" }}
- {{ template "footer" }} -
- {{ template "js" }} - - -{{- end -}} diff --git a/gno.land/cmd/gnoweb/views/package_dir.html b/gno.land/cmd/gnoweb/views/package_dir.html index 6b0bf5cfd48..efaf4d7ad0c 100644 --- a/gno.land/cmd/gnoweb/views/package_dir.html +++ b/gno.land/cmd/gnoweb/views/package_dir.html @@ -2,8 +2,8 @@ - Gno.land - {{ template "html_head" }} + {{ template "html_head" . }} + Gno.land - {{.Data.DirPath}}
@@ -12,13 +12,14 @@ {{ .Data.DirPath }}/*
{{ template "dir_contents" . }}
- {{ template "footer" }} - {{ template "js" }} + {{ template "js" . }} -{{- end -}} {{ define "dir_contents" }} +{{- end -}} + +{{- define "dir_contents" -}}
{{ $dirPath := .Data.DirPath }}
-{{ end }} +{{- end -}} diff --git a/gno.land/cmd/gnoweb/views/package_file.html b/gno.land/cmd/gnoweb/views/package_file.html index 7068854d16c..71aa8b68452 100644 --- a/gno.land/cmd/gnoweb/views/package_file.html +++ b/gno.land/cmd/gnoweb/views/package_file.html @@ -2,8 +2,8 @@ - Gno.land - {{ template "html_head" }} + {{ template "html_head" . }} + Gno.land - {{.Data.DirPath}}/{{.Data.FileName}}
@@ -18,7 +18,7 @@ {{ template "footer" }}
- {{ template "js" }} + {{ template "js" .}} - + {{ template "js" . }} -{{- end -}} +{{ define "func_specs" }} +{{- end -}} + +{{- define "func_specs" -}}
{{ $funcName := .Data.FuncName }} {{ $found := false }} {{ if eq $funcName "" }} {{ range .Data.FunctionSignatures }} {{ template "func_spec" . }} {{ end }} {{ else }} {{ range .Data.FunctionSignatures }} {{ if eq .FuncName $funcName }} {{ $found = true }} {{ template "func_spec" . }} {{ end }} {{ end }} {{ if not $found }} {{ $funcName }} not found. {{ end }} {{ end }}
-{{ end }} {{ define "func_spec" }} +{{- end -}} + +{{- define "func_spec" -}}
@@ -67,7 +69,9 @@
-{{ end }} {{ define "func_param" }} +{{- end -}} + +{{- define "func_param" -}} {{ .Name }} @@ -75,7 +79,9 @@ {{ .Type }} -{{ end }} {{ define "func_result" }} +{{- end -}} + +{{- define "func_result" -}} {{ .Name }} {{ .Type }} diff --git a/gno.land/cmd/gnoweb/views/realm_render.html b/gno.land/cmd/gnoweb/views/realm_render.html index 8a2c35adeca..6337d77aafa 100644 --- a/gno.land/cmd/gnoweb/views/realm_render.html +++ b/gno.land/cmd/gnoweb/views/realm_render.html @@ -2,8 +2,8 @@ - Gno.land - {{ template "html_head" }} + {{ template "html_head" . }} + Gno.land - {{.Data.RealmName}}
@@ -26,10 +26,7 @@
{{ template "footer" }} - {{ template "js" }} - - - + {{ template "js" .}} {{- end -}} diff --git a/gno.land/cmd/gnoweb/views/redirect.html b/gno.land/cmd/gnoweb/views/redirect.html new file mode 100644 index 00000000000..6fe43a7138b --- /dev/null +++ b/gno.land/cmd/gnoweb/views/redirect.html @@ -0,0 +1,16 @@ +{{- define "app" -}} + + + + + + + + Redirecting to {{.Data.To}} + + + {{.Data.To}} + {{ template "analytics" .}} + + +{{- end -}} From 5e4572b36b10720379b59af64177faf4f08164e3 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 17 Oct 2023 23:48:50 +0200 Subject: [PATCH 10/21] chore: improve content, add page partner, make home more focused Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/gnoland/home/home.gno | 150 +++++++++--------- .../gno.land/r/gnoland/home/home_filetest.gno | 61 +++---- .../gno.land/r/gnoland/pages/page_gor.gno | 20 ++- .../r/gnoland/pages/page_partners.gno | 21 +++ .../gno.land/r/gnoland/pages/pages_test.gno | 2 +- gno.land/cmd/gnoweb/main.go | 2 + 6 files changed, 140 insertions(+), 116 deletions(-) create mode 100644 examples/gno.land/r/gnoland/pages/page_partners.gno diff --git a/examples/gno.land/r/gnoland/home/home.gno b/examples/gno.land/r/gnoland/home/home.gno index 2a30fb75d25..ba777d1dbcd 100644 --- a/examples/gno.land/r/gnoland/home/home.gno +++ b/examples/gno.land/r/gnoland/home/home.gno @@ -4,42 +4,30 @@ import "std" var body = `# Welcome to Gno.land ---- - -## An interpretation of the Golang (Go) programming language for advanced developers and intrepid pioneers to build succinct, composable smart contracts for social coordination. +### An interpretation of the Golang (Go) programming language for advanced developers and intrepid pioneers to build succinct, composable smart contracts for social coordination. If you’re concerned about information censorship and want to contribute to the #GnoWorldOrder, follow our socials to find out how. Gno.land is in building mode. If you want to help lay the foundations of a fairer and freer world through innovative ideas and exceptional code, join us today. -
- -[About Gno.land](/about) -[Explore Github repo](https://github.com/gnolang) - -
-
- -### Game of Realms - -The first high-stakes contest will see participants compete for tiered membership to co-own the Gno.land blockchain. A series of complex technical and non-technical tasks will challenge contributors to create innovative patterns that push the chain to new limits. Start building the foundation for tomorrow through key smart contracts and other contributions that change our understanding of the world. - -
- -[Join Game Of Realms](/game-of-realms) - -
-
- -### Fund and Grants Program +--- -Are you a builder, tinkerer, or researcher? If you’re looking to create awesome dApps, tooling, infrastructure, or smart contract libraries on Gno.land, you can apply for a grant. The Gno.land Ecosystem Fund and Grants program provides financial contributions for individuals and teams to innovate on the platform. +### WorxDAO -
+TODO -[More information here](https://github.com/gnolang/ecosystem-fund-grants) +- A + - A1 + - A1A + - A1B + - A2 + - A3 + - A3A + - A3A1 +- B +- C -
+---
@@ -47,11 +35,12 @@ Are you a builder, tinkerer, or researcher? If you’re looking to create awesom ### Learn about Gno.land - [About](/about) +- [GitHub](https://github.com/gnolang) - [Subscribe](#subscribe) - [Tokenomics (soon)](#) - [Blog](/blog) - [Events](/events) -- [Partners (soon)](#) +- [Partners, Fund, Grants](/partners)
@@ -82,66 +71,70 @@ Are you a builder, tinkerer, or researcher? If you’re looking to create awesom
+## Explore New Packages and Realms + +
+
+ +#### r/gnoland +- [/r/gnoland/blog](/r/gnoland/blog) +- [/r/gnoland/dao](/r/gnoland/dao) +- [/r/gnoland/faucet](/r/gnoland/faucet) +- [/r/gnoland/home](/r/gnoland/home) +- [/r/gnoland/pages](/r/gnoland/pages) + +#### r/system +- [/r/system/names](/r/system/names) +- [/r/system/rewards](/r/system/rewards) +- [/r/system/validators](/r/system/validators) + +
+
+ +#### r/demo +- [/r/demo/boards](/r/demo/boards) +- [/r/demo/users](/r/demo/users) +- [/r/demo/banktest](/r/demo/banktest) +- [/r/demo/foo20](/r/demo/foo20) +- [/r/demo/foo721](/r/demo/foo721) +- [/r/demo/microblog](/r/demo/microblog) +- [/r/demo/nft](/r/demo/nft) +- [/r/demo/types](/r/demo/types) +- [/r/demo/art](/r/demo/art) +- [/r/demo/groups](/r/demo/groups) +- ... + +
+
+ +#### p/demo +- [/p/demo/avl](/p/demo/avl) +- [/p/demo/blog](/p/demo/blog) +- [/p/demo/ui](/p/demo/ui) +- [/p/demo/ufmt](/p/demo/ufmt) +- [/p/demo/merkle](/p/demo/merkle) +- [/p/demo/bf](/p/demo/bf) +- [/p/demo/flow](/p/demo/flow) +- [/p/demo/gnode](/p/demo/gnode) +- [/p/demo/grc/grc20](/p/demo/grc/grc20) +- [/p/demo/grc/grc721](/p/demo/grc/grc721) +- ... + +
+
+ --- ### Socials +- Check out our [community projects](https://github.com/gnolang/awesome-gno). - ![Discord](static/img/ico-discord.svg) [Discord](https://discord.gg/S8nKUqwkPn) - ![Twitter](static/img/ico-twitter.svg) [Twitter](https://twitter.com/_gnoland) - ![Youtube](static/img/ico-youtube.svg) [Youtube](https://www.youtube.com/@_gnoland) - ![Telegram](static/img/ico-telegram.svg) [Telegram](https://t.me/gnoland) -` - -var body2 = `# Welcome to **Gno.land** - -- [About Gno.land](/r/gnoland/pages:about) -- [Blogs](/r/gnoland/blog) -- [Install ` + "`" + `gnokey` + "`" + `](https://github.com/gnolang/gno/tree/master/gno.land/cmd/gnokey) -- [Acquire testnet tokens](/faucet) -- [Game of Realms](/game-of-realms) - An open worldwide competition for developers to build the best Gnolang smart-contracts. - -# Explore new packages. - -- r/gnoland - - [/r/gnoland/blog](/r/gnoland/blog) - - [/r/gnoland/faucet](/r/gnoland/faucet) -- r/system - - [/r/system/names](/r/system/names) - - [/r/system/rewards](/r/system/rewards) - - [/r/system/validators](/r/system/validators) -- r/demo - - [/r/demo/banktest](/r/demo/banktest) - - [/r/demo/boards](/r/demo/boards) - - [/r/demo/foo20](/r/demo/foo20) - - [/r/demo/nft](/r/demo/nft) - - [/r/demo/types](/r/demo/types) - - [/r/demo/users](/r/demo/users) - - [/r/demo/groups](/r/demo/groups) -- p/demo - - [/p/demo/avl](/p/demo/avl) - - [/p/demo/blog](/p/demo/blog) - - [/p/demo/flow](/p/demo/flow) - - [/p/demo/gnode](/p/demo/gnode) - - [/p/demo/grc/exts](/p/demo/grc/exts) - - [/p/demo/grc/grc20](/p/demo/grc/grc20) - - [/p/demo/grc/grc721](/p/demo/grc/grc721) - -# Other Testnets - -- **[staging.gno.land](https://staging.gno.land) (wiped every commit to master)** -- _[test3.gno.land](https://test3.gno.land) (latest)_ -- _[test2.gno.land](https://test2.gno.land) (archive)_ -- _[test1.gno.land](https://test1.gno.land) (archive)_ **This is a testnet.** Package names are not guaranteed to be available for production. - -# Social - -Check out our [community projects](https://github.com/gnolang/awesome-gno). - -Official channel: [Discord](https://discord.gg/S8nKUqwkPn)
-Other channels: [Telegram](https://t.me/gnoland) [Twitter](https://twitter.com/_gnoland) [Youtube](https://www.youtube.com/@_gnoland) ` var adminAddr std.Address = std.Address("") @@ -175,7 +168,8 @@ func Render(_ string) string { // XXX: // XXX: community curated picks // XXX: - body += randomBanner() + body += "\n\n" + randomBanner() + return body } diff --git a/examples/gno.land/r/gnoland/home/home_filetest.gno b/examples/gno.land/r/gnoland/home/home_filetest.gno index a38a41eb437..43e831e79c6 100644 --- a/examples/gno.land/r/gnoland/home/home_filetest.gno +++ b/examples/gno.land/r/gnoland/home/home_filetest.gno @@ -9,42 +9,38 @@ func main() { // Output: // # Welcome to Gno.land // -// --- -// -// ## An interpretation of the Golang (Go) programming language for advanced developers and intrepid pioneers to build succinct, composable smart contracts for social coordination. +// ### An interpretation of the Golang (Go) programming language for advanced developers and intrepid pioneers to build succinct, composable smart contracts for social coordination. // // If you’re concerned about information censorship and want to contribute to the #GnoWorldOrder, follow our socials to find out how. // // Gno.land is in building mode. If you want to help lay the foundations of a fairer and freer world through innovative ideas and exceptional code, join us today. // -//
-// -// [About Gno.land](/about) -// [Explore Github repo](https://github.com/gnolang) -// -//
-//
-// -// ### Game of Realms -// -// The first high-stakes contest will see participants compete for tiered membership to co-own the Gno.land blockchain. A series of complex technical and non-technical tasks will challenge contributors to create innovative patterns that push the chain to new limits. Start building the foundation for tomorrow through key smart contracts and other contributions that change our understanding of the world. -// -//
+// ### Explore New Packages and Realms +// +// - r/gnoland +// - [/r/gnoland/blog](/r/gnoland/blog) +// - [/r/gnoland/faucet](/r/gnoland/faucet) +// - r/system +// - [/r/system/names](/r/system/names) +// - [/r/system/rewards](/r/system/rewards) +// - [/r/system/validators](/r/system/validators) +// - r/demo +// - [/r/demo/banktest](/r/demo/banktest) +// - [/r/demo/boards](/r/demo/boards) +// - [/r/demo/foo20](/r/demo/foo20) +// - [/r/demo/nft](/r/demo/nft) +// - [/r/demo/types](/r/demo/types) +// - [/r/demo/users](/r/demo/users) +// - [/r/demo/groups](/r/demo/groups) +// - p/demo +// - [/p/demo/avl](/p/demo/avl) +// - [/p/demo/blog](/p/demo/blog) +// - [/p/demo/flow](/p/demo/flow) +// - [/p/demo/gnode](/p/demo/gnode) +// - [/p/demo/grc/exts](/p/demo/grc/exts) +// - [/p/demo/grc/grc20](/p/demo/grc/grc20) +// - [/p/demo/grc/grc721](/p/demo/grc/grc721) // -// [Join Game Of Realms](/game-of-realms) -// -//
-//
-// -// ### Fund and Grants Program -// -// Are you a builder, tinkerer, or researcher? If you’re looking to create awesome dApps, tooling, infrastructure, or smart contract libraries on Gno.land, you can apply for a grant. The Gno.land Ecosystem Fund and Grants program provides financial contributions for individuals and teams to innovate on the platform. -// -//
-// -// [More information here](https://github.com/gnolang/ecosystem-fund-grants) -// -//
// //
//
@@ -52,6 +48,7 @@ func main() { // ### Learn about Gno.land // // - [About](/about) +// - [GitHub](https://github.com/gnolang) // - [Subscribe](#subscribe) // - [Tokenomics (soon)](#) // - [Blog](/blog) @@ -91,8 +88,12 @@ func main() { // // ### Socials // +// - Check out our [community projects](https://github.com/gnolang/awesome-gno). // - ![Discord](static/img/ico-discord.svg) [Discord](https://discord.gg/S8nKUqwkPn) // - ![Twitter](static/img/ico-twitter.svg) [Twitter](https://twitter.com/_gnoland) // - ![Youtube](static/img/ico-youtube.svg) [Youtube](https://www.youtube.com/@_gnoland) // - ![Telegram](static/img/ico-telegram.svg) [Telegram](https://t.me/gnoland) +// +// **This is a testnet.** +// Package names are not guaranteed to be available for production. // Gno is for Truth. diff --git a/examples/gno.land/r/gnoland/pages/page_gor.gno b/examples/gno.land/r/gnoland/pages/page_gor.gno index 6c9e46b4062..3a6bb022e09 100644 --- a/examples/gno.land/r/gnoland/pages/page_gor.gno +++ b/examples/gno.land/r/gnoland/pages/page_gor.gno @@ -1,13 +1,20 @@ package gnopages func init() { - var ( - path = "gor" - title = "Game of Realms Content For The Best Contributors" - // XXX: description = "Game of Realms is the first high-stakes competition held in two phases to find the best contributors to the Gno.land platform with a 133,700 ATOM prize pool." - body = `# Game of Realms + path := "gor" + title := "Game of Realms Content For The Best Contributors" + // XXX: description := "Game of Realms is the first high-stakes competition held in two phases to find the best contributors to the Gno.land platform with a 133,700 ATOM prize pool." + body := `# Game of Realms -The worldwide competition to find the best contributors to Gno.land is currently in phase one – for advanced developers only. +
+ +### Game of Realms + +The first high-stakes contest will see participants compete for tiered membership to co-own the Gno.land blockchain. A series of complex technical and non-technical tasks will challenge contributors to create innovative patterns that push the chain to new limits. Start building the foundation for tomorrow through key smart contracts and other contributions that change our understanding of the world. + +
+ +The competition is currently in phase one – for advanced developers only. Once the necessary tools to start phase two are ready, we’ll open up the competition to newer devs and non-technical contributors. @@ -210,6 +217,5 @@ Game of Realms participants and core contributors have made significant progress
` - ) _ = b.NewPost("", path, title, body, nil) } diff --git a/examples/gno.land/r/gnoland/pages/page_partners.gno b/examples/gno.land/r/gnoland/pages/page_partners.gno new file mode 100644 index 00000000000..440302437fa --- /dev/null +++ b/examples/gno.land/r/gnoland/pages/page_partners.gno @@ -0,0 +1,21 @@ +package gnopages + +func init() { + path := "partners" + title := "Partners" + // XXX: description := """ + body := `## Partnerships + +### Fund and Grants Program + +Are you a builder, tinkerer, or researcher? If you’re looking to create awesome dApps, tooling, infrastructure, or smart contract libraries on Gno.land, you can apply for a grant. The Gno.land Ecosystem Fund and Grants program provides financial contributions for individuals and teams to innovate on the platform. + +
+ +[More information here](https://github.com/gnolang/ecosystem-fund-grants) + +
+` + + _ = b.NewPost("", path, title, body, nil) +} diff --git a/examples/gno.land/r/gnoland/pages/pages_test.gno b/examples/gno.land/r/gnoland/pages/pages_test.gno index 1389e5b5463..5a6fe84ad38 100644 --- a/examples/gno.land/r/gnoland/pages/pages_test.gno +++ b/examples/gno.land/r/gnoland/pages/pages_test.gno @@ -15,7 +15,7 @@ func TestHome(t *testing.T) { "/r/gnoland/pages:p/start", "/r/gnoland/pages:p/gor", "/r/gnoland/pages:p/about", - "/r/gnoland/pages:p/language", + "/r/gnoland/pages:p/gnolang", } for _, substring := range expectedSubtrings { if !strings.Contains(got, substring) { diff --git a/gno.land/cmd/gnoweb/main.go b/gno.land/cmd/gnoweb/main.go index 3b9f6f5fec3..0d9398cb8e2 100644 --- a/gno.land/cmd/gnoweb/main.go +++ b/gno.land/cmd/gnoweb/main.go @@ -70,6 +70,7 @@ func makeApp() gotuna.App { "/about": "/r/gnoland/pages:p/about", "/gnolang": "/r/gnoland/pages:p/gnolang", "/ecosystem": "/r/gnoland/pages:p/ecosystem", + "/partners": "/r/gnoland/pages:p/partners", "/testnets": "/r/gnoland/pages:p/testnets", "/start": "/r/gnoland/pages:p/start", "/game-of-realms": "/r/gnoland/pages:p/gor", // XXX: replace with gor realm @@ -83,6 +84,7 @@ func makeApp() gotuna.App { "/r/demo/boards:gnolang/6": "/r/demo/boards:gnolang/3", // XXX: temporary "/blog": "/r/gnoland/blog", "/gor": "/game-of-realms", + "/grants": "/partners", "/language": "/gnolang", "/getting-started": "/start", } From a628e6ebb5928bcde663ff895920abb5cea783cf Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 17 Oct 2023 20:44:14 -0400 Subject: [PATCH 11/21] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/demo/boards/README.md | 149 ++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 examples/gno.land/r/demo/boards/README.md diff --git a/examples/gno.land/r/demo/boards/README.md b/examples/gno.land/r/demo/boards/README.md new file mode 100644 index 00000000000..2729df055b1 --- /dev/null +++ b/examples/gno.land/r/demo/boards/README.md @@ -0,0 +1,149 @@ +This is a demo of Gno smart contract programming. This document was +constructed by Gno onto a smart contract hosted on the data Realm +name ["gno.land/r/demo/boards"](https://gno.land/r/demo/boards/) +([github](https://github.com/gnolang/gno/tree/master/examples/gno.land/r/demo/boards)). + + + +## Build `gnokey`, create your account, and interact with Gno. + +NOTE: Where you see `-remote localhost:26657` here, that flag can be replaced +with `-remote test3.gno.land:36657` if you have $GNOT on the testnet. +(To use the testnet, also replace `-chainid dev` with `-chainid testchain` .) + +### Build `gnokey` (and other tools). + +```bash +git clone git@github.com:gnolang/gno.git +cd gno/gno.land +make build +``` + +### Generate a seed/mnemonic code. + +```bash +./build/gnokey generate +``` + +NOTE: You can generate 24 words with any good bip39 generator. + +### Create a new account using your mnemonic. + +```bash +./build/gnokey add -recover KEYNAME +``` + +NOTE: `KEYNAME` is your key identifier, and should be changed. + +### Verify that you can see your account locally. + +```bash +./build/gnokey list +``` + +Take note of your `addr` which looks something like `g17sphqax3kasjptdkmuqvn740u8dhtx4kxl6ljf` . +You will use this as your `ACCOUNT_ADDR`. + +## Interact with the blockchain. + +### Add $GNOT for your account. + +Before starting the `gnoland` node for the first time, your new account can be given $GNOT in the node genesis. +Edit the file `gno.land/genesis/genesis_balances.txt` and add the following line (simlar to the others), using +your `ACCOUNT_ADDR` and `KEYNAME` + +`ACCOUNT_ADDR=10000000000ugnot # @KEYNAME` + +### Alternative: Run a faucet to add $GNOT. + +Instead of editing `gno.land/genesis/genesis_balances.txt`, a more general solution (with more steps) +is to run a local "faucet" and use the web browser to add $GNOT. (This can be done at any time.) +See this page: https://github.com/gnolang/gno/blob/master/gno.land/cmd/gnofaucet/README.md + +### Start the `gnoland` node. + +```bash +./build/gnoland start +``` + +NOTE: The node already has the "boards" realm. + +Leave this running in the terminal. In a new terminal, cd to the same folder `gno/gno.land` . + +### Get your current balance, account number, and sequence number. + +```bash +./build/gnokey query auth/accounts/ACCOUNT_ADDR -remote localhost:26657 +``` + +### Register a board username with a smart contract call. + +The `USERNAME` for posting can different than your `KEYNAME`. It is internally linked to your `ACCOUNT_ADDR`. It must be at least 6 characters, lowercase alphanumeric with underscore. + +```bash +./build/gnokey maketx call -pkgpath "gno.land/r/demo/users" -func "Register" -args "" -args "USERNAME" -args "Profile description" -gas-fee "10000000ugnot" -gas-wanted "2000000" -send "200000000ugnot" -broadcast -chainid dev -remote 127.0.0.1:26657 KEYNAME +``` + +Interactive documentation: https://test3.gno.land/r/demo/users?help&__func=Register + +### Create a board with a smart contract call. + +```bash +./build/gnokey maketx call -pkgpath "gno.land/r/demo/boards" -func "CreateBoard" -args "BOARDNAME" -gas-fee "1000000ugnot" -gas-wanted "10000000" -broadcast -chainid dev -remote localhost:26657 KEYNAME +``` + +Interactive documentation: https://test3.gno.land/r/demo/boards?help&__func=CreateBoard + +Next, query for the permanent board ID by querying (you need this to create a new post): + +```bash +./build/gnokey query "vm/qeval" -data "gno.land/r/demo/boards +GetBoardIDFromName(\"BOARDNAME\")" -remote localhost:26657 +``` + +### Create a post of a board with a smart contract call. + +NOTE: If a board was created successfully, your SEQUENCE_NUMBER would have increased. + +```bash +./build/gnokey maketx call -pkgpath "gno.land/r/demo/boards" -func "CreateThread" -args BOARD_ID -args "Hello gno.land" -args "Text of the post" -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid dev -remote localhost:26657 KEYNAME +``` + +Interactive documentation: https://test3.gno.land/r/demo/boards?help&__func=CreateThread + +### Create a comment to a post. + +```bash +./build/gnokey maketx call -pkgpath "gno.land/r/demo/boards" -func "CreateReply" -args BOARD_ID -args "1" -args "1" -args "Nice to meet you too." -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid dev -remote localhost:26657 KEYNAME +``` + +Interactive documentation: https://test3.gno.land/r/demo/boards?help&__func=CreateReply + +```bash +./build/gnokey query "vm/qrender" -data "gno.land/r/demo/boards +BOARDNAME/1" -remote localhost:26657 +``` + +### Render page with optional path expression. + +The contents of `https://gno.land/r/demo/boards:` and `https://gno.land/r/demo/boards:gnolang` are rendered by calling +the `Render(path string)` function like so: + +```bash +./build/gnokey query "vm/qrender" -data "gno.land/r/demo/boards +gnolang" +``` +## View the board in the browser. + +### Start the web server. + +```bash +./build/gnoweb +``` + +This should print something like `Running on http://127.0.0.1:8888` . Leave this running in the terminal. + +### View in the browser + +In your browser, navigate to the printed address http://127.0.0.1:8888 . +To see you post, click on the package `/r/demo/boards` . From edeaeb24f426056e391aa6aa8d24add6416faf08 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 17 Oct 2023 23:12:04 -0400 Subject: [PATCH 12/21] chore: refactor homepage Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/p/demo/ui/ui.gno | 44 ++- examples/gno.land/r/gnoland/home/home.gno | 304 ++++++++++-------- .../gno.land/r/gnoland/home/home_filetest.gno | 118 +++++-- 3 files changed, 305 insertions(+), 161 deletions(-) diff --git a/examples/gno.land/p/demo/ui/ui.gno b/examples/gno.land/p/demo/ui/ui.gno index efa185914a0..59e9403a025 100644 --- a/examples/gno.land/p/demo/ui/ui.gno +++ b/examples/gno.land/p/demo/ui/ui.gno @@ -1,6 +1,9 @@ package ui -import "strings" +import ( + "strconv" + "strings" +) type DOM struct { // metadata @@ -56,6 +59,17 @@ func (dom DOM) String() string { return output } +type Jumbotron []DomStringer + +func (j Jumbotron) String(dom DOM) string { + output := `
` + "\n\n" + for _, elem := range j { + output += elem.String(dom) + "\n" + } + output += `
` + "\n" + return output +} + // XXX: rename Element to Div? type Element []DomStringer @@ -88,6 +102,26 @@ func (b Breadcrumb) String(dom DOM) string { return output } +type Columns struct { + MaxWidth int + Columns []Element +} + +func (c *Columns) Append(elems ...Element) { + c.Columns = append(c.Columns, elems...) +} + +func (c Columns) String(dom DOM) string { + output := `
` + "\n" + for idx, entry := range c.Columns { + output += `
` + "\n\n" + output += entry.String(dom) + output += "
\n" + } + output += "
\n" + return output +} + type Link struct { Text string Path string @@ -104,8 +138,14 @@ func (l Link) String(dom DOM) string { case l.Path != "" && l.URL != "": panic("a link should have a path or a URL, not both.") case l.Path != "": + if l.Text == "" { + l.Text = l.Path + } url = dom.Prefix + l.Path case l.URL != "": + if l.Text == "" { + l.Text = l.URL + } url = l.URL } @@ -151,6 +191,7 @@ type ( Italic string Code string Paragraph string + Quote string HR struct{} ) @@ -160,6 +201,7 @@ func (text H3) String(_ DOM) string { return "### " + string(text) + "\n" func (text H4) String(_ DOM) string { return "#### " + string(text) + "\n" } func (text H5) String(_ DOM) string { return "##### " + string(text) + "\n" } func (text H6) String(_ DOM) string { return "###### " + string(text) + "\n" } +func (text Quote) String(_ DOM) string { return "> " + string(text) + "\n" } func (text Bold) String(_ DOM) string { return "**" + string(text) + "**" } func (text Italic) String(_ DOM) string { return "_" + string(text) + "_" } func (text Paragraph) String(_ DOM) string { return "\n" + string(text) + "\n" } diff --git a/examples/gno.land/r/gnoland/home/home.gno b/examples/gno.land/r/gnoland/home/home.gno index ba777d1dbcd..c24e455a40d 100644 --- a/examples/gno.land/r/gnoland/home/home.gno +++ b/examples/gno.land/r/gnoland/home/home.gno @@ -1,35 +1,185 @@ package home -import "std" +import ( + "std" -var body = `# Welcome to Gno.land + "gno.land/p/demo/avl" + "gno.land/p/demo/ufmt" + "gno.land/p/demo/ui" +) -### An interpretation of the Golang (Go) programming language for advanced developers and intrepid pioneers to build succinct, composable smart contracts for social coordination. +// XXX: use an updatable block system to update content from a DAO +// XXX: var blocks avl.Tree -If you’re concerned about information censorship and want to contribute to the #GnoWorldOrder, follow our socials to find out how. - -Gno.land is in building mode. If you want to help lay the foundations of a fairer and freer world through innovative ideas and exceptional code, join us today. +func Render(_ string) string { + dom := ui.DOM{Prefix: "r/gnoland/home:"} + dom.Title = "Welcome to Gno.land" + + // body + dom.Body.Append(introSection()...) + dom.Body.Append(ui.Jumbotron(worxDAO()...)) + dom.Body.Append(packageStaffPicks()...) + dom.Body.Append(ui.Jumbotron(discoverLinks()...)) + + // footer + dom.Footer.Append( + ui.Columns{2, []ui.Element{ + socialLinks(), + quoteOfTheBlock(), + }}, + ) + + // Testnet disclaimer + dom.Footer.Append( + ui.HR{}, + ui.Bold("This is a testnet."), + ui.Text("Package names are not guaranteed to be available for production."), + ) + + return dom.String() +} ---- +func introSection() ui.Element { + return ui.Element{ + ui.H3("An interpretation of the Golang (Go) programming language for advanced developers and intrepid pioneers to build succinct, composable smart contracts for social coordination."), + ui.Paragraph("If you’re concerned about information censorship and want to contribute to the #GnoWorldOrder, follow our socials to find out how."), + ui.Paragraph("Gno.land is in building mode. If you want to help lay the foundations of a fairer and freer world through innovative ideas and exceptional code, join us today."), + } +} -### WorxDAO +func worxDAO() ui.Element { + // WorxDAO + // highest level == highest responsibility + // teams are responsible for components they don't owne + // flag : realm maintainers VS facilitators + // teams + // committee of trustees to create the directory + // each directory is a name, has a parent and have groups + // homepage team - blocks aggregating events + // XXX: TODO + /*` + # Directory -TODO + * gno.land (owned by group) + * + * gnovm + * gnolang (language) + * gnovm + - current challenges / concerns / issues + * tm2 + * amino + * -- A - - A1 - - A1A - - A1B - - A2 - - A3 - - A3A - - A3A1 + ## Contributors + ``*/ + return ui.Element{ + ui.H3("WorxDAO"), + ui.Text(`- A +- A1 +- A1A +- A1B +- A2 +- A3 +- A3A +- A3A1 - B -- C +- C`), + } +} + +func quoteOfTheBlock() ui.Element { + quotes := []string{ + "Gno is for Truth.", + "Gno is for Social Coordination.", + "Gno is _not only_ for DeFi.", + "Now, you Gno.", + "Come for the Go, Stay for the Gno.", + } + height := std.GetHeight() + idx := int(height) % len(quotes) + qotb := quotes[idx] ---- + return ui.Element{ + ui.H3(ufmt.Sprintf("Quote of the ~Day~Block#%d", height)), + ui.Quote(qotb), + } +} -
+func socialLinks() ui.Element { + return ui.Element{ + ui.H3("Socials"), + ui.BulletList{ + // XXX: improve UI to support a nice GO api for such links + ui.Text("Check out our [community projects](https://github.com/gnolang/awesome-gno).)"), + ui.Text("![Discord](static/img/ico-discord.svg) [Discord](https://discord.gg/S8nKUqwkPn)"), + ui.Text("![Twitter](static/img/ico-twitter.svg) [Twitter](https://twitter.com/_gnoland)"), + ui.Text("![Youtube](static/img/ico-youtube.svg) [Youtube](https://www.youtube.com/@_gnoland)"), + ui.Text("![Telegram](static/img/ico-telegram.svg) [Telegram](https://t.me/gnoland)"), + }, + } +} + +func packageStaffPicks() ui.Element { + // XXX: make it modifiable from a DAO + return ui.Element{ + ui.H3("Explore New Packages and Realms"), + ui.Columns{ + 3, + []ui.Element{ + { + ui.H4("r/gnoland"), + ui.BulletList{ + ui.Link{URL: "r/gnoland/blog"}, + ui.Link{URL: "r/gnoland/dao"}, + ui.Link{URL: "r/gnoland/faucet"}, + ui.Link{URL: "r/gnoland/home"}, + ui.Link{URL: "r/gnoland/pages"}, + }, + ui.H4("r/system"), + ui.BulletList{ + ui.Link{URL: "r/system/names"}, + ui.Link{URL: "r/system/rewards"}, + ui.Link{URL: "r/system/validators"}, + }, + }, { + ui.H4("r/demo"), + ui.BulletList{ + ui.Link{URL: "r/demo/boards"}, + ui.Link{URL: "r/demo/users"}, + ui.Link{URL: "r/demo/banktest"}, + ui.Link{URL: "r/demo/foo20"}, + ui.Link{URL: "r/demo/foo721"}, + ui.Link{URL: "r/demo/microblog"}, + ui.Link{URL: "r/demo/nft"}, + ui.Link{URL: "r/demo/types"}, + ui.Link{URL: "r/demo/art"}, + ui.Link{URL: "r/demo/groups"}, + ui.Text("..."), + }, + }, { + ui.H4("p/demo"), + ui.BulletList{ + ui.Link{URL: "p/demo/avl"}, + ui.Link{URL: "p/demo/blog"}, + ui.Link{URL: "p/demo/ui"}, + ui.Link{URL: "p/demo/ufmt"}, + ui.Link{URL: "p/demo/merkle"}, + ui.Link{URL: "p/demo/bf"}, + ui.Link{URL: "p/demo/flow"}, + ui.Link{URL: "p/demo/gnode"}, + ui.Link{URL: "p/demo/grc/grc20"}, + ui.Link{URL: "p/demo/grc/grc721"}, + ui.Text("..."), + }, + }, + }, + }, + } +} + +func discoverLinks() ui.Element { + return ui.Element{ + ui.Text(`
### Learn about Gno.land @@ -69,118 +219,6 @@ TODO - [Testnet Tokens (faucet)](https://test3.gno.land/faucet)
-
- -## Explore New Packages and Realms - -
-
- -#### r/gnoland -- [/r/gnoland/blog](/r/gnoland/blog) -- [/r/gnoland/dao](/r/gnoland/dao) -- [/r/gnoland/faucet](/r/gnoland/faucet) -- [/r/gnoland/home](/r/gnoland/home) -- [/r/gnoland/pages](/r/gnoland/pages) - -#### r/system -- [/r/system/names](/r/system/names) -- [/r/system/rewards](/r/system/rewards) -- [/r/system/validators](/r/system/validators) - -
-
- -#### r/demo -- [/r/demo/boards](/r/demo/boards) -- [/r/demo/users](/r/demo/users) -- [/r/demo/banktest](/r/demo/banktest) -- [/r/demo/foo20](/r/demo/foo20) -- [/r/demo/foo721](/r/demo/foo721) -- [/r/demo/microblog](/r/demo/microblog) -- [/r/demo/nft](/r/demo/nft) -- [/r/demo/types](/r/demo/types) -- [/r/demo/art](/r/demo/art) -- [/r/demo/groups](/r/demo/groups) -- ... - -
-
- -#### p/demo -- [/p/demo/avl](/p/demo/avl) -- [/p/demo/blog](/p/demo/blog) -- [/p/demo/ui](/p/demo/ui) -- [/p/demo/ufmt](/p/demo/ufmt) -- [/p/demo/merkle](/p/demo/merkle) -- [/p/demo/bf](/p/demo/bf) -- [/p/demo/flow](/p/demo/flow) -- [/p/demo/gnode](/p/demo/gnode) -- [/p/demo/grc/grc20](/p/demo/grc/grc20) -- [/p/demo/grc/grc721](/p/demo/grc/grc721) -- ... - -
-
- ---- - -### Socials - -- Check out our [community projects](https://github.com/gnolang/awesome-gno). -- ![Discord](static/img/ico-discord.svg) [Discord](https://discord.gg/S8nKUqwkPn) -- ![Twitter](static/img/ico-twitter.svg) [Twitter](https://twitter.com/_gnoland) -- ![Youtube](static/img/ico-youtube.svg) [Youtube](https://www.youtube.com/@_gnoland) -- ![Telegram](static/img/ico-telegram.svg) [Telegram](https://t.me/gnoland) - -**This is a testnet.** -Package names are not guaranteed to be available for production. -` - -var adminAddr std.Address = std.Address("") - -func Render(_ string) string { - // highest level == highest responsibility - // teams are responsible for components they don't owne - // flag : realm maintainers VS facilitators - // teams - // committee of trustees to create the directory - // each directory is a name, has a parent and have groups - // homepage team - blocks aggregating events - - /*` - # Directory - - * gno.land (owned by group) - * - * gnovm - * gnolang (language) - * gnovm - - current challenges / concerns / issues - * tm2 - * amino - * - - ## Contributors - ``*/ - - // XXX: dynamic content: contributions - // XXX: - // XXX: community curated picks - // XXX: - body += "\n\n" + randomBanner() - - return body -} - -func randomBanner() string { - // not sure to keep this... - banners := []string{ - "Gno is for Truth.", - "Gno is for Social Coordination.", - "Gno is _not only_ for DeFi.", +
`), } - height := std.GetHeight() - idx := int(height) % len(banners) - return banners[idx] } diff --git a/examples/gno.land/r/gnoland/home/home_filetest.gno b/examples/gno.land/r/gnoland/home/home_filetest.gno index 43e831e79c6..9032277ae38 100644 --- a/examples/gno.land/r/gnoland/home/home_filetest.gno +++ b/examples/gno.land/r/gnoland/home/home_filetest.gno @@ -11,36 +11,85 @@ func main() { // // ### An interpretation of the Golang (Go) programming language for advanced developers and intrepid pioneers to build succinct, composable smart contracts for social coordination. // +// // If you’re concerned about information censorship and want to contribute to the #GnoWorldOrder, follow our socials to find out how. // +// // Gno.land is in building mode. If you want to help lay the foundations of a fairer and freer world through innovative ideas and exceptional code, join us today. // +//
+// +// ### WorxDAO +// +// - A +// - A1 +// - A1A +// - A1B +// - A2 +// - A3 +// - A3A +// - A3A1 +// - B +// - C +//
+// // ### Explore New Packages and Realms // -// - r/gnoland -// - [/r/gnoland/blog](/r/gnoland/blog) -// - [/r/gnoland/faucet](/r/gnoland/faucet) -// - r/system -// - [/r/system/names](/r/system/names) -// - [/r/system/rewards](/r/system/rewards) -// - [/r/system/validators](/r/system/validators) -// - r/demo -// - [/r/demo/banktest](/r/demo/banktest) -// - [/r/demo/boards](/r/demo/boards) -// - [/r/demo/foo20](/r/demo/foo20) -// - [/r/demo/nft](/r/demo/nft) -// - [/r/demo/types](/r/demo/types) -// - [/r/demo/users](/r/demo/users) -// - [/r/demo/groups](/r/demo/groups) -// - p/demo -// - [/p/demo/avl](/p/demo/avl) -// - [/p/demo/blog](/p/demo/blog) -// - [/p/demo/flow](/p/demo/flow) -// - [/p/demo/gnode](/p/demo/gnode) -// - [/p/demo/grc/exts](/p/demo/grc/exts) -// - [/p/demo/grc/grc20](/p/demo/grc/grc20) -// - [/p/demo/grc/grc721](/p/demo/grc/grc721) +//
+//
+// +// #### r/gnoland +// +// - [r/gnoland/blog](r/gnoland/blog) +// - [r/gnoland/dao](r/gnoland/dao) +// - [r/gnoland/faucet](r/gnoland/faucet) +// - [r/gnoland/home](r/gnoland/home) +// - [r/gnoland/pages](r/gnoland/pages) +// +// #### r/system +// +// - [r/system/names](r/system/names) +// - [r/system/rewards](r/system/rewards) +// - [r/system/validators](r/system/validators) +// +//
+//
+// +// #### r/demo +// +// - [r/demo/boards](r/demo/boards) +// - [r/demo/users](r/demo/users) +// - [r/demo/banktest](r/demo/banktest) +// - [r/demo/foo20](r/demo/foo20) +// - [r/demo/foo721](r/demo/foo721) +// - [r/demo/microblog](r/demo/microblog) +// - [r/demo/nft](r/demo/nft) +// - [r/demo/types](r/demo/types) +// - [r/demo/art](r/demo/art) +// - [r/demo/groups](r/demo/groups) +// - ... +// +//
+//
// +// #### p/demo +// +// - [p/demo/avl](p/demo/avl) +// - [p/demo/blog](p/demo/blog) +// - [p/demo/ui](p/demo/ui) +// - [p/demo/ufmt](p/demo/ufmt) +// - [p/demo/merkle](p/demo/merkle) +// - [p/demo/bf](p/demo/bf) +// - [p/demo/flow](p/demo/flow) +// - [p/demo/gnode](p/demo/gnode) +// - [p/demo/grc/grc20](p/demo/grc/grc20) +// - [p/demo/grc/grc721](p/demo/grc/grc721) +// - ... +// +//
+//
+// +//
// //
//
@@ -53,7 +102,7 @@ func main() { // - [Tokenomics (soon)](#) // - [Blog](/blog) // - [Events](/events) -// - [Partners (soon)](#) +// - [Partners, Fund, Grants](/partners) // //
// @@ -83,17 +132,32 @@ func main() { // //
//
+//
// -// --- +// +//
+//
// // ### Socials // -// - Check out our [community projects](https://github.com/gnolang/awesome-gno). +// - Check out our [community projects](https://github.com/gnolang/awesome-gno).) // - ![Discord](static/img/ico-discord.svg) [Discord](https://discord.gg/S8nKUqwkPn) // - ![Twitter](static/img/ico-twitter.svg) [Twitter](https://twitter.com/_gnoland) // - ![Youtube](static/img/ico-youtube.svg) [Youtube](https://www.youtube.com/@_gnoland) // - ![Telegram](static/img/ico-telegram.svg) [Telegram](https://t.me/gnoland) // +//
+//
+// +// ### Quote of the ~Day~Block#123 +// +// > Now, you Gno. +// +//
+//
+// +// +// --- +// // **This is a testnet.** // Package names are not guaranteed to be available for production. -// Gno is for Truth. From 5279477735c4e17788bbba73eb86197e5ad20220 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Wed, 18 Oct 2023 00:43:12 -0400 Subject: [PATCH 13/21] chore: temporary demo for miami 23 Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/manfred/present/admin.gno | 92 +++++++++++++++++++ examples/gno.land/r/manfred/present/gno.mod | 6 ++ .../r/manfred/present/present_miami23.gno | 13 +++ .../r/manfred/present/presentations.gno | 17 ++++ 4 files changed, 128 insertions(+) create mode 100644 examples/gno.land/r/manfred/present/admin.gno create mode 100644 examples/gno.land/r/manfred/present/gno.mod create mode 100644 examples/gno.land/r/manfred/present/present_miami23.gno create mode 100644 examples/gno.land/r/manfred/present/presentations.gno diff --git a/examples/gno.land/r/manfred/present/admin.gno b/examples/gno.land/r/manfred/present/admin.gno new file mode 100644 index 00000000000..ff0cb075656 --- /dev/null +++ b/examples/gno.land/r/manfred/present/admin.gno @@ -0,0 +1,92 @@ +package present + +import ( + "std" + "strings" + + "gno.land/p/demo/avl" +) + +var ( + adminAddr std.Address + moderatorList avl.Tree + inPause bool +) + +func init() { + // adminAddr = std.GetOrigCaller() // FIXME: find a way to use this from the main's genesis. + adminAddr = "g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq" +} + +func AdminSetAdminAddr(addr std.Address) { + assertIsAdmin() + adminAddr = addr +} + +func AdminSetInPause(state bool) { + assertIsAdmin() + inPause = state +} + +func AdminAddModerator(addr std.Address) { + assertIsAdmin() + moderatorList.Set(addr.String(), true) +} + +func AdminRemoveModerator(addr std.Address) { + assertIsAdmin() + moderatorList.Set(addr.String(), false) // XXX: delete instead? +} + +func ModAddPost(slug, title, body, tags string) { + assertIsModerator() + + caller := std.GetOrigCaller() + tagList := strings.Split(tags, ",") + err := b.NewPost(caller, slug, title, body, tagList) + checkErr(err) +} + +func ModEditPost(slug, title, body, tags string) { + assertIsModerator() + + tagList := strings.Split(tags, ",") + err := b.GetPost(slug).Update(title, body, tagList) + checkErr(err) +} + +func isAdmin(addr std.Address) bool { + return addr == adminAddr +} + +func isModerator(addr std.Address) bool { + _, found := moderatorList.Get(addr.String()) + return found +} + +func assertIsAdmin() { + caller := std.GetOrigCaller() + if !isAdmin(caller) { + panic("access restricted.") + } +} + +func assertIsModerator() { + caller := std.GetOrigCaller() + if isAdmin(caller) || isModerator(caller) { + return + } + panic("access restricted") +} + +func assertNotInPause() { + if inPause { + panic("access restricted (pause)") + } +} + +func checkErr(err error) { + if err != nil { + panic(err) + } +} diff --git a/examples/gno.land/r/manfred/present/gno.mod b/examples/gno.land/r/manfred/present/gno.mod new file mode 100644 index 00000000000..9d1ab5b0e56 --- /dev/null +++ b/examples/gno.land/r/manfred/present/gno.mod @@ -0,0 +1,6 @@ +module gno.land/r/manfred/present + +require ( + "gno.land/p/demo/avl" v0.0.0-latest + "gno.land/p/demo/blog" v0.0.0-latest +) diff --git a/examples/gno.land/r/manfred/present/present_miami23.gno b/examples/gno.land/r/manfred/present/present_miami23.gno new file mode 100644 index 00000000000..36a88b3d00f --- /dev/null +++ b/examples/gno.land/r/manfred/present/present_miami23.gno @@ -0,0 +1,13 @@ +package present + +func init() { + path := "miami23" + title := "Portal Loop Demo (Miami 2023)" + body := `# Portal Loop Demo (Miami 2023) + +- subject A +- subject B +- subject C +` + _ = b.NewPost("", path, title, body, nil) +} diff --git a/examples/gno.land/r/manfred/present/presentations.gno b/examples/gno.land/r/manfred/present/presentations.gno new file mode 100644 index 00000000000..8a99f502e86 --- /dev/null +++ b/examples/gno.land/r/manfred/present/presentations.gno @@ -0,0 +1,17 @@ +package present + +import ( + "gno.land/p/demo/blog" +) + +// TODO: switch from p/blog to p/present + +var b = &blog.Blog{ + Title: "Manfred's Presentations", + Prefix: "/r/manfred/present:", + NoBreadcrumb: true, +} + +func Render(path string) string { + return b.Render(path) +} From dd68415e064178b2e503c787f83eebdd0644fd08 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Wed, 18 Oct 2023 06:10:35 -0400 Subject: [PATCH 14/21] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- .../r/manfred/present/present_miami23.gno | 8 +++--- .../present/present_miami23_filetest.gno | 27 +++++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 examples/gno.land/r/manfred/present/present_miami23_filetest.gno diff --git a/examples/gno.land/r/manfred/present/present_miami23.gno b/examples/gno.land/r/manfred/present/present_miami23.gno index 36a88b3d00f..5b385052390 100644 --- a/examples/gno.land/r/manfred/present/present_miami23.gno +++ b/examples/gno.land/r/manfred/present/present_miami23.gno @@ -5,9 +5,9 @@ func init() { title := "Portal Loop Demo (Miami 2023)" body := `# Portal Loop Demo (Miami 2023) -- subject A -- subject B -- subject C +- roadmap +- portal loop +- screenshot github project ` - _ = b.NewPost("", path, title, body, nil) + _ = b.NewPost(adminAddr, path, title, body, []string{"demo", "portal-loop", "miami"}) } diff --git a/examples/gno.land/r/manfred/present/present_miami23_filetest.gno b/examples/gno.land/r/manfred/present/present_miami23_filetest.gno new file mode 100644 index 00000000000..0632eebdf89 --- /dev/null +++ b/examples/gno.land/r/manfred/present/present_miami23_filetest.gno @@ -0,0 +1,27 @@ +package main + +import "gno.land/r/manfred/present" + +func main() { + println(present.Render("")) + println("------------------------------------") + println(present.Render("p/miami23")) +} + +// Output: +//
+// +// ## [Portal Loop Demo (Miami 2023)](/r/manfred/present:p/miami23) +// **[Learn More](/r/manfred/present:p/miami23)** +// +//
+// ------------------------------------ +// # Portal Loop Demo (Miami 2023) +// +// - roadmap +// - portal loop +// - screenshot github project +// +// [#demo](/r/manfred/present:t/demo) [#portal-loop](/r/manfred/present:t/portal-loop) [#miami](/r/manfred/present:t/miami) +// +// by g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq on 1970-01-01 12:00am UTC From ecd93c17486a7aac6a9629ad2acada434d89837c Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Thu, 19 Oct 2023 09:54:22 -0400 Subject: [PATCH 15/21] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/gnoland/home/home.gno | 18 +++++---- .../r/manfred/present/present_miami23.gno | 39 +++++++++++++++++-- .../present/present_miami23_filetest.gno | 36 +++++++++++++++-- gno.land/cmd/gnoweb/main.go | 1 + 4 files changed, 79 insertions(+), 15 deletions(-) diff --git a/examples/gno.land/r/gnoland/home/home.gno b/examples/gno.land/r/gnoland/home/home.gno index c24e455a40d..303b44ed1e4 100644 --- a/examples/gno.land/r/gnoland/home/home.gno +++ b/examples/gno.land/r/gnoland/home/home.gno @@ -8,6 +8,7 @@ import ( "gno.land/p/demo/ui" ) +// XXX: p/demo/ui API is crappy, we need to make it more idiomatic // XXX: use an updatable block system to update content from a DAO // XXX: var blocks avl.Tree @@ -49,6 +50,7 @@ func introSection() ui.Element { func worxDAO() ui.Element { // WorxDAO + // XXX(manfred): please, let me finish a v0, then we can iterate // highest level == highest responsibility // teams are responsible for components they don't owne // flag : realm maintainers VS facilitators @@ -73,15 +75,15 @@ func worxDAO() ui.Element { ## Contributors ``*/ return ui.Element{ - ui.H3("WorxDAO"), + ui.H3("WorxDAO (WIP)"), ui.Text(`- A -- A1 -- A1A -- A1B -- A2 -- A3 -- A3A -- A3A1 + - A1 + - A1A + - A1B + - A2 + - A3 + - A3A + - A3A1 - B - C`), } diff --git a/examples/gno.land/r/manfred/present/present_miami23.gno b/examples/gno.land/r/manfred/present/present_miami23.gno index 5b385052390..36b1980bb0b 100644 --- a/examples/gno.land/r/manfred/present/present_miami23.gno +++ b/examples/gno.land/r/manfred/present/present_miami23.gno @@ -3,11 +3,42 @@ package present func init() { path := "miami23" title := "Portal Loop Demo (Miami 2023)" - body := `# Portal Loop Demo (Miami 2023) + body := ` +# Portal Loop Demo (Miami 2023) -- roadmap -- portal loop -- screenshot github project +Rendered by Gno. + +[Source (WIP)](https://github.com/gnolang/gno/pull/1176) + +## Portal Loop + +- DONE: Dynamic homepage, key pages, aliases, and redirects. +- TODO: Deploy with history, complete worxdao v0. +- Will replace the static gno.land site. +- Enhances local development. + +[GitHub Issue](https://github.com/gnolang/gno/issues/1108) + +## Roadmap + +- Crafting the roadmap this week, open to collaboration. +- Combining onchain (portal loop) and offchain (GitHub). +- Next week: Unveiling the official v0 roadmap. + +## Teams, DAOs, Projects + +- Developing worxDAO contracts for directories of projects and teams. +- GitHub teams and projects align with this structure. +- CODEOWNER file updates coming. +- Initial teams announced next week. + +## Tech Team Retreat Plan + +- Continue Portal Loop. +- Consider dApp development. +- Explore new topics [here](https://github.com/orgs/gnolang/projects/15/). +- Engage in workshops. +- Connect and have fun with colleagues. ` _ = b.NewPost(adminAddr, path, title, body, []string{"demo", "portal-loop", "miami"}) } diff --git a/examples/gno.land/r/manfred/present/present_miami23_filetest.gno b/examples/gno.land/r/manfred/present/present_miami23_filetest.gno index 0632eebdf89..05c41905060 100644 --- a/examples/gno.land/r/manfred/present/present_miami23_filetest.gno +++ b/examples/gno.land/r/manfred/present/present_miami23_filetest.gno @@ -18,9 +18,39 @@ func main() { // ------------------------------------ // # Portal Loop Demo (Miami 2023) // -// - roadmap -// - portal loop -// - screenshot github project +// Rendered by Gno. +// +// [Source (WIP)](https://github.com/gnolang/gno/pull/1176) +// +// ## Portal Loop +// +// - DONE: Dynamic homepage, key pages, aliases, and redirects. +// - TODO: Deploy with history, complete worxdao v0. +// - Will replace the static gno.land site. +// - Enhances local development. +// +// [GitHub Issue](https://github.com/gnolang/gno/issues/1108) +// +// ## Roadmap +// +// - Crafting the roadmap this week, open to collaboration. +// - Combining onchain (portal loop) and offchain (GitHub). +// - Next week: Unveiling the official v0 roadmap. +// +// ## Teams, DAOs, Projects +// +// - Developing worxDAO contracts for directories of projects and teams. +// - GitHub teams and projects align with this structure. +// - CODEOWNER file updates coming. +// - Initial teams announced next week. +// +// ## Tech Team Retreat Plan +// +// - Continue Portal Loop. +// - Consider dApp development. +// - Explore new topics [here](https://github.com/orgs/gnolang/projects/15/). +// - Engage in workshops. +// - Connect and have fun with colleagues. // // [#demo](/r/manfred/present:t/demo) [#portal-loop](/r/manfred/present:t/portal-loop) [#miami](/r/manfred/present:t/miami) // diff --git a/gno.land/cmd/gnoweb/main.go b/gno.land/cmd/gnoweb/main.go index 0d9398cb8e2..12a764c9fb2 100644 --- a/gno.land/cmd/gnoweb/main.go +++ b/gno.land/cmd/gnoweb/main.go @@ -260,6 +260,7 @@ func handlerRealmMain(app gotuna.App) http.Handler { writeError(w, err) return } + println(string(res.Data)) var fsigs vm.FunctionSignatures amino.MustUnmarshalJSON(res.Data, &fsigs) // Fill fsigs with query parameters. From 4e1782447a901097aa7cda30dfd1743ee40b8fd8 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Thu, 19 Oct 2023 10:36:06 -0400 Subject: [PATCH 16/21] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/p/demo/blog/blog.gno | 12 ++++++ examples/gno.land/r/gnoland/blog/gnoblog.gno | 4 ++ examples/gno.land/r/gnoland/home/gno.mod | 9 +++- examples/gno.land/r/gnoland/home/home.gno | 32 +++++++++++++++ .../gno.land/r/gnoland/home/home_filetest.gno | 41 +++++++++++++++---- 5 files changed, 89 insertions(+), 9 deletions(-) diff --git a/examples/gno.land/p/demo/blog/blog.gno b/examples/gno.land/p/demo/blog/blog.gno index 5f6db1dfa0f..1cf37b7ad3a 100644 --- a/examples/gno.land/p/demo/blog/blog.gno +++ b/examples/gno.land/p/demo/blog/blog.gno @@ -19,6 +19,18 @@ type Blog struct { NoBreadcrumb bool } +func (b Blog) RenderLastPostsWidget(limit int) string { + output := "" + i := 0 + b.Posts.Iterate("", "", func(key string, value interface{}) bool { + p := value.(*Post) + output += ufmt.Sprintf("- [%s](%s)\n", p.Title, p.URL()) + i++ + return i >= limit + }) + return output +} + func (b Blog) RenderHome(res *mux.ResponseWriter, req *mux.Request) { if !b.NoBreadcrumb { res.Write(breadcrumb([]string{b.Title})) diff --git a/examples/gno.land/r/gnoland/blog/gnoblog.gno b/examples/gno.land/r/gnoland/blog/gnoblog.gno index 2982ea88489..cad84507614 100644 --- a/examples/gno.land/r/gnoland/blog/gnoblog.gno +++ b/examples/gno.land/r/gnoland/blog/gnoblog.gno @@ -23,3 +23,7 @@ func AddComment(postSlug, comment string) { func Render(path string) string { return b.Render(path) } + +func RenderLastPostsWidget(limit int) string { + return b.RenderLastPostsWidget(limit) +} diff --git a/examples/gno.land/r/gnoland/home/gno.mod b/examples/gno.land/r/gnoland/home/gno.mod index a943194ae5d..9192b4364d0 100644 --- a/examples/gno.land/r/gnoland/home/gno.mod +++ b/examples/gno.land/r/gnoland/home/gno.mod @@ -1 +1,8 @@ -module gno.land/r/gnoland/home \ No newline at end of file +module gno.land/r/gnoland/home + +require ( + "gno.land/r/gnoland/blog" v0.0.0-latest + "gno.land/p/demo/ufmt" v0.0.0-latest + "gno.land/p/demo/avl" v0.0.0-latest + "gno.land/p/demo/ui" v0.0.0-latest +) diff --git a/examples/gno.land/r/gnoland/home/home.gno b/examples/gno.land/r/gnoland/home/home.gno index 303b44ed1e4..953fb6d4c2d 100644 --- a/examples/gno.land/r/gnoland/home/home.gno +++ b/examples/gno.land/r/gnoland/home/home.gno @@ -6,6 +6,7 @@ import ( "gno.land/p/demo/avl" "gno.land/p/demo/ufmt" "gno.land/p/demo/ui" + blog "gno.land/r/gnoland/blog" ) // XXX: p/demo/ui API is crappy, we need to make it more idiomatic @@ -20,6 +21,14 @@ func Render(_ string) string { dom.Body.Append(introSection()...) dom.Body.Append(ui.Jumbotron(worxDAO()...)) dom.Body.Append(packageStaffPicks()...) + dom.Body.Append(ui.HR{}) + dom.Body.Append( + ui.Columns{3, []ui.Element{ + lastBlogposts(4), + upcomingEvents(4), + lastContributions(4), + }}, + ) dom.Body.Append(ui.Jumbotron(discoverLinks()...)) // footer @@ -40,6 +49,29 @@ func Render(_ string) string { return dom.String() } +func lastBlogposts(limit int) ui.Element { + posts := blog.RenderLastPostsWidget(limit) + return ui.Element{ + ui.H3("Last Blogposts"), + ui.Text(posts), + } +} + +func lastContributions(limit int) ui.Element { + return ui.Element{ + ui.H3("Last Contributions"), + ui.Text("TODO: import r/gh"), + ui.Link{Text: "#1134", URL: "https://github.com/gnolang/gno/pull/1134"}, + } +} + +func upcomingEvents(limit int) ui.Element { + return ui.Element{ + ui.H3("Upcoming Events"), + ui.Text("TODO: import r/gnoland/events"), + } +} + func introSection() ui.Element { return ui.Element{ ui.H3("An interpretation of the Golang (Go) programming language for advanced developers and intrepid pioneers to build succinct, composable smart contracts for social coordination."), diff --git a/examples/gno.land/r/gnoland/home/home_filetest.gno b/examples/gno.land/r/gnoland/home/home_filetest.gno index 9032277ae38..0b92c419c6d 100644 --- a/examples/gno.land/r/gnoland/home/home_filetest.gno +++ b/examples/gno.land/r/gnoland/home/home_filetest.gno @@ -19,16 +19,16 @@ func main() { // //
// -// ### WorxDAO +// ### WorxDAO (WIP) // // - A -// - A1 -// - A1A -// - A1B -// - A2 -// - A3 -// - A3A -// - A3A1 +// - A1 +// - A1A +// - A1B +// - A2 +// - A3 +// - A3A +// - A3A1 // - B // - C //
@@ -89,6 +89,31 @@ func main() { // // // +// +// --- +// +//
+//
+// +// ### Last Blogposts +// +// +//
+//
+// +// ### Upcoming Events +// +// TODO: import r/gnoland/events +//
+//
+// +// ### Last Contributions +// +// TODO: import r/gh +// [#1134](https://github.com/gnolang/gno/pull/1134) +//
+//
+// //
// //
From f278ecfa33c877b6c40a9889d340e51fab90e35b Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Thu, 19 Oct 2023 10:37:38 -0400 Subject: [PATCH 17/21] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/gnoland/home/home.gno | 2 +- examples/gno.land/r/gnoland/home/home_filetest.gno | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/gno.land/r/gnoland/home/home.gno b/examples/gno.land/r/gnoland/home/home.gno index 953fb6d4c2d..959349f125e 100644 --- a/examples/gno.land/r/gnoland/home/home.gno +++ b/examples/gno.land/r/gnoland/home/home.gno @@ -144,7 +144,7 @@ func socialLinks() ui.Element { ui.H3("Socials"), ui.BulletList{ // XXX: improve UI to support a nice GO api for such links - ui.Text("Check out our [community projects](https://github.com/gnolang/awesome-gno).)"), + ui.Text("Check out our [community projects](https://github.com/gnolang/awesome-gno)"), ui.Text("![Discord](static/img/ico-discord.svg) [Discord](https://discord.gg/S8nKUqwkPn)"), ui.Text("![Twitter](static/img/ico-twitter.svg) [Twitter](https://twitter.com/_gnoland)"), ui.Text("![Youtube](static/img/ico-youtube.svg) [Youtube](https://www.youtube.com/@_gnoland)"), diff --git a/examples/gno.land/r/gnoland/home/home_filetest.gno b/examples/gno.land/r/gnoland/home/home_filetest.gno index 0b92c419c6d..1fffc11792f 100644 --- a/examples/gno.land/r/gnoland/home/home_filetest.gno +++ b/examples/gno.land/r/gnoland/home/home_filetest.gno @@ -165,7 +165,7 @@ func main() { // // ### Socials // -// - Check out our [community projects](https://github.com/gnolang/awesome-gno).) +// - Check out our [community projects](https://github.com/gnolang/awesome-gno) // - ![Discord](static/img/ico-discord.svg) [Discord](https://discord.gg/S8nKUqwkPn) // - ![Twitter](static/img/ico-twitter.svg) [Twitter](https://twitter.com/_gnoland) // - ![Youtube](static/img/ico-youtube.svg) [Youtube](https://www.youtube.com/@_gnoland) From 7a71ab282963f5ab9b3f90f9f13913c738b7844d Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Thu, 19 Oct 2023 10:56:00 -0400 Subject: [PATCH 18/21] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/p/demo/ui/ui.gno | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gno.land/p/demo/ui/ui.gno b/examples/gno.land/p/demo/ui/ui.gno index 59e9403a025..d737ae47ddc 100644 --- a/examples/gno.land/p/demo/ui/ui.gno +++ b/examples/gno.land/p/demo/ui/ui.gno @@ -93,7 +93,7 @@ func (b *Breadcrumb) Append(elems ...DomStringer) { func (b Breadcrumb) String(dom DOM) string { output := "" - for idx, entry := range b { + for _, entry := range b { if idx > 0 { output += " / " } From 016d2a450f0f6726cce4a7d78927e1fdec1cdecf Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Thu, 19 Oct 2023 11:34:37 -0400 Subject: [PATCH 19/21] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/p/demo/ui/ui.gno | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/gno.land/p/demo/ui/ui.gno b/examples/gno.land/p/demo/ui/ui.gno index d737ae47ddc..dd21d0510eb 100644 --- a/examples/gno.land/p/demo/ui/ui.gno +++ b/examples/gno.land/p/demo/ui/ui.gno @@ -93,7 +93,7 @@ func (b *Breadcrumb) Append(elems ...DomStringer) { func (b Breadcrumb) String(dom DOM) string { output := "" - for _, entry := range b { + for idx, entry := range b { if idx > 0 { output += " / " } @@ -113,7 +113,7 @@ func (c *Columns) Append(elems ...Element) { func (c Columns) String(dom DOM) string { output := `
` + "\n" - for idx, entry := range c.Columns { + for _, entry := range c.Columns { output += `
` + "\n\n" output += entry.String(dom) output += "
\n" From 2acc75eb82aa4fc31ca1a16abafd13ad09a456f4 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Thu, 19 Oct 2023 14:53:46 -0400 Subject: [PATCH 20/21] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/gnoland/home/home.gno | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/gno.land/r/gnoland/home/home.gno b/examples/gno.land/r/gnoland/home/home.gno index 959349f125e..5f2a5b9c4b5 100644 --- a/examples/gno.land/r/gnoland/home/home.gno +++ b/examples/gno.land/r/gnoland/home/home.gno @@ -3,7 +3,6 @@ package home import ( "std" - "gno.land/p/demo/avl" "gno.land/p/demo/ufmt" "gno.land/p/demo/ui" blog "gno.land/r/gnoland/blog" @@ -19,7 +18,7 @@ func Render(_ string) string { // body dom.Body.Append(introSection()...) - dom.Body.Append(ui.Jumbotron(worxDAO()...)) + dom.Body.Append(ui.Jumbotron(worxDAO())) dom.Body.Append(packageStaffPicks()...) dom.Body.Append(ui.HR{}) dom.Body.Append( @@ -29,7 +28,7 @@ func Render(_ string) string { lastContributions(4), }}, ) - dom.Body.Append(ui.Jumbotron(discoverLinks()...)) + dom.Body.Append(ui.Jumbotron(discoverLinks())) // footer dom.Footer.Append( From 4f173004e8de28098b4bb029caa7d4add02003b2 Mon Sep 17 00:00:00 2001 From: Manfred Touron <94029+moul@users.noreply.github.com> Date: Thu, 19 Oct 2023 22:31:19 -0400 Subject: [PATCH 21/21] Update gno.land/cmd/gnoweb/main.go --- gno.land/cmd/gnoweb/main.go | 1 - 1 file changed, 1 deletion(-) diff --git a/gno.land/cmd/gnoweb/main.go b/gno.land/cmd/gnoweb/main.go index 12a764c9fb2..0d9398cb8e2 100644 --- a/gno.land/cmd/gnoweb/main.go +++ b/gno.land/cmd/gnoweb/main.go @@ -260,7 +260,6 @@ func handlerRealmMain(app gotuna.App) http.Handler { writeError(w, err) return } - println(string(res.Data)) var fsigs vm.FunctionSignatures amino.MustUnmarshalJSON(res.Data, &fsigs) // Fill fsigs with query parameters.