1package avatar23import (4 "strconv"56 "gno.land/p/moul/md/v0"7 "gno.land/p/moul/mdtable/v0"8 "gno.land/p/nt/grc721/v0"9 "gno.land/p/nt/mdalert/v0"10 "gno.land/p/nt/mux/v0"11 settlers "gno.land/r/g17khqpukees4237dtn3astzapmp462vjhsz6st4/settlers/nft"12)1314const (15 // Sample size is the size in pixels of the avatars in the pages.16 sampleSize = 481718 // Samples is how many avatars the home page shows.19 samples = 620)2122// Render renders the realm.23//24// By default renders what this realm is, how to use it, and some avatars.25//26// Paths:27// - `svg/{address}`: The SVG of the Settler of an address.28// - `md/{address}`: The Markdown that Markdown returns for an address, rendered, with the same parameters.29func Render(path string) string {30 router := mux.NewRouter()31 router.NotFoundHandler = func(res *mux.ResponseWriter, _ *mux.Request) {32 res.Write("Path not found")33 }3435 router.HandleFunc("", renderHome)36 router.HandleFunc("svg/{addr}", renderSVG)37 router.HandleFunc("md/{addr}", renderMarkdown)3839 return router.Render(path)40}4142func renderHome(res *mux.ResponseWriter, _ *mux.Request) {43 res.Write(md.H1("Settler avatars"))4445 if Notice != "" {46 res.Write(mdalert.New(NoticeType, "Message", Notice, false).String() + "\n\n")47 }4849 res.Write(md.Paragraph("This realm draws a Settler as a picture give an address."))50 res.Write(md.Paragraph(51 "It doesn't own the Settler, or store anything about it, it just looks one up and draws it, " +52 "fresh, every time it's asked. That's on purpose, keeping the drawing separate from the main " +53 "collection means any other realm or web app on Gno.land, a forum, a leaderboard, a profile " +54 "page, can show a Settler next to an address without needing to understand pixel art, traits, " +55 "or how any of it's put together.",56 ))5758 res.Write(md.Paragraph(59 "The " + md.Link("Settlers nft", settlers.RealmPath) + " realm is still the one that actually mints " +60 "the Settlers and keeps track of who owns what.",61 ))6263 res.Write(md.Paragraph("Realm paths:"))64 pathsTable := mdtable.Table{Headers: []string{"Path", "Description"}}65 pathsTable.Append([]string{66 md.InlineCode("svg/{address}"),67 "The SVG of the Settler of an address.",68 })69 pathsTable.Append([]string{70 md.InlineCode("md/{address}"),71 "The Markdown that Markdown returns for an address, rendered, with the same parameters.",72 })73 res.Write(pathsTable.String() + "\n")7475 res.Write(md.H2("From a realm"))76 res.Write(md.Paragraph(77 "Call it directly from another realm, for example to show a Settler " +78 "next to an address in your own " + md.InlineCode("Render") + " function:",79 ))80 res.Write(md.LanguageCodeBlock("go", goSnippet))8182 table := mdtable.Table{Headers: []string{"Function", "Description"}}83 table.Append([]string{84 "Markdown(addr, size, transparent)",85 "The image, or an empty text if there is none",86 })87 table.Append([]string{88 "SVG(addr, size, transparent)",89 "The SVG document, or an empty text if there is none",90 })91 table.Append([]string{92 "URI(addr, size, transparent)",93 "The same image as a data URI",94 })95 res.Write(table.String() + "\n")9697 res.Write(md.Paragraph(98 "The size is in pixels, from 32 to 2048, and 0 leaves it to the container. " +99 "With transparent the image has no background. Every call draws the image again and " +100 "costs gas (about 6 to 8 million), so use it in `Render` and not in a transaction.",101 ))102103 res.Write(md.H2("From a web app"))104 res.Write(md.Paragraph(105 "Ask the node for the page of an address, with `vm/qrender`, and use what it returns as an image: " +106 md.InlineCode(RealmPath+":svg/{address}?size=64&transparent=1") +107 ". It is empty if the address has no Settler.",108 ))109 res.Write(md.Paragraph("With gnokey, from a terminal, save it straight to a file:"))110 res.Write(md.LanguageCodeBlock("sh", gnokeySnippet))111112 if n := settlers.TotalSupply(); n > 0 {113 res.Write(md.H2("Last Settlers"))114115 for id := n; id > 0 && id > n-samples; id-- {116 tid := grc721.TokenID(strconv.FormatInt(id, 10))117 owner, err := settlers.OwnerOf(tid)118 if err != nil {119 continue120 }121122 tokenPath := settlers.RealmPath + ":token/" + string(tid)123 table := mdtable.Table{Headers: []string{"", ""}}124 table.Append([]string{125 Markdown(owner, sampleSize, false),126 md.Link(owner.String(), tokenPath),127 })128 res.Write(table.String() + "\n")129 }130 }131}132133func renderSVG(res *mux.ResponseWriter, req *mux.Request) {134 svg := SVG(address(req.GetVar("addr")), sizeParam(req), transparentParam(req))135 res.Write(svg)136}137138func renderMarkdown(res *mux.ResponseWriter, req *mux.Request) {139 size := sizeParam(req)140 if size == 0 {141 size = sampleSize142 }143144 addr := req.GetVar("addr")145 if !address(addr).IsValid() {146 res.Write(md.Paragraph("Not a valid address."))147 res.Write(md.Paragraph(md.Link("< Home", RealmPath)))148 return149 }150151 res.Write(md.H1("Avatar of " + md.InlineCode(addr)))152 res.Write(md.Paragraph(Markdown(address(addr), size, transparentParam(req))))153 res.Write(md.Paragraph(md.Link("< Home", RealmPath)))154}155156func sizeParam(req *mux.Request) int {157 size, err := strconv.Atoi(req.Query.Get("size"))158 if err != nil {159 return 0160 }161 return size162}163164func transparentParam(req *mux.Request) bool {165 v := req.Query.Get("transparent")166 return v == "1" || v == "true"167}168Admin() string
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})
Markdown(addr string, size int, transparent bool) string
Render(path string) string
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)
SVG(addr string, size int, transparent bool) 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)
URI(addr string, size int, transparent bool) string
Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.
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.