Skip to content

Commit

Permalink
docs: update How-to section with Playground (#1766)
Browse files Browse the repository at this point in the history
## Description

This PR updates all tutorials in the How-to section of the docs to lead
and primarily use the Playground as the number one option to write Gno
code.

I also fixed minor issues and updated outdated code along the way.

For all of the snippets of code shared via the Playground links, there
is a unique comment at the bottom of the code, such as `// How to:
Deploy using Gno Playground`, so that deployments can be traceable via
metrics.

This PR also removes the GRC721 guide because GRC721 needs refactoring
and is not very usable right now.

Latest preview of the docs:
#1766 (comment)

cc @ilgooz @salmad3 

<details><summary>Contributors' checklist...</summary>

- [x] Added new tests, or not needed, or not feasible
- [x] Provided an example (e.g. screenshot) to aid review or the PR is
self-explanatory
- [x] Updated the official documentation or not needed
- [x] No breaking changes were made, or a `BREAKING CHANGE: xxx` message
was included in the description
- [x] Added references to related issues and PRs
- [x] Provided any useful hints for running manual tests
- [ ] Added new benchmarks to [generated
graphs](https://gnoland.github.io/benchmarks), if any. More info
[here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md).
</details>

---------

Co-authored-by: Danny <salman.danny03@hotmail.com>
  • Loading branch information
leohhhn and salmad3 authored Apr 8, 2024
1 parent 1321476 commit 69811ff
Show file tree
Hide file tree
Showing 21 changed files with 539 additions and 260 deletions.
20 changes: 12 additions & 8 deletions docs/assets/how-to-guides/creating-grc20/mytoken-1.gno
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
package mytoken

import (
"std"
"strings"

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

var (
mytoken *grc20.AdminToken
admin std.Address = "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj" // set admin account
admin std.Address
)

// init is a constructor function that runs only once (at time of deployment)
// init is called once at time of deployment
func init() {
// provision the token's name, symbol and number of decimals
mytoken = grc20.NewAdminToken("Mytoken", "MTKN", 4)
// Set deployer of Realm to admin
admin = std.PrevRealm().Addr()

// Set token name, symbol and number of decimals
mytoken = grc20.NewAdminToken("My Token", "TKN", 4)

// set the total supply
mytoken.Mint(admin, 1000000*10000) // @administrator (supply = 1 million)
// Mint 1 million tokens to admin
mytoken.Mint(admin, 1000000*10000)
}

89 changes: 58 additions & 31 deletions docs/assets/how-to-guides/creating-grc20/mytoken-2.gno
Original file line number Diff line number Diff line change
@@ -1,83 +1,110 @@
// TotalSupply returns the total supply of mytoken
func TotalSupply() uint64 {
return mytoken.TotalSupply()
}

func BalanceOf(owner users.AddressOrName) uint64 {
balance, err := mytoken.BalanceOf(owner.Resolve())
// Decimals returns the number of decimals of mytoken
func Decimals() uint {
return mytoken.GetDecimals()
}

// BalanceOf returns the balance mytoken for `account`
func BalanceOf(account std.Address) uint64 {
balance, err := mytoken.BalanceOf(account)
if err != nil {
panic(err)
}

return balance
}

func Allowance(owner, spender users.AddressOrName) uint64 {
allowance, err := mytoken.Allowance(owner.Resolve(), spender.Resolve())
// Allowance returns the allowance of spender on owner's balance
func Allowance(owner, spender std.Address) uint64 {
allowance, err := mytoken.Allowance(owner, spender)
if err != nil {
panic(err)
}

return allowance
}

func Transfer(to users.AddressOrName, amount uint64) {
// Transfer transfers amount from caller to recipient
func Transfer(recipient std.Address, amount uint64) {
caller := std.PrevRealm().Addr()
err := mytoken.Transfer(caller, to.Resolve(), amount)
if err != nil {
if err := mytoken.Transfer(caller, recipient, amount); err != nil {
panic(err)
}
}

func Approve(spender users.AddressOrName, amount uint64) {
// Approve approves amount of caller's tokens to be spent by spender
func Approve(spender std.Address, amount uint64) {
caller := std.PrevRealm().Addr()
err := mytoken.Approve(caller, spender.Resolve(), amount)
if err != nil {
if err := mytoken.Approve(caller, spender, amount); err != nil {
panic(err)
}
}

func TransferFrom(from, to users.AddressOrName, amount uint64) {
// TransferFrom transfers `amount` of tokens from `from` to `to`
func TransferFrom(from, to std.Address, amount uint64) {
caller := std.PrevRealm().Addr()
err := mytoken.TransferFrom(caller, from.Resolve(), to.Resolve(), amount)
if err != nil {

if amount <= 0 {
panic("transfer amount must be greater than zero")
}

if err := mytoken.TransferFrom(caller, from, to, amount); err != nil {
panic(err)
}
}

func Mint(address users.AddressOrName, amount uint64) {
caller := std.PrevRealm().Addr()
assertIsAdmin(caller)
err := mytoken.Mint(address.Resolve(), amount)
if err != nil {
// Mint mints amount of tokens to address. Callable only by admin of token
func Mint(address std.Address, amount uint64) {
assertIsAdmin(std.PrevRealm().Addr())

if amount <= 0 {
panic("mint amount must be greater than zero")
}

if err := mytoken.Mint(address, amount); err != nil {
panic(err)
}
}

func Burn(address users.AddressOrName, amount uint64) {
caller := std.PrevRealm().Addr()
assertIsAdmin(caller)
err := mytoken.Burn(address.Resolve(), amount)
if err != nil {
// Burn burns amount of tokens from address. Callable only by admin of token
func Burn(address std.Address, amount uint64) {
assertIsAdmin(std.PrevRealm().Addr())

if amount <= 0 {
panic("burn amount must be greater than zero")
}

if err := mytoken.Burn(address, amount); err != nil {
panic(err)
}
}

// assertIsAdmin asserts the address is the admin of token
func assertIsAdmin(address std.Address) {
if address != admin {
panic("restricted access")
}
}

// Render renders the state of the realm
func Render(path string) string {
parts := strings.Split(path, "/")
c := len(parts)

switch {
case path == "":
// Default GRC20 render
return mytoken.RenderHome()
case c == 2 && parts[0] == "balance":
owner := users.AddressOrName(parts[1])
balance, _ := mytoken.BalanceOf(owner.Resolve())
// Render balance of specific address
owner := std.Address(parts[1])
balance, _ := mytoken.BalanceOf(owner)
return ufmt.Sprintf("%d\n", balance)
default:
return "404\n"
}
}

func assertIsAdmin(address std.Address) {
if address != admin {
panic("restricted access")
}
}
101 changes: 94 additions & 7 deletions docs/assets/how-to-guides/creating-grc721/mynonfungibletoken-1.gno
Original file line number Diff line number Diff line change
@@ -1,17 +1,104 @@
package mynonfungibletoken
package mynft

import (
"github.com/gnolang/gno/examples/gno.land/p/demo/grc/grc721"
"std"

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

var (
admin std.Address = "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj" // set admin account
// provision the token's name and symbol
mynonfungibletoken = grc721.NewBasicNFT("mynonfungibletoken", "MNFT")
mynft *grc721.IGRC721
admin std.Address
)

// init is called once at time of deployment
func init() {
mintNNFT(admin, 10) // @administrator (supply = 10)
// Set deployer of Realm to admin
admin = std.PrevRealm().Addr()

// Set token name, symbol and number of decimals
mynft = grc721.NewBasicNFT("My NFT", "MNFT")
}

func BalanceOf(owner std.Address) uint64 {
balance, err := mynft.BalanceOf(owner)
if err != nil {
panic(err)
}

return balance
}

func OwnerOf(tid grc721.TokenID) std.Address {
owner, err := mynft.OwnerOf(tid)
if err != nil {
panic(err)
}

return owner
}

func IsApprovedForAll(owner, operator std.Address) bool {
return mynft.IsApprovedForAll(owner, operator)
}

func GetApproved(tid grc721.TokenID) std.Address {
addr, err := mynft.GetApproved(tid)
if err != nil {
panic(err)
}

return addr
}

func Approve(to std.Address, tid grc721.TokenID) {
err := mynft.Approve(to, tid)
if err != nil {
panic(err)
}
}

func SetApprovalForAll(operator std.Address, approved bool) {
err := mynft.SetApprovalForAll(operator, approved)
if err != nil {
panic(err)
}
}

func TransferFrom(from, to std.Address, tid grc721.TokenID) {
err := mynft.TransferFrom(from, to, tid)
if err != nil {
panic(err)
}
}

func Mint(to std.Address, tid grc721.TokenID) {
assertIsAdmin(std.PrevRealm().Addr())
err := mynft.Mint(to, tid)
if err != nil {
panic(err)
}
}

func Burn(tid grc721.TokenID) {
assertIsAdmin(std.PrevRealm().Addr())
err := mynft.Burn(tid)
if err != nil {
panic(err)
}
}

func Render(path string) string {
switch {
case path == "":
return mynft.RenderHome()
default:
return "404\n"
}
}

func assertIsAdmin(address std.Address) {
if address != admin {
panic("restricted access")
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 7 additions & 10 deletions docs/assets/how-to-guides/simple-library/tapas.gno
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package tapas

import (
"gno.land/p/demo/rand"
)
import "std"

// List of tapas suggestions
var listOfTapas = []string{
Expand All @@ -27,14 +25,13 @@ var listOfTapas = []string{
}

// GetTapaSuggestion randomly selects and returns a tapa suggestion
func GetTapaSuggestion() string {
// Create a new instance of the random number generator.
// Notice that this is from an imported Gno library
generator := rand.New()
func GetTapaSuggestion(userInput string) string {

// Generate a random index
randomIndex := generator.Intn(len(listOfTapas))
// Create a random number depending on the block height.
// We get the block height using std.GetHeight(), which is from an imported Gno library, "std"
// Note: this value is not fully random and is easily guessable
randomNumber := int(std.GetHeight()) % len(listOfTapas)

// Return the random suggestion
return listOfTapas[randomIndex]
return listOfTapas[randomNumber]
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions docs/assets/how-to-guides/write-simple-dapp/poll-1.gno
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ func NewPoll(title, description string, deadline int64) *Poll {

// Vote Votes for a user
func (p *Poll) Vote(voter std.Address, vote bool) {
p.Voters().Set(string(voter), vote)
p.Voters().Set(voter.String(), vote)
}

// HasVoted vote: yes - true, no - false
func (p *Poll) HasVoted(address std.Address) (bool, bool) {
vote, exists := p.Voters().Get(string(address))
vote, exists := p.Voters().Get(address.String())
if exists {
return true, vote.(bool)
}
Expand Down
Loading

0 comments on commit 69811ff

Please sign in to comment.