gno.land/r/g17khqpukees4237dtn3astzapmp462vjhsz6st4/settlers/nft⧉ Realm Open in gnoweb ↗
Kind Realm (renderable)
Name nft
Namespace g17khqpukees4237dtn3astzapmp462vjhsz6st4 / settlers
Exported functions 27
Module gno.land/r/g17khqpukees4237dtn3astzapmp462vjhsz6st4/settlers/nft
gno 0.9 ⧉
1 package nft 2 3 import ( 4 "strconv" 5 6 "gno.land/p/g17khqpukees4237dtn3astzapmp462vjhsz6st4/settlers/nft/v0" 7 "gno.land/p/moul/md/v0" 8 Admin () string
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}, to string, tid string)
BalanceOf (owner string) (int64, interface {Error func() string})
Cap () int
ClearNotice (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})
ExternalURL (tid string) string
GetApproved (tid string) (string, interface {Error func() string})
GetName () string
GetSymbol () string
ID () string
IsApprovedForAll (owner string, operator string) bool
MerkleRoot () string
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}, proof string) string
OwnerOf (tid string) (string, interface {Error func() string})
Render (path string) string
SetApprovalForAll (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}, operator string, approved bool)
SetNotice (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}, alertType string, msg string)
SetSnapshot (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}, rootHex string, count int)
Token () interface {Approve func(int, .uverse.realm, .uverse.address, gno.land/p/nt/grc721/v0.TokenID) .uverse.error; BalanceOf func(.uverse.address) (int64, .uverse.error); GetApproved func(gno.land/p/nt/grc721/v0.TokenID) (.uverse.address, .uverse.error); GetName func() string; GetSymbol func() string; ID func() string; IsApprovedForAll func(.uverse.address, .uverse.address) bool; OwnerOf func(gno.land/p/nt/grc721/v0.TokenID) (.uverse.address, .uverse.error); SetApprovalForAll func(int, .uverse.realm, .uverse.address, bool) .uverse.error; TotalSupply func() int64; TransferFrom func(int, .uverse.realm, .uverse.address, .uverse.address, gno.land/p/nt/grc721/v0.TokenID) .uverse.error}
TokenMetadata (tid string) (string, interface {Error func() string})
TokenOf (addr string) string
TokenURI (tid string) (string, interface {Error func() string})
Total () int
TotalSupply () int64
TraitsOf (tid string) (struct{Skin uint8; Hat uint8; BeardColor uint8; Tunic uint8; Background uint8; HatShape uint8; Flip uint8; Glasses uint8; Beard uint8}, interface {Error func() string})
TransferAdmin (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}, newAdmin string)
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}, from string, to string, tid string)
Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.
"gno.land/p/moul/mdtable/v0"
9 "gno.land/p/nt/grc721/v0"
10 "gno.land/p/nt/markdown/sanitize/v0"
11 "gno.land/p/nt/mdalert/v0"
12 "gno.land/p/nt/mux/v0"
13 )
14
15 const (
16 // Gallery width is the width/height of gallery Settler images.
17 galleryWidth = 96
18
19 // Detail width is the width/height of Settler the image for detail views.
20 detailWidth = 256
21
22 // Gallery length is the number of last minted Settlers of the home page.
23 galleryLen = 5
24 )
25
26 // Render renders the realm.
27 //
28 // By default renders the state of the mint and the last minted Settlers.
29 //
30 // Paths:
31 // - `token/{id}`: A Settler with its traits and its owner.
32 // - `addr/{address}`: The Settler of an account.
33 func Render(path string ) string {
34 router := mux.NewRouter()
35 router.NotFoundHandler = func (res *mux.ResponseWriter, _ *mux.Request) {
36 res.Write( "Path not found" )
37 }
38
39 router.HandleFunc( "" , renderHome)
40 router.HandleFunc( "token/{id}" , renderToken)
41 router.HandleFunc( "addr/{addr}" , renderAddr)
42
43 return router.Render(path)
44 }
45
46 func renderHome(res *mux.ResponseWriter, _ *mux.Request) {
47 res.Write(md.H1( "Settlers" ))
48
49 if Notice != "" {
50 res.Write(mdalert.New(NoticeType, "Message" , Notice, false ).String() + "\n\n" )
51 }
52
53 res.Write(md.Paragraph(
54 "Soulbound pixel-art gnomes for the early settlers of Gno.land. " +
55 "Every account that had at least 15 GNOT at the launch of `gnoland-1` can mint one, " +
56 "first come first served. A Settler can't be transferred, it's soulbound" ,
57 ))
58
59 res.Write(md.Paragraph( "Realm paths:" ))
60 pathsTable := mdtable.Table{Headers: [] string { "Path" , "Description" }}
61 pathsTable.Append([] string {
62 md.InlineCode( "token/{id}" ),
63 "A Settler with its traits and its owner." ,
64 })
65 pathsTable.Append([] string {
66 md.InlineCode( "addr/{address}" ),
67 "The Settler of an account." ,
68 })
69 res.Write(pathsTable.String() + "\n" )
70
71 minted := tokens.Size()
72 if len(root) == 0 {
73 res.Write(md.Paragraph( "The mint is not open yet." ))
74 } else {
75 res.Write(md.Paragraph(
76 md.BulletItem(md.Bold( "Minted:" )+ " " +strconv.Itoa(minted)+ " of " +strconv.Itoa(supplyCap)) +
77 md.BulletItem(md.Bold( "Eligible accounts:" )+ " " +strconv.Itoa(total)) +
78 md.BulletItem(md.Bold( "Merkle root:" )+ " " +md.InlineCode(MerkleRoot())),
79 ))
80
81 res.Write(md.Paragraph(
82 "To mint, get your proof from the list of eligible accounts and call " +
83 md.Link( "Mint" , RealmPath+ "$help&func=Mint" ) + " with it; the account that " +
84 "signs the transaction is the one that gets the Settler." ,
85 ))
86 res.Write(md.Paragraph(
87 "Check the " + md.Link( "README" , RealmPath+ "$source&file=README.md" ) + " for the full instructions." ,
88 ))
89 }
90
91 if minted > 0 {
92 res.Write(md.H2( "Last Settlers" ))
93 tokens.ReverseIterateByOffset( 0 , galleryLen, func (key string , value any ) bool {
94 settlerID, _ := strconv.Atoi(key)
95 img := image(settlerID, nft.Unpack(value.( uint32 )), galleryWidth)
96 res.Write( "[" + img + "](" + tokenPath(settlerID) + ") " )
97 return false
98 })
99 res.Write( "\n\n" )
100 }
101
102 res.Write(footer())
103 }
104
105 func renderToken(res *mux.ResponseWriter, req *mux.Request) {
106 tid := grc721.TokenID(req.GetVar( "id" ))
107 settlerID, _ := parseTokenID(tid)
108 packed, ok := traitsOf(tid)
109 if !ok {
110 res.Write(md.Paragraph( "Settler not found." ))
111 res.Write(md.Paragraph(backHomeLink()))
112 return
113 }
114
115 res.Write(md.H1(settlerName(settlerID)))
116 t := nft.Unpack(packed)
117 res.Write(image(settlerID, t, detailWidth) + "\n\n" )
118
119 ownerAddr, _ := OwnerOf(tid)
120 owner := ownerAddr.String()
121 res.Write(md.Paragraph(
122 "Owner: " + md.Link(owner, RealmPath+ ":addr/" +owner) +
123 " · soulbound, it can't be transferred" ,
124 ))
125
126 res.Write( "| Trait | Value |\n| --- | --- |\n" )
127 for _, attr := range t.Attributes() {
128 res.Write( "| " + attr.Type + " | " + attr.Value + " |\n" )
129 }
130 res.Write( "\n" )
131
132 res.Write(md.Paragraph(backHomeLink()))
133 res.Write(footer())
134 }
135
136 func renderAddr(res *mux.ResponseWriter, req *mux.Request) {
137 addr := sanitize.BechString(req.GetVar( "addr" ), "g" )
138 if addr == "" {
139 res.Write(md.Paragraph( "Not a valid address." ))
140 res.Write(md.Paragraph(backHomeLink()))
141 return
142 }
143
144 tid := TokenOf(address(addr))
145 if tid == "" {
146 res.Write(md.H1( "Settler of " + md.InlineCode(addr)))
147 res.Write(md.Paragraph( "This account has not minted a Settler." ))
148 res.Write(md.Paragraph(backHomeLink()))
149 return
150 }
151
152 settlerID, _ := parseTokenID(tid)
153 packed, _ := traitsOf(tid)
154 img := image(settlerID, nft.Unpack(packed), detailWidth)
155 res.Write(md.H1( "Settler of " + md.InlineCode(addr)))
156 res.Write( "[" + img + "](" + tokenPath(settlerID) + ")\n\n" )
157 res.Write(md.Paragraph(backHomeLink()))
158 res.Write(footer())
159 }
160
161 func image(settlerID int , t nft.Traits, width int ) string {
162 alt := settlerName(settlerID)
163 return " + ")"
164 }
165
166 func tokenPath(settlerID int ) string {
167 return RealmPath + ":token/" + strconv.Itoa(settlerID)
168 }
169
170 func backHomeLink() string {
171 return md.Link( "< Home" , RealmPath)
172 }
173
174 func settlerName(settlerID int ) string {
175 return "Settler #" + strconv.Itoa(settlerID)
176 }
177
178 func footer() string {
179 return md.Blockquote(nft.Credits)
180 }
181
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.