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