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.

profile.gno

3.73 Kb · 155 lines
  1package gnocial
  2
  3import (
  4	"chain"
  5	"chain/runtime"
  6	"strconv"
  7	"strings"
  8)
  9
 10// Register opens a profile for the calling account.
 11// handle is 3–16 chars of a-z, 0-9 and underscore. referrer may be empty
 12// or the bech32 address of an existing member. A member can register once.
 13func Register(cur realm, handle, name, bio, referrer string) {
 14	who := caller(cur)
 15	mustNoPay()
 16	if profileByAddr(who) != nil {
 17		panic("already registered")
 18	}
 19	handle = strings.ToLower(strings.TrimSpace(handle))
 20	if !validHandle(handle) {
 21		panic("bad handle")
 22	}
 23	if state.byHandle.Has(handle) {
 24		panic("handle taken")
 25	}
 26	if name == "" {
 27		name = handle
 28	}
 29	name = cleanLine(name, maxNameRunes, maxNameBytes, "name", false)
 30	bio = cleanLine(bio, maxBioRunes, maxBioBytes, "bio", true)
 31
 32	var ref address
 33	referrer = strings.TrimSpace(referrer)
 34	if referrer != "" {
 35		if len(referrer) > 60 {
 36			panic("bad referrer")
 37		}
 38		ref = address(referrer)
 39		if !ref.IsValid() {
 40			panic("bad referrer")
 41		}
 42		if ref == who {
 43			panic("self referral")
 44		}
 45		if profileByAddr(ref) == nil {
 46			panic("referrer not registered")
 47		}
 48	}
 49
 50	p := &Profile{
 51		Addr:       who,
 52		Handle:     handle,
 53		Name:       name,
 54		Bio:        bio,
 55		Referrer:   ref,
 56		Joined:     runtime.ChainHeight(),
 57		CreatorFee: CreatorFeeDefaultBps,
 58	}
 59	state.byAddr.Set(who.String(), p)
 60	state.byHandle.Set(handle, p)
 61	state.books.Set(who.String(), &book{})
 62	chain.Emit(
 63		"ArenaRegister",
 64		"addr", who.String(),
 65		"handle", handle,
 66		"referrer", ref.String(),
 67	)
 68}
 69
 70// SetCreatorFee stores this member's share of each ticket trade, in basis points.
 71// Only that member can change it. The trade total stays FeeCapBps.
 72func SetCreatorFee(cur realm, points int64) {
 73	who := caller(cur)
 74	mustNoPay()
 75	p := mustMember(who)
 76	if points < CreatorFeeMinBps || points > CreatorFeeMaxBps {
 77		panic("fee")
 78	}
 79	p.CreatorFee = points
 80	chain.Emit(
 81		"ArenaCreatorFee",
 82		"addr", who.String(),
 83		"handle", p.Handle,
 84		"bps", strconv.FormatInt(points, 10),
 85	)
 86}
 87
 88// UpdateProfile replaces the display name and bio. The handle stays.
 89func UpdateProfile(cur realm, name, bio string) {
 90	who := caller(cur)
 91	mustNoPay()
 92	p := mustMember(who)
 93	if strings.TrimSpace(name) == "" {
 94		name = p.Handle
 95	}
 96	p.Name = cleanLine(name, maxNameRunes, maxNameBytes, "name", false)
 97	p.Bio = cleanLine(bio, maxBioRunes, maxBioBytes, "bio", true)
 98	chain.Emit("ArenaProfile", "addr", who.String(), "handle", p.Handle)
 99}
100
101// Follow records that the caller follows handle.
102func Follow(cur realm, handle string) {
103	who := caller(cur)
104	mustNoPay()
105	self := mustMember(who)
106	target := lookup(handle)
107	if target == nil {
108		panic("unknown handle")
109	}
110	if target.Addr == who {
111		panic("cannot follow self")
112	}
113	k := followKey(who, target.Addr)
114	if state.follows.Has(k) {
115		panic("already following")
116	}
117	state.follows.Set(k, 1)
118	state.fans.Set(fanKey(target.Addr, who), 1)
119	self.Following++
120	target.Followers++
121	chain.Emit("ArenaFollow", "from", who.String(), "to", target.Addr.String(), "handle", target.Handle)
122}
123
124// Unfollow removes a follow.
125func Unfollow(cur realm, handle string) {
126	who := caller(cur)
127	mustNoPay()
128	self := mustMember(who)
129	target := lookup(handle)
130	if target == nil {
131		panic("unknown handle")
132	}
133	k := followKey(who, target.Addr)
134	if !state.follows.Has(k) {
135		panic("not following")
136	}
137	state.follows.Remove(k)
138	state.fans.Remove(fanKey(target.Addr, who))
139	if self.Following > 0 {
140		self.Following--
141	}
142	if target.Followers > 0 {
143		target.Followers--
144	}
145	chain.Emit("ArenaUnfollow", "from", who.String(), "to", target.Addr.String(), "handle", target.Handle)
146}
147
148// Following reports whether from follows the handle.
149func Following(from address, handle string) bool {
150	target := lookup(handle)
151	if target == nil {
152		return false
153	}
154	return state.follows.Has(followKey(from, target.Addr))
155}