Search Apps Documentation Source Content File Folder Download Copy Actions Download 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}