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/g1n4pl5uc4yt5r96m9w6fmdznx3x0jyg8l6arhmt/gnocialview

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
gnocialview
Namespace
g1n4pl5uc4yt5r96m9w6fmdznx3x0jyg8l6arhmt
Files
4 (gnomod.toml)
Exported functions
2
Module
gno.land/r/g1n4pl5uc4yt5r96m9w6fmdznx3x0jyg8l6arhmt/gnocialview
gno
0.9

Files (4)

  • gnomod.tomltoml
  • render.gnogno
  • sheet.gnogno
  • sheet_test.gnogno
sheet.gnogno
1package gnocialview23import (4	"strconv"5	"strings"67	gnocial "gno.land/r/g1n4pl5uc4yt5r96m9w6fmdznx3x0jyg8l6arhmt/gnocial"8)910const pageSize = 81112// Sheet is the stable text board the website reads.13// kind selects the page. a, b, and c are cursors or decimal limits.14// Gated bodies are left empty. The fund realm still stores them.15func Sheet(kind, a, b, c string) string {16	var body string17	switch kind {18	case "feed":19		body = sheetPosts(gnocial.Feed(atoiOpt(a), atoiLimit(b)), false)20	case "author":21		p, ok := gnocial.ProfileByHandle(a)22		if !ok {23			panic("unknown handle")24		}25		body = sheetPosts(gnocial.PostsBy(p.Addr, atoiOpt(b), atoiLimit(c)), false)26	case "replies":27		body = sheetPosts(gnocial.Replies(atoiReq(a), atoiOpt(b), atoiLimit(c)), true)28	case "post":29		body = sheetOne(atoiReq(a))30	case "people":31		body = sheetProfiles(gnocial.Handles(a, atoiLimit(b)))32	case "profile":33		body = sheetProfile(a)34	case "account":35		body = sheetAccount(a)36	case "hot":37		body = sheetPosts(gnocial.Hot(atoiLimit(a)), false)38	case "followfeed":39		body = sheetFollowFeed(a, atoiLimit(b))40	case "graph":41		body = sheetProfiles(gnocial.FollowingList(mustAddr(a), optAddr(b), atoiLimit(c)))42	case "fans":43		body = sheetProfiles(gnocial.FollowerList(mustAddr(a), optAddr(b), atoiLimit(c)))44	case "holdings":45		body = sheetHoldings(gnocial.Holdings(mustAddr(a), optAddr(b), atoiLimit(c)))46	case "meta":47		body = sheetMeta()48	case "quotebuy":49		body = quoteLine(true, a, b, c)50	case "quotesell":51		body = quoteLine(false, a, b, c)52	case "shares":53		body = strconv.Itoa(gnocial.SharesOf(mustAddr(a), b))54	default:55		panic("kind")56	}57	return "v1\n" + body58}5960func sheetPosts(posts []gnocial.Article, full bool) string {61	var b strings.Builder62	for i, p := range posts {63		if i > 0 {64			b.WriteString("\n")65		}66		if full {67			b.WriteString(postLine(p))68		} else {69			b.WriteString(cardLine(p))70		}71	}72	return b.String()73}7475func sheetOne(id int) string {76	p, ok := gnocial.GetPost(id)77	if !ok {78		return ""79	}80	return postLine(p)81}8283func sheetProfile(handle string) string {84	p, ok := gnocial.ProfileByHandle(handle)85	if !ok {86		return ""87	}88	return profileLine(p)89}9091func sheetAccount(raw string) string {92	who := optAddr(raw)93	if !who.IsValid() {94		return ""95	}96	p, ok := gnocial.ProfileOf(who)97	if !ok {98		return ""99	}100	return profileLine(p)101}102103func sheetProfiles(rows []gnocial.Profile) string {104	var b strings.Builder105	for i, p := range rows {106		if i > 0 {107			b.WriteString("\n")108		}109		b.WriteString(p.Handle + "\t" + esc(p.Name) + "\t" + strconv.Itoa(p.Followers) + "\t" + strconv.Itoa(p.Posts))110	}111	return b.String()112}113114func sheetHoldings(rows []gnocial.Holding) string {115	var b strings.Builder116	for i, h := range rows {117		if i > 0 {118			b.WriteString("\n")119		}120		b.WriteString(h.Creator.String() + "\t" + esc(h.Handle) + "\t" + strconv.Itoa(h.Amount))121	}122	return b.String()123}124125func sheetFollowFeed(raw string, limit int) string {126	who := mustAddr(raw)127	posts := gnocial.Feed(0, limit)128	var b strings.Builder129	n := 0130	for _, p := range posts {131		prof, ok := gnocial.ProfileOf(p.Author)132		if !ok || !gnocial.Following(who, prof.Handle) {133			continue134		}135		if n > 0 {136			b.WriteString("\n")137		}138		b.WriteString(cardLine(p))139		n++140	}141	return b.String()142}143144func sheetMeta() string {145	paused := "0"146	if gnocial.Paused() {147		paused = "1"148	}149	return strings.Join([]string{150		gnocial.Version(),151		gnocial.Successor(),152		paused,153		strconv.FormatInt(gnocial.TotalReserve(), 10),154		gnocial.Admin().String(),155		gnocial.Treasury().String(),156		strconv.Itoa(gnocial.MemberCount()),157		strconv.Itoa(gnocial.FeedCount()),158		strconv.Itoa(gnocial.LatestID()),159	}, "\t")160}161162func profileLine(p gnocial.Profile) string {163	supply, reserve, holders := gnocial.SupplyOf(p.Handle)164	next := "-1"165	if supply < gnocial.MaxSupply {166		due, _, _, _, _ := gnocial.QuoteBuy(p.Handle, 1)167		next = strconv.FormatInt(due, 10)168	}169	ref := ""170	if p.Referrer.IsValid() {171		ref = p.Referrer.String()172	}173	return strings.Join([]string{174		p.Handle,175		esc(p.Name),176		esc(p.Bio),177		p.Addr.String(),178		ref,179		strconv.Itoa(p.Posts),180		strconv.Itoa(p.Followers),181		strconv.Itoa(p.Following),182		strconv.FormatInt(p.TipsIn, 10),183		strconv.FormatInt(p.TipsOut, 10),184		strconv.Itoa(supply),185		strconv.FormatInt(reserve, 10),186		strconv.Itoa(holders),187		next,188		strconv.FormatInt(p.CreatorFee, 10),189	}, "\t")190}191192// quoteLine prices a trade. c is an optional buyer or seller address.193// Empty c is the anonymous quote. The first number is the amount due or the proceeds.194func quoteLine(buy bool, handle, amount, trader string) string {195	n := atoiReq(amount)196	var head, curve, cf, pf, rf int64197	trader = strings.TrimSpace(trader)198	if buy {199		if trader == "" {200			head, curve, cf, pf, rf = gnocial.QuoteBuy(handle, n)201		} else {202			head, curve, cf, pf, rf = gnocial.QuoteBuyFor(handle, trader, n)203		}204	} else if trader == "" {205		head, curve, cf, pf, rf = gnocial.QuoteSell(handle, n)206	} else {207		head, curve, cf, pf, rf = gnocial.QuoteSellFor(handle, trader, n)208	}209	return join5(head, curve, cf, pf, rf)210}211212func cardLine(p gnocial.Article) string {213	h, name := namesOf(p.Author)214	return strings.Join([]string{215		strconv.Itoa(p.ID),216		esc(h),217		esc(name),218		strconv.Itoa(p.Likes),219		strconv.Itoa(p.Replies),220		strconv.FormatInt(p.Tips, 10),221		bit(p.Gated),222		esc(openPreview(p)),223	}, "\t")224}225226func postLine(p gnocial.Article) string {227	h, name := namesOf(p.Author)228	body := ""229	if !p.Gated && !p.Deleted {230		body = p.Body231	}232	return strings.Join([]string{233		strconv.Itoa(p.ID),234		p.Author.String(),235		esc(h),236		esc(name),237		strconv.Itoa(p.ReplyTo),238		strconv.Itoa(p.Likes),239		strconv.Itoa(p.Replies),240		strconv.FormatInt(p.Tips, 10),241		bit(p.Gated),242		bit(p.Deleted),243		strconv.FormatInt(p.Height, 10),244		esc(body),245	}, "\t")246}247248func namesOf(a address) (handle, name string) {249	p, ok := gnocial.ProfileOf(a)250	if !ok {251		return a.String(), a.String()252	}253	return p.Handle, p.Name254}255256func openPreview(p gnocial.Article) string {257	if p.Gated || p.Deleted {258		return ""259	}260	return preview(strings.ReplaceAll(p.Body, "\n", " "), 160)261}262263func bit(v bool) string {264	if v {265		return "1"266	}267	return "0"268}269270func esc(s string) string {271	s = strings.ReplaceAll(s, "\\", "\\\\")272	s = strings.ReplaceAll(s, "\r", "")273	s = strings.ReplaceAll(s, "\n", "\\n")274	s = strings.ReplaceAll(s, "\t", "\\t")275	return s276}277278func join5(a, b, c, d, e int64) string {279	return strconv.FormatInt(a, 10) + "\t" + strconv.FormatInt(b, 10) + "\t" + strconv.FormatInt(c, 10) + "\t" + strconv.FormatInt(d, 10) + "\t" + strconv.FormatInt(e, 10)280}281282func atoiOpt(s string) int {283	s = strings.TrimSpace(s)284	if s == "" {285		return 0286	}287	n, err := strconv.Atoi(s)288	if err != nil || n < 0 {289		panic("cursor")290	}291	return n292}293294func atoiReq(s string) int {295	n := atoiOpt(s)296	if n < 1 {297		panic("id")298	}299	return n300}301302func atoiLimit(s string) int {303	s = strings.TrimSpace(s)304	if s == "" {305		return pageSize306	}307	n, err := strconv.Atoi(s)308	if err != nil {309		panic("limit")310	}311	if n < 1 || n > 20 {312		panic("limit")313	}314	return n315}316317func mustAddr(s string) address {318	a := optAddr(s)319	if !a.IsValid() {320		panic("bad address")321	}322	return a323}324325func optAddr(s string) address {326	s = strings.TrimSpace(s)327	if s == "" {328		return address("")329	}330	if len(s) > 60 {331		panic("bad address")332	}333	return address(s)334}335336func preview(s string, n int) string {337	if len(s) <= n {338		return s339	}340	i := n341	for i > 0 && s[i]&0xC0 == 0x80 {342		i--343	}344	return s[:i] + "…"345}346

Functions

  • Render(path string) string

  • Sheet(kind string, a string, b string, c string) 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.