From c199cc85f2d34b749cbd2bec166be17b68cef658 Mon Sep 17 00:00:00 2001 From: Guilhem Fanton <8671905+gfanton@users.noreply.github.com> Date: Mon, 15 Jul 2024 17:22:13 +0200 Subject: [PATCH] feat: add gfanton nebular 2024 (#57) Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- .../.gitattributes | 2 + .../2024-07-13--nebular--gfanton/.gitignore | 1 + .../2024-07-13--nebular--gfanton/.gitpod.yml | 38 ++++++ .../01_gno/README.md | 29 +++++ .../01_gno/gno.mod | 1 + .../01_gno/main.gno | 10 ++ .../01_gno/sum_test.gno | 12 ++ .../02_gnodev/README.md | 33 ++++++ .../02_gnodev/gno.mod | 1 + .../02_gnodev/render.gno | 33 ++++++ .../03_gnokey/README.md | 58 ++++++++++ .../03_gnokey/counter.gno | 21 ++++ .../03_gnokey/gno.mod | 1 + .../04_gnoland/README.md | 55 +++++++++ .../04_gnoland/gno.mod | 1 + .../04_gnoland/guess_book.gno | 109 ++++++++++++++++++ .../05_build_your_app/README.md | 7 ++ .../2024-07-13--nebular--gfanton/Makefile | 31 +++++ .../2024-07-13--nebular--gfanton/README.md | 34 ++++++ 19 files changed, 477 insertions(+) create mode 100644 presentations/2024-07-13--nebular--gfanton/.gitattributes create mode 100644 presentations/2024-07-13--nebular--gfanton/.gitignore create mode 100644 presentations/2024-07-13--nebular--gfanton/.gitpod.yml create mode 100644 presentations/2024-07-13--nebular--gfanton/01_gno/README.md create mode 100644 presentations/2024-07-13--nebular--gfanton/01_gno/gno.mod create mode 100644 presentations/2024-07-13--nebular--gfanton/01_gno/main.gno create mode 100644 presentations/2024-07-13--nebular--gfanton/01_gno/sum_test.gno create mode 100644 presentations/2024-07-13--nebular--gfanton/02_gnodev/README.md create mode 100644 presentations/2024-07-13--nebular--gfanton/02_gnodev/gno.mod create mode 100644 presentations/2024-07-13--nebular--gfanton/02_gnodev/render.gno create mode 100644 presentations/2024-07-13--nebular--gfanton/03_gnokey/README.md create mode 100644 presentations/2024-07-13--nebular--gfanton/03_gnokey/counter.gno create mode 100644 presentations/2024-07-13--nebular--gfanton/03_gnokey/gno.mod create mode 100644 presentations/2024-07-13--nebular--gfanton/04_gnoland/README.md create mode 100644 presentations/2024-07-13--nebular--gfanton/04_gnoland/gno.mod create mode 100644 presentations/2024-07-13--nebular--gfanton/04_gnoland/guess_book.gno create mode 100644 presentations/2024-07-13--nebular--gfanton/05_build_your_app/README.md create mode 100644 presentations/2024-07-13--nebular--gfanton/Makefile create mode 100644 presentations/2024-07-13--nebular--gfanton/README.md diff --git a/presentations/2024-07-13--nebular--gfanton/.gitattributes b/presentations/2024-07-13--nebular--gfanton/.gitattributes new file mode 100644 index 0000000..f0172d1 --- /dev/null +++ b/presentations/2024-07-13--nebular--gfanton/.gitattributes @@ -0,0 +1,2 @@ +*.gno linguist-language=Go + diff --git a/presentations/2024-07-13--nebular--gfanton/.gitignore b/presentations/2024-07-13--nebular--gfanton/.gitignore new file mode 100644 index 0000000..ff62145 --- /dev/null +++ b/presentations/2024-07-13--nebular--gfanton/.gitignore @@ -0,0 +1 @@ +gno/ \ No newline at end of file diff --git a/presentations/2024-07-13--nebular--gfanton/.gitpod.yml b/presentations/2024-07-13--nebular--gfanton/.gitpod.yml new file mode 100644 index 0000000..43eaee8 --- /dev/null +++ b/presentations/2024-07-13--nebular--gfanton/.gitpod.yml @@ -0,0 +1,38 @@ +# http://gitpod.io/#github.com/gnolang/getting-started-workshop + +additionalRepositories: + - url: https://github.com/gfanton/gno + checkoutLocation: gno + +tasks: + - name: Gno Deps + env: + GNO_ROOT: '../gno' + before: echo "alias gnodev='gnodev -web-remote=$(gp url 8888)'" >> $HOME/.bashrc + init: make deps + command: source $HOME/.bashrc + +ports: + - name: gnoweb + description: "the Gno.land web server" + port: 8888 + onOpen: open-preview + + - name: "gnodev RPC" + description: "the RPC server, managed by tendermint2" + port: 26657 + onOpen: ignore + +github: + prebuilds: + master: true + branches: true + pullRequests: true + pullRequestsFromForks: true + addCheck: true + addComment: true + addBadge: true + +vscode: + extensions: + - harry-hov.gno diff --git a/presentations/2024-07-13--nebular--gfanton/01_gno/README.md b/presentations/2024-07-13--nebular--gfanton/01_gno/README.md new file mode 100644 index 0000000..1b0f68c --- /dev/null +++ b/presentations/2024-07-13--nebular--gfanton/01_gno/README.md @@ -0,0 +1,29 @@ +## 01_Gno - Go, little brother + +In this section, you will learn to use the `gno` CLI to run and test Gno packages. This part does not rely on a blockchain; instead, it operates solely on the GnoVM. + +### Package + +A GNO package is generally composed of: + +* a `gno.mod` file that describes the package and its dependencies +* some `*.gno` files (and optionally some `*_test.gno` files for testing) +* an optional `README.md` + +Explore the different files in the current package (in the same folder as this README). + +### Run Gno Package +To execute your package, run the following command from the directory containing the package: + +```bash +$ gno run . +``` + +This command runs the `main()` function in the `main.gno` file, which serves as the entry point of the package. + +### Testing Gno Packages +Run tests using the `gno test .` command. This command executes all functions prefixed with `Test` in files that are suffixed with `_test.gno`. + +```bash +$ gno test . +``` diff --git a/presentations/2024-07-13--nebular--gfanton/01_gno/gno.mod b/presentations/2024-07-13--nebular--gfanton/01_gno/gno.mod new file mode 100644 index 0000000..b4f664c --- /dev/null +++ b/presentations/2024-07-13--nebular--gfanton/01_gno/gno.mod @@ -0,0 +1 @@ +module gno.land/r/nebular24/gno \ No newline at end of file diff --git a/presentations/2024-07-13--nebular--gfanton/01_gno/main.gno b/presentations/2024-07-13--nebular--gfanton/01_gno/main.gno new file mode 100644 index 0000000..d374dc7 --- /dev/null +++ b/presentations/2024-07-13--nebular--gfanton/01_gno/main.gno @@ -0,0 +1,10 @@ +package main + +func Sum(a int, b int) int { + return a + b +} + +func main() { + val := Sum(2, 3) + println("sum of value:", val) +} diff --git a/presentations/2024-07-13--nebular--gfanton/01_gno/sum_test.gno b/presentations/2024-07-13--nebular--gfanton/01_gno/sum_test.gno new file mode 100644 index 0000000..255db5c --- /dev/null +++ b/presentations/2024-07-13--nebular--gfanton/01_gno/sum_test.gno @@ -0,0 +1,12 @@ +package main + +import "testing" + +func TestSum(t *testing.T) { + const expected = 3 + + actual := Sum(1, 2) + if actual != expected { + t.Fatalf("invalid result, expecting %d got %d", expected, actual) + } +} diff --git a/presentations/2024-07-13--nebular--gfanton/02_gnodev/README.md b/presentations/2024-07-13--nebular--gfanton/02_gnodev/README.md new file mode 100644 index 0000000..3c02885 --- /dev/null +++ b/presentations/2024-07-13--nebular--gfanton/02_gnodev/README.md @@ -0,0 +1,33 @@ +## 02_Gnodev - Debuging and Rendering + +`gnodev` is a Gno development tool to works on the Gno package. It embeds a fully functional `gnoland` node (blockchain), along with `gnoweb`, a web server used to explore and visualize the `gnoland` realm. + +By watching your development directory, `gnodev` detects changes in your Gno code and reflects them in the state of the node immediately. `gnodev` also runs a local instance of `gnoweb`, allowing you to see the rendering of your Gno code instantly. + +### Start gnodev + +To start `gnodev` on a given package, simply use the command `gnodev `. + +To start gnodev with the package located in this folder, use: +```bash +$ gnodev ./02_gnodev +``` + +> You can exit `gnodev` at any time using `Ctrl+C`. + +### Gnoweb + +`gnodev` will automatically serve `gnoweb` (by default on `:8888`). + +> In this demo, if you are using gitpod, a browser tab will open on `gnoweb` when running `gnodev` + +- On a local machine you should be able to accesse `gnoweb` in your browser with http://localhost:8888. +- If you are using gitpod, you can retreive `gnoweb` url by typing `gp url 8888` in your terminal session + +### Access Your Realm + +You can then access your realm by reaching `http:///` url. + +So for the realm (package) located in the same directory as this `README`, it will be: +- `http://localhost:8888/r/nebular24/gnodev` in case of gnodev running locally on your machine +- `$(gp url 8888)/r/nubular24/gnodev` in case of gnodev running on gitpod diff --git a/presentations/2024-07-13--nebular--gfanton/02_gnodev/gno.mod b/presentations/2024-07-13--nebular--gfanton/02_gnodev/gno.mod new file mode 100644 index 0000000..6137552 --- /dev/null +++ b/presentations/2024-07-13--nebular--gfanton/02_gnodev/gno.mod @@ -0,0 +1 @@ +module gno.land/r/nebular24/gnodev \ No newline at end of file diff --git a/presentations/2024-07-13--nebular--gfanton/02_gnodev/render.gno b/presentations/2024-07-13--nebular--gfanton/02_gnodev/render.gno new file mode 100644 index 0000000..dbeb0b1 --- /dev/null +++ b/presentations/2024-07-13--nebular--gfanton/02_gnodev/render.gno @@ -0,0 +1,33 @@ +package render + +var bodyPage = ` +# My Gno Realm + +### Realms in short: + +* Smart contracts in Gno. +* Realms are stateful. +* Realms can own assets (tokens). +* Realms can implement ` + "`" + `Render(path string) string` + "`" + ` + to simplify dapp frontend development by allowing users to request + markdown renderings from validators and full nodes without a transaction. + +### Path + +The Render function takes a path argument that can impact its behavior. In +'gnoweb', this argument can be passed by adding ` + "`" + `:` + "`" + ` after the URL. + +*Try it, go to [/r/nebular24/gnodev:page-2](/r/nebular24/gnodev:page-2)* + +` + +func Render(path string) string { + view := bodyPage + + if path != "" { + view += "---\n" + view += "### " + path + "\n" + } + + return view +} diff --git a/presentations/2024-07-13--nebular--gfanton/03_gnokey/README.md b/presentations/2024-07-13--nebular--gfanton/03_gnokey/README.md new file mode 100644 index 0000000..3609ac8 --- /dev/null +++ b/presentations/2024-07-13--nebular--gfanton/03_gnokey/README.md @@ -0,0 +1,58 @@ +## Bring Your Realm to Life with Gnokey + +`gnokey` is a command-line tool for interacting with a blockchain node. It allows you to make blockchain transactions, publish new packages, and perform various operations with a remote or local blockchain node. + +### Create an Account + +To create an account, simply type: + +``` +$ gnokey add mykeyname +``` +__Replace `mykeyname` with the desired name for your key.__ + +You will be prompted to enter a password to secure your key. It is strongly recommended to use a password, as using the key without one is not advisable outside of this workshop. + +You can then verify that your key has been correctly added to the keybase by typing: + +``` +$ gnokey list +``` + +This should correctly display your newly created key. + +### Start gnodev + +As in the previous exercise, start `gnodev` target this directory by typing + +``` +$ gnodev ./03_gnokey +``` + +To load the `counter` package on `gno.land/r/nebular24/gnokey` + +`gnodev` should automatically load the key you just created. You can verify this +by pressing `A` within `gnodev` to display all known accounts and their +balances. + +In `gnodev`, your account should have been premined with enough tokens +to do whatever you want. + +### Interact with the contract + +You can then interact with the realm using the `maketx call` command from gnokey + +``` +$ gnokey maketx call \ + -pkgpath "gno.land/r/nebular24/gnokey" \ + -func "Inc" \ + -gas-fee 1ugnot \ + -gas-wanted 2000000 \ + -broadcast \ + -chainid "dev" \ + -remote "127.0.0.1:26657" mykeyname +``` +__Replace `mykeyname` with your key.__ + + + diff --git a/presentations/2024-07-13--nebular--gfanton/03_gnokey/counter.gno b/presentations/2024-07-13--nebular--gfanton/03_gnokey/counter.gno new file mode 100644 index 0000000..3ac5bcb --- /dev/null +++ b/presentations/2024-07-13--nebular--gfanton/03_gnokey/counter.gno @@ -0,0 +1,21 @@ +package counter + +import ( + "strconv" +) + +var count int + +func Inc() { + count += 1 +} + +func Add(value int) { + count += value +} + +func Render(path string) string { + view := "# My Super Counter \n" + view += "* my counter is: " + strconv.Itoa(count) + return view +} diff --git a/presentations/2024-07-13--nebular--gfanton/03_gnokey/gno.mod b/presentations/2024-07-13--nebular--gfanton/03_gnokey/gno.mod new file mode 100644 index 0000000..77a7ec7 --- /dev/null +++ b/presentations/2024-07-13--nebular--gfanton/03_gnokey/gno.mod @@ -0,0 +1 @@ +module gno.land/r/nebular24/gnokey \ No newline at end of file diff --git a/presentations/2024-07-13--nebular--gfanton/04_gnoland/README.md b/presentations/2024-07-13--nebular--gfanton/04_gnoland/README.md new file mode 100644 index 0000000..6776af8 --- /dev/null +++ b/presentations/2024-07-13--nebular--gfanton/04_gnoland/README.md @@ -0,0 +1,55 @@ +## 04_GnoLand - Publish Your Realm on Gno.Land + +`Gno.Land` is the platform where you can upload your contract and make it available to the world, on-chain. When publishing on `Gno.Land`, there is no rollback or hot reload. Your contract will remain there permanently, so be cautious when choosing the package path to publish your realm. + +### Faucet Hub + +Unlike `gnodev`, you don't have any tokens to interact with the chain (yet). Let's get some for your key on the `Faucet Hub`. + +1. Go to https://faucet.gno.land and select `Portal Loop`. +2. Enter the wallet address you created in the previous section (use `gnokey list` to retrieve the key address). +3. Select the faucet amount and click on `Request Drip`. + +Your address should now have received some tokens! + +You can verify your current balance by running: +```bash +$ gnokey query --remote https://rpc.gno.land bank/balances/ +``` +> wallet address should be in the form `g1xxxx...` + +This command should display the current amount of `ugnot` you possess in your wallet. + +### Publish + +Now, it's time to upload your first package. We'll upload the package inside `04_gnoland`. + +1. Choose a package path name. It's recommended to use your address as the namespace for your contract: + * Example: `gno.land/r/g1hr3dl82edy84a5f3dmchh0due7zgwm5rnns6na/myrealm` +2. Run the following command to publish the package on `gno.land`: +```bash +$ gnokey maketx addpkg "" \ + -pkgpath "" \ + -pkgdir "" \ + -gas-fee 1ugnot \ + -gas-wanted 10000000 \ + -broadcast \ + -chainid portal-loop \ + -remote https://rpc.gno.land + +# * `MY_KEY_NAME`: the name of your key used in the gnokey section; use `gnokey list` to retrieve it. +# * `LOCAL_PKG_DIR`: the local directory containing the realm (package) you want to publish. +# * `PKG_PATH_NAME`: the package path name you chose in step 1. +# * You will be prompted for your key password. +``` +3. Visit your realm on `gno.land` using the package path you chose in step 1. + * Example: `https://gno.land/r/g1hr3dl82edy84a5f3dmchh0due7zgwm5rnns6na/myrealm` + +### BONUS: Gno Bro + +There are many ways to explore realms. Try running: +```bash +$ ssh bro.gno.cool +``` + +This will bring you to a terminal-based version of `gno.land`, where you can fetch the previously published realm by typing its path. Enjoy the magic! diff --git a/presentations/2024-07-13--nebular--gfanton/04_gnoland/gno.mod b/presentations/2024-07-13--nebular--gfanton/04_gnoland/gno.mod new file mode 100644 index 0000000..80358c3 --- /dev/null +++ b/presentations/2024-07-13--nebular--gfanton/04_gnoland/gno.mod @@ -0,0 +1 @@ +module gno.land/r/nebular24/guessbook diff --git a/presentations/2024-07-13--nebular--gfanton/04_gnoland/guess_book.gno b/presentations/2024-07-13--nebular--gfanton/04_gnoland/guess_book.gno new file mode 100644 index 0000000..940e8b0 --- /dev/null +++ b/presentations/2024-07-13--nebular--gfanton/04_gnoland/guess_book.gno @@ -0,0 +1,109 @@ +package guessbook + +import ( + "std" + "strconv" + "strings" + "time" + + "gno.land/p/demo/avl" +) + +type Message struct { + Content string + Author string + Date time.Time +} + +var ( + messages []Message + users avl.Tree // std.Address -> true +) + +func AddMessage(message string) { + std.AssertOriginCall() + + caller := std.GetOrigCaller().String() + + if _, ok := users.Get(caller); ok { + panic("caller have alreay register a message") + } + + users.Set(caller, true) + messages = append(messages, Message{ + Author: caller, + Content: message, + Date: time.Now(), + }) +} + +func renderMessages(msgs []Message) string { + var str strings.Builder + + for i, msg := range msgs { + if i > 0 { + str.WriteString("---") + } + + str.WriteString(renderMessage(msg)) + str.WriteRune('\n') + } + + return str.String() +} + +func renderMessage(msg Message) string { + var str strings.Builder + + str.WriteRune('\n') + str.WriteString("#### Writen By " + msg.Author + + " on " + msg.Date.Format("02 Jan 2006")) + str.WriteRune('\n') + str.WriteString(msg.Content) + str.WriteRune('\n') + + return str.String() +} + +func Render(path string) string { + const messagePerPage = 5 + + if len(messages) == 0 { + return "no messages yet :(" + } + + page := 0 + if path != "" { + var err error + page, err = strconv.Atoi(path) + if err != nil { + panic("unable get page number from path") + } + + if page < 1 || (page*messagePerPage) > len(messages) { + panic("invalid page number") + } + + page-- + } + + startpage := page * messagePerPage + endPage := min(startpage+messagePerPage, len(messages)) + mshow := messages[startpage:endPage] + + var view strings.Builder + view.WriteString(renderMessages(mshow)) + view.WriteRune('\n') + view.WriteString("---") + view.WriteRune('\n') + + return view.String() +} + +func min(a, b int) int { + if a < b { + return a + } + + return b +} diff --git a/presentations/2024-07-13--nebular--gfanton/05_build_your_app/README.md b/presentations/2024-07-13--nebular--gfanton/05_build_your_app/README.md new file mode 100644 index 0000000..1be8029 --- /dev/null +++ b/presentations/2024-07-13--nebular--gfanton/05_build_your_app/README.md @@ -0,0 +1,7 @@ +# Build Your Own App + +Lets build your own app ! + +some ideas: tic-tac-toe, token, voting system, blog, ... + +You have plenty of example to get some inspiration. diff --git a/presentations/2024-07-13--nebular--gfanton/Makefile b/presentations/2024-07-13--nebular--gfanton/Makefile new file mode 100644 index 0000000..4198b31 --- /dev/null +++ b/presentations/2024-07-13--nebular--gfanton/Makefile @@ -0,0 +1,31 @@ +# gno +GNO_COMMIT ?= feat/ws/webremote +GNO_ROOT ?= gno +GNO_REPO ?= github.com/gnolang/gno + +git_gno := git -C $(GNO_ROOT) + +all: deps + +deps: $(GNO_ROOT) checkout _deps +_deps: +# install gno dev deps + $(MAKE) -C $(GNO_ROOT)/misc/devdeps install +# install gno + $(MAKE) -C $(GNO_ROOT) install + +checkout: + $(git_gno) cat-file -e $(GNO_COMMIT) || $(git_gno) fetch + $(git_gno) checkout $(GNO_COMMIT) && $(git_gno) pull + +update: $(GNO_ROOT) + $(git_gno) pull --rebase + +cleanup: + rm -rf $(GNO_ROOT) + +.PHONY: update deps checkout + +$(GNO_ROOT): + git clone https://$(GNO_REPO) $@ + diff --git a/presentations/2024-07-13--nebular--gfanton/README.md b/presentations/2024-07-13--nebular--gfanton/README.md new file mode 100644 index 0000000..fff6b3f --- /dev/null +++ b/presentations/2024-07-13--nebular--gfanton/README.md @@ -0,0 +1,34 @@ +# Nebular Workshop + +Welcome to my Nebular 2024 Workshop! + +This workshop will teach you the basics of creating, debugging, and deploying smart contracts on Gno.Land. You'll explore the Gnolang and Gnoland ecosystem tools: `gno`, `gnodev`, and `gnokey`. By the end, you'll deploy your first smart contract on Gno.Land. + +This is the local development experience. There are other ways to develop on Gno. Check out [Gno Play](https://play.gno.land). + +### How To Play With This Workshop: + +#### GitPod (recommended) +Use GitPod, a remote machine with an editor and all necessary tools pre-installed. +[![Open in GitPod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/gfanton/workshop-nebular) + +#### Locally +You will need [Golang](https://go.dev/doc/install) installed and set up. Then clone this repo and run `make deps` to install the necessary dependencies. It will: +- Clone a forked version of GNO (necessary to work with GitPod) +- Install the necessary tools: `gno`, `gnodev`, `gnoland` + +## 01_Gnolang + +This section focuses on `gno`, the CLI tool companion for Gnolang, the integrated Go language. There is no blockchain involved in this part. + +## 02_Gnodev + +This section focuses on `gnodev`, the Gno development tool for working on Gno packages. It includes a `gnoland` blockchain and `gnoweb`, a web application to help you visualize your contract. + +## 03_Gnokey + +This section focuses on `gnokey`, the Gno development tool for interacting with the chain. + +## 04_Gno.Land + +This section focuses on publishing a contract on `gno.land`.