Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

render.gno

4.26 Kb · 165 lines
  1package vouch
  2
  3import (
  4	"strconv"
  5
  6	"gno.land/p/moul/kit/num/v0"
  7	"gno.land/p/moul/kit/ui/v0"
  8	"gno.land/p/moul/md/v0"
  9	"gno.land/p/moul/realmpath/v0"
 10	vo "gno.land/p/moul/x/social/vouch/v0"
 11)
 12
 13// Render routes two views: the realm's own index, and one address's page.
 14//
 15// An address carries no slash, so the per-address route is a path element and
 16// not a prefix strip.
 17func Render(path string) string {
 18	req := realmpath.Parse(path)
 19
 20	switch req.PathPart(0) {
 21	case "":
 22		return renderIndex()
 23	case "addr":
 24		return renderAddr(req.PathPart(1))
 25	default:
 26		return md.H1("Not found") + "No such view: " + ui.Inline(req.Path)
 27	}
 28}
 29
 30func renderIndex() string {
 31	out := md.H1("Vouch")
 32	out += "A web of trust other realms gate on. One address vouches for another, " +
 33		"in writing, optionally with GNOT locked behind it.\n\n"
 34
 35	t := ui.NewTable("vouches", "people vouched for", "bonded", "awaiting withdrawal")
 36	t.Row(
 37		strconv.Itoa(graph.Count()),
 38		strconv.Itoa(graph.People()),
 39		num.GNOTf(graph.TotalBonded()),
 40		num.GNOTf(graph.TotalOwed()),
 41	)
 42	out += t.String()
 43
 44	out += md.H2("Most vouched for")
 45	out += board()
 46
 47	out += md.H2("The gate")
 48	out += "One line in the realm that wants it, and it costs no transaction:\n\n"
 49	out += md.LanguageCodeBlock("go", `import "`+realmPath+`"
 50
 51if !vouch.IsTrusted(addr, 2) {
 52	panic("get two people to vouch for you first")
 53}`)
 54	out += md.Italic("A score counts distinct vouchers, so restating a vouch does not " +
 55		"raise it and revoking lowers it. It does not count distinct people: a pair " +
 56		"vouching for each other both reach one, which is why a real gate asks for " +
 57		"more.") + "\n\n"
 58
 59	out += md.H2("Take part")
 60	out += ui.Action("\U0001F91D Vouch", "Vouch", "target", "", "reason", "") +
 61		" · " + ui.Action("\U0001F4B0 Withdraw a refunded bond", "Withdraw") + "\n\n"
 62	out += md.Italic("Coins sent with Vouch are locked as a bond on that vouch and come " +
 63		"back when you revoke it. There is no slashing: deciding that a vouch was a lie " +
 64		"needs an arbiter, and choosing one is the whole design question.") + "\n"
 65
 66	return out
 67}
 68
 69func board() string {
 70	rows := graph.Leaderboard(BoardSize)
 71	if len(rows) == 0 {
 72		return ui.Empty("Nobody has been vouched for yet.")
 73	}
 74	t := ui.NewTable("", "address", "vouchers", "bonded")
 75	for i, r := range rows {
 76		t.Row(
 77			ui.Podium(i),
 78			md.Link(ui.AddrText(r.Addr), vo.AddrURL(realmPath, r.Addr)),
 79			strconv.Itoa(r.Score),
 80			num.GNOTf(r.Bonded),
 81		)
 82	}
 83	return t.String()
 84}
 85
 86func renderAddr(raw string) string {
 87	addr := address(raw)
 88	if !addr.IsValid() {
 89		return md.H1("Vouch") + "Not an address: " + ui.Inline(raw)
 90	}
 91
 92	out := md.H1("Vouch for " + ui.AddrText(addr))
 93	out += ui.AddrFull(addr) + "\n\n"
 94
 95	score := graph.ScoreOf(addr)
 96	t := ui.NewTable("vouchers", "bonded on them", "trusted at 2", "awaiting withdrawal")
 97	t.Row(
 98		strconv.Itoa(score),
 99		num.GNOTf(graph.BondedFor(addr)),
100		yesno(graph.IsTrusted(addr, 2)),
101		num.GNOTf(graph.Owed(addr)),
102	)
103	out += t.String()
104
105	out += md.H2("Vouched for by")
106	out += inbound(addr)
107
108	out += md.H2("Vouches for")
109	out += outbound(addr)
110
111	out += "\n" + ui.Action("\U0001F91D Vouch for this address", "Vouch",
112		"target", addr.String(), "reason", "") +
113		" · " + ui.Action("\U0000274C Revoke mine", "Revoke", "target", addr.String()) + "\n"
114	return out
115}
116
117func inbound(addr address) string {
118	from := graph.VouchedBy(addr)
119	if len(from) == 0 {
120		return ui.Empty("Nobody vouches for this address.")
121	}
122	t := ui.NewTable("voucher", "reason", "bond", "mutual", "since")
123	for _, f := range from {
124		v, ok := graph.Get(f, addr)
125		if !ok {
126			continue
127		}
128		t.Row(
129			md.Link(ui.AddrText(f), vo.AddrURL(realmPath, f)),
130			ui.Cell(v.Reason),
131			num.GNOTf(v.Bond),
132			yesno(graph.Mutual(f, addr)),
133			strconv.FormatInt(v.At, 10),
134		)
135	}
136	return t.String()
137}
138
139func outbound(addr address) string {
140	to := graph.VouchesOf(addr)
141	if len(to) == 0 {
142		return ui.Empty("This address vouches for nobody.")
143	}
144	t := ui.NewTable("for", "reason", "bond", "their vouchers")
145	for _, target := range to {
146		v, ok := graph.Get(addr, target)
147		if !ok {
148			continue
149		}
150		t.Row(
151			md.Link(ui.AddrText(target), vo.AddrURL(realmPath, target)),
152			ui.Cell(v.Reason),
153			num.GNOTf(v.Bond),
154			strconv.Itoa(graph.ScoreOf(target)),
155		)
156	}
157	return t.String()
158}
159
160func yesno(b bool) string {
161	if b {
162		return "yes"
163	}
164	return "no"
165}