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

support.gno

4.54 Kb · 136 lines
  1package catalog
  2
  3import (
  4	"chain"
  5	"chain/banker"
  6	"strings"
  7	"time"
  8
  9	"gno.land/p/nym-alexiscolin000/gnoradio/role/v0"
 10	"gno.land/p/nym-alexiscolin000/gnoradio/store/v0"
 11	"gno.land/p/nym-alexiscolin000/gnoradio/text/v0"
 12	"gno.land/r/nym-alexiscolin000/gnoradio/data"
 13)
 14
 15// GnoRadio's own funding, always on top of what artists receive and always
 16// visible on-chain: direct support and the optional share added to a tip.
 17// Every coin is forwarded to the treasury in the same transaction.
 18
 19// SupportGnoRadio sends the attached ugnot to the GnoRadio treasury.
 20func SupportGnoRadio(cur realm) {
 21	caller := userCaller(cur)
 22	amt := paid()
 23	if amt < minTip || amt > maxTip {
 24		panic("catalog: support is between 0.1 and 1000000 GNOT")
 25	}
 26	t := rd()
 27	if treasury(t) == "" {
 28		panic("catalog: no treasury is set, GnoRadio takes no support")
 29	}
 30	bk := banker.NewBanker(banker.BankerTypeRealmSend, cur)
 31	bk.SendCoins(cur.Address(), treasury(t), chain.Coins{{Denom: denom, Amount: amt}})
 32	recordSupport(t, caller, amt)
 33	save(cur, t)
 34	emitEvent("Supported", "by", caller.String(), "amount", text.Itoa64(amt))
 35}
 36
 37// SetTreasury changes where GnoRadio's support goes; "" (the default) takes none. Admin only.
 38func SetTreasury(cur realm, to address) {
 39	onlyAdmin(cur)
 40	if to != "" && !role.Canonical(to) { // "" switches support off
 41		panic("catalog: invalid address")
 42	}
 43	if data.IsGnoRadio(to) {
 44		panic("catalog: the treasury cannot be a GnoRadio realm")
 45	}
 46	t := rd()
 47	emitEvent("TreasuryChanged", "from", treasury(t).String(), "to", to.String())
 48	t.set(cConfig, "treasury", to.String())
 49	save(cur, t)
 50}
 51
 52// SetMonthlyGoal sets the monthly support goal shown in the app (ugnot). Admin only.
 53func SetMonthlyGoal(cur realm, ugnot int64) {
 54	onlyAdmin(cur)
 55	if ugnot < 0 || ugnot > maxTip {
 56		panic("catalog: goal out of range")
 57	}
 58	t := rd()
 59	t.set(cConfig, "goal", text.Itoa64(ugnot))
 60	save(cur, t)
 61	emitEvent("MonthlyGoal", "ugnot", text.Itoa64(ugnot))
 62}
 63
 64func treasury(t *tx) address { return address(t.val(cConfig, "treasury")) }
 65
 66func Treasury() address { return treasury(rd()) }
 67
 68// SupportInfo returns GnoRadio's public funding state for this month.
 69func SupportInfo() (to address, total int64, supporters int, monthTotal, goal int64) {
 70	t := rd()
 71	return treasury(t), t.count(mSupport), int(t.count(mSupporters)), text.Atoi64(t.val(cMonthly, month(now()))), text.Atoi64(t.val(cConfig, "goal"))
 72}
 73
 74func recordSupport(t *tx, by address, amt int64) {
 75	t.bump(mSupport, amt)
 76	s, had := t.get(cSupporters, by.String())
 77	if !had {
 78		t.bump(mSupporters, 1)
 79	}
 80	total := text.Atoi64(s) + amt
 81	t.set(cSupporters, by.String(), text.Itoa64(total))
 82	t.rank(topSupport, by.String(), total, true)
 83	mo := month(now())
 84	t.set(cMonthly, mo, text.Itoa64(text.Atoi64(t.val(cMonthly, mo))+amt))
 85	t.activity("support", by, "0", "0", text.Itoa64(amt))
 86}
 87
 88func month(unix int64) string { return time.Unix(unix, 0).UTC().Format("2006-01") }
 89
 90// Activities returns up to limit entries, newest first.
 91func Activities(limit int) []Activity {
 92	limit = store.Limit(limit, activitySize)
 93	t := rd()
 94	head := text.Atoi(t.val(cMeta, "head"))
 95	out := make([]Activity, 0, limit)
 96	for i := 1; i <= limit; i++ {
 97		v := t.val(cActivity, store.Pad((head-i+activitySize)%activitySize))
 98		if v == "" {
 99			break // the ring is not full yet
100		}
101		f := store.Fields(v)
102		out = append(out, Activity{Kind: f[0], By: address(f[1]), Track: text.Atoi(f[2]), Artist: text.Atoi(f[3]), Amount: text.Atoi64(f[4]), At: text.Atoi64(f[5])})
103	}
104	return out
105}
106
107// ActivityJSON returns the activity feed, newest first (limit <= 64).
108func ActivityJSON(limit int) string {
109	var b strings.Builder
110	b.WriteString("[")
111	for i, a := range Activities(limit) {
112		if i > 0 {
113			b.WriteString(",")
114		}
115		b.WriteString(`{"kind":` + text.Str(a.Kind) + `,"by":` + text.Str(a.By.String()) + `,"track":` + text.Itoa(a.Track) +
116			`,"artist":` + text.Itoa(a.Artist) + `,"amount":` + text.Itoa64(a.Amount) + `,"at":` + text.Itoa64(a.At) + `}`)
117	}
118	b.WriteString("]")
119	return b.String()
120}
121
122// SupportJSON returns GnoRadio's public funding state.
123func SupportJSON() string {
124	to, total, supporters, mt, goal := SupportInfo()
125	var b strings.Builder
126	b.WriteString(`{"treasury":` + text.Str(to.String()) + `,"total":` + text.Itoa64(total) + `,"supporters":` + text.Itoa(supporters) +
127		`,"month":` + text.Str(month(now())) + `,"monthTotal":` + text.Itoa64(mt) + `,"goal":` + text.Itoa64(goal) + `,"top":[`)
128	for i, r := range rd().top(topSupport) {
129		if i > 0 {
130			b.WriteString(",")
131		}
132		b.WriteString(`{"address":` + text.Str(r.Key) + `,"amount":` + text.Itoa64(r.Value) + `}`)
133	}
134	b.WriteString(`]}`)
135	return b.String()
136}