HomeOverviewValsValidatorsGovGovernanceIBCRelayersN/AInfraInfra
/
powered by GATA HUB

r/demo/defi/grc20factory

Gno.land

Realm
Files31 test
Lines of code225excluding tests
Functions17exported
Storage112.4 KB11.24 GNOT deposit
DeployedN/A

Realm

Pathgno.land/r/demo/defi/grc20factory
Accountg1afzm94ck2u…ghu4cfac
TokensPERUNMOULTEST
grc20factory.gno224 lines
1package grc20factory
2
3import (
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)
15
16var (
17 instances avl.Tree // symbol -> *instance
18 nextTokenID seqid.ID
19 pager = p.NewPager(rotree.Wrap(&instances, nil), 20, false)
20)
21
22type instance struct {
23 token *grc20.Token
24 ledger *grc20.PrivateLedger
25 admin *ownable.Ownable
26 faucet int64 // per-request amount. disabled if 0.
27}
28
29func 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}
33
34func 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 }
39
40 token, ledger := grc20.NewToken(name, symbol, decimals, nextTokenID.Next(), cur)
41 if initialMint > 0 {
42 ledger.Mint(admin, initialMint)
43 }
44
45 inst := instance{
46 token: token,
47 ledger: ledger,
48 admin: ownable.NewWithAddress(admin),
49 faucet: faucet,
50 }
51 instances.Set(symbol, &inst)
52
53 grc20reg.Register(cross(cur), token, symbol)
54}
55
56func Bank(symbol string) *grc20.Token {
57 inst := mustGetInstance(symbol)
58 return inst.token
59}
60
61func TotalSupply(symbol string) int64 {
62 inst := mustGetInstance(symbol)
63 return inst.token.ReadonlyTeller().TotalSupply()
64}
65
66func HasAddr(symbol string, owner address) bool {
67 inst := mustGetInstance(symbol)
68 return inst.token.HasAddr(owner)
69}
70
71func BalanceOf(symbol string, owner address) int64 {
72 inst := mustGetInstance(symbol)
73 return inst.token.ReadonlyTeller().BalanceOf(owner)
74}
75
76func Allowance(symbol string, owner, spender address) int64 {
77 inst := mustGetInstance(symbol)
78 return inst.token.ReadonlyTeller().Allowance(owner, spender)
79}
80
81func 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}
87
88func 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}
94
95func 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}
101
102// 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}
113
114func 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}
119
120func 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}
125
126// instance admin functionality
127func DropInstanceOwnership(cur realm, symbol string) {
128 inst := mustGetInstance(symbol)
129 checkErr(inst.admin.DropOwnership(0, cur))
130}
131
132func TransferInstanceOwnership(cur realm, symbol string, newOwner address) {
133 inst := mustGetInstance(symbol)
134 checkErr(inst.admin.TransferOwnership(0, cur, newOwner))
135}
136
137func ListTokens(pageNumber, pageSize int) []*grc20.Token {
138 page := pager.GetPageWithSize(pageNumber, pageSize)
139
140 tokens := make([]*grc20.Token, len(page.Items))
141 for i := range page.Items {
142 tokens[i] = page.Items[i].Value.(*instance).token
143 }
144
145 return tokens
146}
147
148func 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}
155
156func renderHome(res *mux.ResponseWriter, req *mux.Request) {
157 out := md.H1(ufmt.Sprintf("GRC20 Tokens (%d)", instances.Size()))
158
159 // Get the current page of tokens based on the request path.
160 page := pager.MustGetPageByPath(req.RawPath)
161
162 // Render the list of tokens.
163 for _, item := range page.Items {
164 token := item.Value.(*instance).token
165 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"
173
174 // Add the page picker.
175 out += md.Paragraph(page.Picker(req.Path))
176
177 res.Write(out)
178}
179
180func renderToken(res *mux.ResponseWriter, req *mux.Request) {
181 // Get the token symbol from the request.
182 symbol := req.GetVar("symbol")
183 inst := mustGetInstance(symbol)
184
185 // 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 )
190
191 res.Write(out)
192}
193
194func renderBalance(res *mux.ResponseWriter, req *mux.Request) {
195 var (
196 symbol = req.GetVar("symbol")
197 addr = req.GetVar("address")
198 )
199
200 // Get the balance of the specified address for the token.
201 inst := mustGetInstance(symbol)
202 balance := inst.token.BalanceOf(address(addr))
203
204 // Render the balance information.
205 out := md.Paragraph(
206 ufmt.Sprintf("%s balance: %d", md.Bold(addr), balance),
207 )
208
209 res.Write(out)
210}
211
212func 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}
219
220func checkErr(err error) {
221 if err != nil {
222 panic(err.Error())
223 }
224}
FunctionParametersReturnsKind
New(name string, symbol string, decimals int, initialMint int64, faucet int64)-Crossing
NewWithAdmin(name string, symbol string, decimals int, initialMint int64, faucet int64, admin string)-Crossing
Bank(symbol string)*gno.land/p/nt/grc20/v0.Token-
TotalSupply(symbol string)int64-
HasAddr(symbol string, owner string)bool-
BalanceOf(symbol string, owner string)int64-
Allowance(symbol string, owner string, spender string)int64-
Transfer(symbol string, to string, amount int64)-Crossing
Approve(symbol string, spender string, amount int64)-Crossing
TransferFrom(symbol string, from string, to string, amount int64)-Crossing
Faucet(symbol string)-Crossing
Mint(symbol string, to string, amount int64)-Crossing
1–12 of 171/2

GRC20 Tokens (2)

  • moultest \($MOULTEST\)
  • Perun \($PERUN\)
Loading calls…
Calls20from 10 accounts
FunctionCallerStatusBlockAge
Approveg1cyhtq6…z2xx7xSuccess749,5842d ago
Approveg1s2g47c…tx36yvSuccess711,2934d ago
Approveg1ak7swu…fs9m4gSuccess680,7575d ago
Approveg1s2g47c…tx36yvSuccess485,73313d ago
Approveg1qyfled…t0n8khSuccess474,85013d ago
Approveg1r9mekl…y5hazpSuccess471,79713d ago
Approveg1rtsce8…xk87jaSuccess448,01514d ago
Approveg1558yc5…z3a9f3Success447,35114d ago
Approveg1qyfled…t0n8khSuccess430,69315d ago
Approveg12t2q70…xepmvdSuccess418,09815d ago
Approveg1qyfled…t0n8khSuccess404,41016d ago
Transferg1cyhtq6…z2xx7xSuccess399,47316d ago
1–12 of 201/2