state.gno
4.88 Kb · 175 lines
1package bolo
2
3import (
4 "gno.land/p/nt/avl/v0"
5 "gno.land/p/nt/seqid/v0"
6)
7
8// Params are the settings snapshotted into each campaign when it is created
9// (API §2.2): its deposit and its timers never change afterwards (INV-5).
10// Durations are in seconds.
11type Params struct {
12 CreationDeposit int64
13 DormancyPeriod int64
14 ExitDelay int64
15 BondHold int64
16}
17
18// Custody modes, statuses and close reasons (API §2.1).
19const (
20 modeDirect = "direct"
21 modeEscrow = "escrow"
22
23 statusOpen = "open"
24 statusClosed = "closed"
25 statusSettled = "settled"
26
27 reasonOrganizer = "organizer"
28 reasonDeadline = "deadline"
29 reasonDormant = "dormant"
30)
31
32// campaign holds what never changes once a campaign is created (INV-10), and
33// points to what does. Gno re-saves a changed object and every object that owns
34// it, up to the first with two owners, so each donation re-saves this object with
35// its hot state and its trees: it holds only small fields, and the organizer's
36// text lives in its own object, written once (API §2.5).
37type campaign struct {
38 id seqid.ID
39 category string
40 organizer address
41 beneficiary address
42 mode string // modeDirect or modeEscrow
43 goal int64 // ugnot; 0: no goal
44 deadline int64 // Unix seconds; 0: none
45 createdAt int64
46 params Params
47
48 text *campaignText // written once; read by views and Render
49 state *campaignState // counters, timers and flags
50
51 // One object each, keyed by donor address or by seqid.Binary(): a donation
52 // writes O(log n) small nodes, not the campaign's history.
53 contributions *avl.Tree // address → *contribution
54 receipts *avl.Tree // seq → *receipt
55 withdrawals *avl.Tree // seq → *withdrawal
56 refunds *avl.Tree // seq → *refund
57 updates *avl.Tree // seq → *update
58}
59
60// campaignText is what the organizer wrote, which never changes (INV-10): written
61// once, off the path every donation re-saves.
62type campaignText struct {
63 title string
64 description string
65 imageCID string
66 imageAlt string
67}
68
69const recentSize = 20
70
71// campaignState is a campaign's hot object: small, rewritten on every donation.
72type campaignState struct {
73 status string // as stored; a passed deadline counts as closed before it is recorded
74 closeReason string
75 closedAt int64
76 listed bool
77 notice string
78 imageHidden bool
79
80 raised int64 // gross: every donation ever
81 refunded int64
82 withdrawn int64 // tracked coins only; untracked ones are counted apart
83
84 donorCount int
85 donationCount int
86 refundCount int
87 updateCount int
88
89 bond int64
90 bondSlashed bool
91 bondReleased bool
92
93 lastDonationAt int64
94 lastUpdateAt int64
95 everWithdrawn bool // ends the open refund window for good
96
97 // The exit window's snapshot, frozen by the first exit claim (API §3.2).
98 exitFrozen bool
99 exitPool int64
100 exitBase int64
101
102 // The last donations' sequence numbers, a ring: numbers, not receipts.
103 recent [recentSize]uint64
104 recentNext int
105
106 receiptSeq seqid.ID
107 withdrawalSeq seqid.ID
108 refundSeq seqid.ID
109 updateSeq seqid.ID
110}
111
112// contribution is one donor's record in one campaign (API §3.2).
113type contribution struct {
114 amount int64 // everything given
115 refunded int64 // everything paid back
116 exitClaimed bool // the one exit claim is used (INV-17)
117 public bool // at least one gift wasn't anonymous
118}
119
120// receipt is one donation.
121type receipt struct {
122 seq uint64
123 donor address
124 anonymous bool
125 amount int64
126 tip int64
127 message string
128 messageHidden bool
129 at int64
130 raisedAfter int64
131
132 refundedBefore int64 // what this donor was refunded on this campaign before this gift
133}
134
135// withdrawal is one payout to the beneficiary.
136type withdrawal struct {
137 seq uint64
138 amount int64 // tracked coins
139 untracked int64 // coins sent to the escrow outside Bolo
140 at int64
141 to address
142}
143
144// refund is one payout to a donor.
145type refund struct {
146 seq uint64
147 amount int64
148 at int64
149 donor address
150 kind string // "open" or "exit"
151}
152
153// update is one organizer update: append-only.
154type update struct {
155 seq uint64
156 at int64
157 body string
158}
159
160// Package state, all unexported (API C6).
161var (
162 nextID seqid.ID // the last campaign ID given out
163 campaigns avl.Tree // seqid.Binary() → *campaign
164
165 // derived holds every escrow and bond address a campaign ever got: none of
166 // them may be a beneficiary (API §1).
167 derived avl.Tree // address → true
168
169 // The indexes (API §2.5): keys sort newest campaign last.
170 active avl.Tree // seqid.Binary() → true: the open, listed campaigns
171 activeByCategory avl.Tree // category + "/" + seqid.Binary() → true: the same
172 byOrganizer avl.Tree // organizer + "/" + seqid.Binary() → true
173 byBeneficiary avl.Tree // beneficiary + "/" + seqid.Binary() → true
174 byDonor avl.Tree // donor + "/" + seqid.Binary() → true: a gift that wasn't anonymous
175)