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}