PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/r/demo/defi/grc20factory

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
grc20factory
Namespace
demo / defi
Files
3 (gnomod.toml)
Exported functions
17
Module
gno.land/r/demo/defi/grc20factory
gno
0.9
This realm implements 2 recognized tokens.MOULTEST →PERUN →

Files (3)

  • gnomod.tomltoml
  • grc20factory.gnogno
  • grc20factory_test.gnogno
grc20factory.gnogno
1package grc20factory23import (4	"gno.land/p/moul/md/v0"5	p "gno.land/p/nt/avl/pager/v0"6	"gno.land/p/nt/avl/rotree/v0"7	"gno.land/p/nt/avl/v0"8	"gno.land/p/nt/grc20/v0"9	"gno.land/p/nt/mux/v0"10	"gno.land/p/nt/ownable/v0"11	"gno.land/p/nt/seqid/v0"12	"gno.land/p/nt/ufmt/v0"13	"gno.land/r/nt/grc20reg/v0"14)1516var (17	instances   avl.Tree // symbol -> *instance18	nextTokenID seqid.ID19	pager       = p.NewPager(rotree.Wrap(&instances, nil), 20, false)20)2122type instance struct {23	token  *grc20.Token24	ledger *grc20.PrivateLedger25	admin  *ownable.Ownable26	faucet int64 // per-request amount. disabled if 0.27}2829func New(cur realm, name, symbol string, decimals int, initialMint, faucet int64) {30	caller := cur.Previous().Address()31	NewWithAdmin(cur, name, symbol, decimals, initialMint, faucet, caller)32}3334func NewWithAdmin(cur realm, name, symbol string, decimals int, initialMint, faucet int64, admin address) {35	exists := instances.Has(symbol)36	if exists {37		panic("token already exists")38	}3940	token, ledger := grc20.NewToken(name, symbol, decimals, nextTokenID.Next(), cur)41	if initialMint > 0 {42		ledger.Mint(admin, initialMint)43	}4445	inst := instance{46		token:  token,47		ledger: ledger,48		admin:  ownable.NewWithAddress(admin),49		faucet: faucet,50	}51	instances.Set(symbol, &inst)5253	grc20reg.Register(cross(cur), token, symbol)54}5556func Bank(symbol string) *grc20.Token {57	inst := mustGetInstance(symbol)58	return inst.token59}6061func TotalSupply(symbol string) int64 {62	inst := mustGetInstance(symbol)63	return inst.token.ReadonlyTeller().TotalSupply()64}6566func HasAddr(symbol string, owner address) bool {67	inst := mustGetInstance(symbol)68	return inst.token.HasAddr(owner)69}7071func BalanceOf(symbol string, owner address) int64 {72	inst := mustGetInstance(symbol)73	return inst.token.ReadonlyTeller().BalanceOf(owner)74}7576func Allowance(symbol string, owner, spender address) int64 {77	inst := mustGetInstance(symbol)78	return inst.token.ReadonlyTeller().Allowance(owner, spender)79}8081func Transfer(cur realm, symbol string, to address, amount int64) {82	inst := mustGetInstance(symbol)83	caller := cur.Previous().Address()84	teller := inst.ledger.ImpersonateTeller(caller)85	checkErr(teller.Transfer(0, cur, to, amount))86}8788func Approve(cur realm, symbol string, spender address, amount int64) {89	inst := mustGetInstance(symbol)90	caller := cur.Previous().Address()91	teller := inst.ledger.ImpersonateTeller(caller)92	checkErr(teller.Approve(0, cur, spender, amount))93}9495func TransferFrom(cur realm, symbol string, from, to address, amount int64) {96	inst := mustGetInstance(symbol)97	caller := cur.Previous().Address()98	teller := inst.ledger.ImpersonateTeller(caller)99	checkErr(teller.TransferFrom(0, cur, from, to, amount))100}101102// faucet.103func Faucet(cur realm, symbol string) {104	inst := mustGetInstance(symbol)105	if inst.faucet == 0 {106		panic("faucet disabled for this token")107	}108	// FIXME: add limits?109	// FIXME: add payment in gnot?110	caller := cur.Previous().Address()111	checkErr(inst.ledger.Mint(caller, inst.faucet))112}113114func Mint(cur realm, symbol string, to address, amount int64) {115	inst := mustGetInstance(symbol)116	inst.admin.AssertOwnedBy(cur.Previous().Address())117	checkErr(inst.ledger.Mint(to, amount))118}119120func Burn(cur realm, symbol string, from address, amount int64) {121	inst := mustGetInstance(symbol)122	inst.admin.AssertOwnedBy(cur.Previous().Address())123	checkErr(inst.ledger.Burn(from, amount))124}125126// instance admin functionality127func DropInstanceOwnership(cur realm, symbol string) {128	inst := mustGetInstance(symbol)129	checkErr(inst.admin.DropOwnership(0, cur))130}131132func TransferInstanceOwnership(cur realm, symbol string, newOwner address) {133	inst := mustGetInstance(symbol)134	checkErr(inst.admin.TransferOwnership(0, cur, newOwner))135}136137func ListTokens(pageNumber, pageSize int) []*grc20.Token {138	page := pager.GetPageWithSize(pageNumber, pageSize)139140	tokens := make([]*grc20.Token, len(page.Items))141	for i := range page.Items {142		tokens[i] = page.Items[i].Value.(*instance).token143	}144145	return tokens146}147148func Render(path string) string {149	router := mux.NewRouter()150	router.HandleFunc("", renderHome)151	router.HandleFunc("{symbol}", renderToken)152	router.HandleFunc("{symbol}/balance/{address}", renderBalance)153	return router.Render(path)154}155156func renderHome(res *mux.ResponseWriter, req *mux.Request) {157	out := md.H1(ufmt.Sprintf("GRC20 Tokens (%d)", instances.Size()))158159	// Get the current page of tokens based on the request path.160	page := pager.MustGetPageByPath(req.RawPath)161162	// Render the list of tokens.163	for _, item := range page.Items {164		token := item.Value.(*instance).token165		out += md.BulletItem(166			md.Link(167				ufmt.Sprintf("%s ($%s)", token.GetName(), token.GetSymbol()),168				ufmt.Sprintf("/r/demo/grc20factory:%s", token.GetSymbol()),169			),170		)171	}172	out += "\n"173174	// Add the page picker.175	out += md.Paragraph(page.Picker(req.Path))176177	res.Write(out)178}179180func renderToken(res *mux.ResponseWriter, req *mux.Request) {181	// Get the token symbol from the request.182	symbol := req.GetVar("symbol")183	inst := mustGetInstance(symbol)184185	// Render the token details.186	out := inst.token.RenderHome()187	out += md.BulletItem(188		ufmt.Sprintf("%s: %s", md.Bold("Admin"), inst.admin.Owner()),189	)190191	res.Write(out)192}193194func renderBalance(res *mux.ResponseWriter, req *mux.Request) {195	var (196		symbol = req.GetVar("symbol")197		addr   = req.GetVar("address")198	)199200	// Get the balance of the specified address for the token.201	inst := mustGetInstance(symbol)202	balance := inst.token.BalanceOf(address(addr))203204	// Render the balance information.205	out := md.Paragraph(206		ufmt.Sprintf("%s balance: %d", md.Bold(addr), balance),207	)208209	res.Write(out)210}211212func mustGetInstance(symbol string) *instance {213	t := instances.Get(symbol)214	if t == nil {215		panic("token instance does not exist")216	}217	return t.(*instance)218}219220func checkErr(err error) {221	if err != nil {222		panic(err.Error())223	}224}225

Functions

  • Allowance(symbol string, owner string, spender string) int64

  • Approve(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, symbol string, spender string, amount int64)

  • BalanceOf(symbol string, owner string) int64

  • Bank(symbol string) *gno.land/p/nt/grc20/v0.Token

  • Burn(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, symbol string, from string, amount int64)

  • DropInstanceOwnership(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, symbol string)

  • Faucet(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, symbol string)

  • HasAddr(symbol string, owner string) bool

  • ListTokens(pageNumber int, pageSize int) []*gno.land/p/nt/grc20/v0.Token

  • Mint(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, symbol string, to string, amount int64)

  • New(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, name string, symbol string, decimals int, initialMint int64, faucet int64)

  • NewWithAdmin(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, name string, symbol string, decimals int, initialMint int64, faucet int64, admin string)

  • Render(path string) string

  • TotalSupply(symbol string) int64

  • Transfer(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, symbol string, to string, amount int64)

  • TransferFrom(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, symbol string, from string, to string, amount int64)

  • TransferInstanceOwnership(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, symbol string, newOwner string)

Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

Rendered

RenderedRawgnoweb ↗

vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.