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

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

stakeseries.gno

3.69 Kb · 151 lines
  1package kourtv3
  2import (
  3	"strconv"
  4	"strings"
  5	checkpoint "gno.land/p/g1leu8d2vsplhehcfkjg50mwgdpxdkt8tztu95wr/checkpoint/v0"
  6)
  7const (
  8	hourlyKeep = uint32(168)
  9	trimBudget = 2
 10	dailyBlocks = int64(17_280)
 11	seriesRowCap = 400
 12)
 13func csKey(id uint64, suffix string) string {
 14	return "cs:" + strconv.FormatUint(id, 10) + ":" + suffix
 15}
 16func ensureCSArch(c *Court) *checkpoint.Archive {
 17	if c.csArch == nil {
 18		c.csArch = checkpoint.NewArchive()
 19	}
 20	return c.csArch
 21}
 22func setIfChanged(a *checkpoint.Archive, s *checkpoint.Series, key string, e uint32, v int64) {
 23	if v != s.Value() {
 24		s.SetAt(a, key, e, v)
 25	}
 26}
 27func recordPools(c *Court, cs *claimState) {
 28	h := heightNow()
 29	a := ensureCSArch(c)
 30	hE := uint32(h/epochBlocks) + 1
 31	dE := uint32(h/dailyBlocks) + 1
 32	setIfChanged(a, &cs.yesH, csKey(cs.id, "yh"), hE, cs.yesStake)
 33	setIfChanged(a, &cs.noH, csKey(cs.id, "nh"), hE, cs.noStake)
 34	setIfChanged(a, &cs.yesD, csKey(cs.id, "yd"), dE, cs.yesStake)
 35	setIfChanged(a, &cs.noD, csKey(cs.id, "nd"), dE, cs.noStake)
 36	if hE > cs.histTrimmedTo {
 37		cs.histTrimmedTo = hE
 38		trimClaimHistory(c, cs, hE)
 39	}
 40}
 41func trimClaimHistory(c *Court, cs *claimState, hE uint32) {
 42	if c.csArch == nil || hE <= hourlyKeep+1 {
 43		return
 44	}
 45	keep := hE - hourlyKeep
 46	c.csArch.Trim(csKey(cs.id, "yh"), keep, trimBudget)
 47	c.csArch.Trim(csKey(cs.id, "nh"), keep, trimBudget)
 48}
 49type histPoint struct {
 50	e uint32
 51	v int64
 52}
 53func collectSeriesKeyed(a *checkpoint.Archive, s *checkpoint.Series, key string) ([]histPoint, bool) {
 54	pts := []histPoint{}
 55	more := false
 56	if a != nil && key != "" {
 57		a.WalkDesc(key, func(e uint32, v int64) bool {
 58			if len(pts) >= seriesRowCap {
 59				more = true
 60				return true
 61			}
 62			pts = append(pts, histPoint{e, v})
 63			return false
 64		})
 65	}
 66	for i, j := 0, len(pts)-1; i < j; i, j = i+1, j-1 {
 67		pts[i], pts[j] = pts[j], pts[i]
 68	}
 69	if e1, pv := s.Prev(); e1 != 0 {
 70		pts = append(pts, histPoint{e1, pv})
 71	}
 72	if e0 := s.Since(); e0 != 0 {
 73		pts = append(pts, histPoint{e0, s.Value()})
 74	}
 75	return pts, more
 76}
 77func ClaimSeries(courtSlug string, claimID uint64, grain string) string {
 78	c := mustCourt(courtSlug)
 79	cs := mustClaim(c, claimID)
 80	var width int64
 81	var yS, nS *checkpoint.Series
 82	var yKey, nKey string
 83	switch grain {
 84	case "hourly":
 85		width = epochBlocks
 86		yS, nS = &cs.yesH, &cs.noH
 87		yKey, nKey = csKey(claimID, "yh"), csKey(claimID, "nh")
 88	case "daily":
 89		width = dailyBlocks
 90		yS, nS = &cs.yesD, &cs.noD
 91		yKey, nKey = csKey(claimID, "yd"), csKey(claimID, "nd")
 92	default:
 93		panic(`kourtv3: grain is "hourly" or "daily"`)
 94	}
 95	now := uint32(heightNow()/width) + 1
 96	ys, moreY := collectSeriesKeyed(c.csArch, yS, yKey)
 97	ns, moreN := collectSeriesKeyed(c.csArch, nS, nKey)
 98	start := uint32(0)
 99	if moreY && len(ys) > 0 && ys[0].e > start {
100		start = ys[0].e
101	}
102	if moreN && len(ns) > 0 && ns[0].e > start {
103		start = ns[0].e
104	}
105	more := moreY || moreN
106	curY, curN := int64(0), int64(0)
107	i, j := 0, 0
108	for i < len(ys) && ys[i].e < start {
109		curY = ys[i].v
110		i++
111	}
112	for j < len(ns) && ns[j].e < start {
113		curN = ns[j].v
114		j++
115	}
116	rows := []string{}
117	for i < len(ys) || j < len(ns) {
118		var e uint32
119		switch {
120		case i >= len(ys):
121			e = ns[j].e
122		case j >= len(ns):
123			e = ys[i].e
124		case ys[i].e < ns[j].e:
125			e = ys[i].e
126		default:
127			e = ns[j].e
128		}
129		if i < len(ys) && ys[i].e == e {
130			curY = ys[i].v
131			i++
132		}
133		if j < len(ns) && ns[j].e == e {
134			curN = ns[j].v
135			j++
136		}
137		rows = append(rows, strconv.FormatUint(uint64(e), 10)+":"+
138			strconv.FormatInt(curY, 10)+":"+strconv.FormatInt(curN, 10))
139	}
140	if len(rows) > seriesRowCap {
141		rows = rows[len(rows)-seriesRowCap:]
142		more = true
143	}
144	m := "0"
145	if more {
146		m = "1"
147	}
148	return grain + "," + strconv.FormatInt(width, 10) + "," +
149		strconv.FormatUint(uint64(now), 10) + "," + m + ";" +
150		strings.Join(rows, ",")
151}