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

3.82 Kb · 130 lines
  1package emission
  2
  3import (
  4	"strings"
  5	"time"
  6
  7	"gno.land/p/gnoswap/utils/v1"
  8	"gno.land/p/moul/md/v0"
  9	"gno.land/p/moul/mdtable/v0"
 10	ufmt "gno.land/p/nt/ufmt/v0"
 11)
 12
 13const gnsDisplayScale uint64 = 1_000_000
 14
 15// Render returns the current GNS emission and distribution state.
 16func Render(path string) string {
 17	if path != "" {
 18		return "404\n"
 19	}
 20
 21	out := md.H1("GNS Emission") +
 22		"\n" +
 23		md.Paragraph("All GNS amounts use exactly six decimal places. Schedule timestamps are UTC.")
 24
 25	scheduleTable := mdtable.Table{
 26		Headers: []string{"Field", "Value"},
 27		Rows: [][]string{
 28			{"Distribution start", formatEmissionTimestamp(GetDistributionStartTimestamp(), "Not started")},
 29			{"Distribution end", formatEmissionTimestamp(GetDistributionEndTimestamp(), "Not scheduled")},
 30			{"Last execution", formatEmissionTimestamp(GetLastExecutedTimestamp(), "Not yet executed")},
 31		},
 32	}
 33	out += md.H2("Distribution schedule") +
 34		"\n" +
 35		scheduleTable.String() +
 36		"\n"
 37
 38	accountingTable := mdtable.Table{
 39		Headers: []string{"Metric", "Amount"},
 40		Rows: [][]string{
 41			{"Undistributed GNS", formatGnsAmount(GetLeftGNSAmount())},
 42			{"Total cumulative distributed", formatGnsAmount(GetTotalAccuDistributed())},
 43		},
 44	}
 45	out += md.H2("Distribution accounting") +
 46		"\n" +
 47		accountingTable.String() +
 48		"\n" +
 49		md.Paragraph(
 50			"The cumulative total includes allocations sent to all four recipients;\n"+
 51				"DevOps and community-pool rows represent completed direct-transfer accounting.",
 52		)
 53
 54	recipientsTable := mdtable.Table{
 55		Headers: []string{"Recipient", "Allocation", "Cumulative distributed"},
 56		Rows: [][]string{
 57			{"Liquidity stakers", formatDistributionPercent(distributionBpsPct[LIQUIDITY_STAKER]), formatGnsAmount(GetAccuDistributedToStaker())},
 58			{"DevOps", formatDistributionPercent(distributionBpsPct[DEVOPS]), formatGnsAmount(GetAccuDistributedToDevOps())},
 59			{"Community pool", formatDistributionPercent(distributionBpsPct[COMMUNITY_POOL]), formatGnsAmount(GetAccuDistributedToCommunityPool())},
 60			{"Governance stakers", formatDistributionPercent(distributionBpsPct[GOV_STAKER]), formatGnsAmount(GetAccuDistributedToGovStaker())},
 61		},
 62	}
 63	out += md.H2("Recipients") +
 64		"\n" +
 65		recipientsTable.String() +
 66		"\n"
 67
 68	stakingTable := mdtable.Table{
 69		Headers: []string{"Recipient", "Since last accounting clear"},
 70		Rows: [][]string{
 71			{"Liquidity stakers", formatGnsAmount(GetDistributedToStaker())},
 72			{"Governance stakers", formatGnsAmount(GetDistributedToGovStaker())},
 73		},
 74	}
 75	out += md.H2("Staking accounting") +
 76		"\n" +
 77		md.Paragraph(
 78			"These allocations have already been transferred to the recipients.\n"+
 79				"The counters below show amounts since each accounting contract's last clear; they\n"+
 80				"are not wallet balances or claimable amounts.",
 81		) +
 82		stakingTable.String()
 83
 84	return out
 85}
 86
 87func formatEmissionTimestamp(timestamp int64, zeroLabel string) string {
 88	if timestamp == 0 {
 89		return zeroLabel
 90	}
 91
 92	return time.Unix(timestamp, 0).UTC().Format(time.RFC3339)
 93}
 94
 95func formatGnsAmount(amount int64) string {
 96	sign := ""
 97	magnitude := uint64(amount)
 98	if amount < 0 {
 99		sign = "-"
100		// Avoid overflowing when formatting the smallest int64 value.
101		magnitude = uint64(-(amount + 1)) + 1
102	}
103
104	whole := magnitude / gnsDisplayScale
105	fraction := magnitude % gnsDisplayScale
106	return ufmt.Sprintf("%s%d.%s GNS", sign, whole, zeroPadUnsigned(fraction, 6))
107}
108
109func formatDistributionPercent(bps int64) string {
110	sign := ""
111	magnitude := uint64(bps)
112	if bps < 0 {
113		sign = "-"
114		magnitude = uint64(-(bps + 1)) + 1
115	}
116
117	whole := magnitude / 100
118	fraction := magnitude % 100
119	return ufmt.Sprintf("%s%d.%s%%", sign, whole, zeroPadUnsigned(fraction, 2))
120}
121
122func zeroPadUnsigned(value uint64, width int) string {
123	valueString := utils.FormatUint(value)
124	padding := width - len(valueString)
125	if padding <= 0 {
126		return valueString
127	}
128
129	return strings.Repeat("0", padding) + valueString
130}