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.

close.gno

2.45 Kb · 71 lines
 1package bolo
 2
 3import (
 4	"chain"
 5	"chain/runtime"
 6)
 7
 8// Close closes campaign id to new donations. Its organizer can, at any time; anyone
 9// can, once it is past its deadline or inactive for long enough — the campaign's page
10// says when. Closing stops gifts only: what the campaign holds still goes to the
11// beneficiary, or back to its donors.
12//
13// Its branch follows state, never the caller (API §3.1, Q7). Past its deadline, Close
14// records the close if nothing has yet, and never fails. A dormant campaign closes as
15// dormant, whoever calls. Only an open campaign nobody else may close yet takes the
16// organizer's branch, which checks how the call arrived (C11) before it reads who
17// sent it.
18func Close(cur realm, id string) {
19	assertCurrent(cur)
20	c := campaignOf(id)
21	recordDeadline(cur, c)
22	if c.deadline != 0 && now() >= c.deadline {
23		return // recorded above, now or before: housekeeping, never an error
24	}
25	assertOpen(c)
26	if now() >= dormantAt(c) {
27		closeNow(c, reasonDormant, cur.Previous().Address())
28		return
29	}
30	if !cur.Previous().IsUserCall() {
31		panic(ErrNotUserCall)
32	}
33	runtime.AssertOriginCall()
34	if cur.Previous().Address() != c.organizer {
35		panic(ErrNotClosable)
36	}
37	closeNow(c, reasonOrganizer, c.organizer)
38}
39
40// closeNow closes the open campaign c now, for reason, and takes it out of the
41// active indexes; Closed names by, who sent the call (API §3.1, §6).
42func closeNow(c *campaign, reason string, by address) {
43	s := c.state
44	s.status, s.closedAt, s.closeReason = statusClosed, now(), reason
45	stats.open--
46	dropActive(c)
47	chain.Emit(evClosed, "id", idString(c.id), "reason", reason, "by", by.String())
48}
49
50// closeNotYet is CanClose's reason while only the organizer may close.
51const closeNotYet = "not_yet"
52
53// CanClose says what Close(id), sent by caller from a wallet, would do now (API
54// §4): true, with the reason it would record — "deadline" or "dormant" for anyone,
55// "organizer" for the organizer alone — or false, with "closed" once closed or
56// settled, and "not_yet" while only the organizer may close.
57func CanClose(id string, caller address) (bool, string) {
58	c := campaignOf(id)
59	status, _, _ := effective(c)
60	switch {
61	case status != statusOpen && c.state.status == statusOpen:
62		return true, reasonDeadline // passed, not yet recorded
63	case status != statusOpen:
64		return false, statusClosed
65	case now() >= dormantAt(c):
66		return true, reasonDormant
67	case caller == c.organizer:
68		return true, reasonOrganizer
69	}
70	return false, closeNotYet
71}