@@ -3,10 +3,18 @@ package launchpad
3
3
import (
4
4
"errors"
5
5
"std"
6
+ "strconv"
7
+ "strings"
6
8
7
9
"gno.land/p/demo/ufmt"
8
10
)
9
11
12
+ var (
13
+ errEmptyTokenPath = errors.New("token path cannot be empty")
14
+ errInvalidAddress = errors.New("invalid address")
15
+ errZeroDepositAmount = errors.New("deposit amount cannot be 0")
16
+ )
17
+
10
18
// region: projectInput
11
19
12
20
// ProjectInput defines the input parameters required to create a project.
@@ -87,8 +95,37 @@ func NewProjectInput(
87
95
}
88
96
}
89
97
90
- // CheckName checks if the project name is valid.
91
- func (p *projectInput) CheckName() error {
98
+ // CheckAll checks all the project input fields.
99
+ // need to pass `IsRegistered` function as a callback parameter to check if the token is registered.
100
+ func (p *projectInput) CheckAll(now uint64, f func(string) error) (tokenConditionMap, error) {
101
+ if err := p.checkName(); err != nil {
102
+ return nil, err
103
+ }
104
+ if err := p.checkTokenPath(f); err != nil {
105
+ return nil, err
106
+ }
107
+ if err := p.checkRecipient(); err != nil {
108
+ return nil, err
109
+ }
110
+ if err := p.checkDepositAmount(); err != nil {
111
+ return nil, err
112
+ }
113
+ if err := p.checkRatio(); err != nil {
114
+ return nil, err
115
+ }
116
+ if err := p.checkStartTime(now); err != nil {
117
+ return nil, err
118
+ }
119
+
120
+ conds, err := p.parseConditions(f)
121
+ if err != nil {
122
+ return nil, err
123
+ }
124
+ return conds, nil
125
+ }
126
+
127
+ // checkName checks if the project name is valid.
128
+ func (p *projectInput) checkName() error {
92
129
if p.name == "" {
93
130
return errors.New("project name cannot be empty")
94
131
}
@@ -98,8 +135,8 @@ func (p *projectInput) CheckName() error {
98
135
return nil
99
136
}
100
137
101
- // VerifyRatio checks if the sum of the tier ratios equals 100.
102
- func (p *projectInput) VerifyRatio () error {
138
+ // checkRatio checks if the sum of the tier ratios equals 100.
139
+ func (p *projectInput) checkRatio () error {
103
140
if p.tierSum() != 100 {
104
141
return ufmt.Errorf(
105
142
"invalid ratio, sum of all tiers(30:%d, 90:%d, 180:%d) should be 100",
@@ -113,14 +150,101 @@ func (p *projectInput) tierSum() uint64 {
113
150
return p.Tier30Ratio() + p.Tier90Ratio() + p.Tier180Ratio()
114
151
}
115
152
116
- // ValidateStartTime checks if the start time is in the future.
117
- func (p *projectInput) ValidateStartTime (now uint64) error {
153
+ // checkStartTime checks if the start time is in the future.
154
+ func (p *projectInput) checkStartTime (now uint64) error {
118
155
if p.startTime <= now {
119
156
return errors.New("start time must be greater than now")
120
157
}
121
158
return nil
122
159
}
123
160
161
+ func (p *projectInput) checkTokenPath(f func(string) error) error {
162
+ path := p.TokenPath()
163
+ if path == "" {
164
+ return errEmptyTokenPath
165
+ }
166
+ if err := f(path); err != nil {
167
+ return err
168
+ }
169
+ return nil
170
+ }
171
+
172
+ func (p *projectInput) checkRecipient() error {
173
+ if !p.Recipient().IsValid() {
174
+ return errInvalidAddress
175
+ }
176
+ return nil
177
+ }
178
+
179
+ func (p *projectInput) checkDepositAmount() error {
180
+ if p.DepositAmount() == 0 {
181
+ return errZeroDepositAmount
182
+ }
183
+ return nil
184
+ }
185
+
186
+ // ParseConditions parses the conditions from `ConditionsToken` and `ConditionsAmount`.
187
+ //
188
+ // Splits the token and amount strings using `*PAD*`, validates each token path, and converts
189
+ // the amounts to integers. Returns a map of token paths to their corresponding conditions.
190
+ func (p *projectInput) parseConditions(f func(string) error) (tokenConditionMap, error) {
191
+ if p.ConditionsToken() == "" || p.ConditionsAmount() == "" {
192
+ return nil, nil
193
+ }
194
+
195
+ return parseConditions(p.ConditionsToken(), p.ConditionsAmount(), f)
196
+ }
197
+
198
+ func parseConditions(condToken, condAmount string, f func(string) error) (tokenConditionMap, error) {
199
+ tokens, amounts, err := trySplitConditions(condToken, condAmount)
200
+ if err != nil {
201
+ return nil, err
202
+ }
203
+
204
+ return buildTokenConditions(tokens, amounts, f)
205
+ }
206
+
207
+ func trySplitConditions(tokenStr, amountStr string) (tokens, amounts []string, err error) {
208
+ if tokenStr == "" || amountStr == "" {
209
+ return nil, nil, errors.New("conditionsToken or conditionsAmount cannot be empty")
210
+ }
211
+
212
+ tokens = strings.Split(tokenStr, PAD_SEP)
213
+ amounts = strings.Split(amountStr, PAD_SEP)
214
+ if len(tokens) != len(amounts) {
215
+ return nil, nil, ufmt.Errorf("length of tokens(%d) and amounts(%d) are not same", len(tokens), len(amounts))
216
+ }
217
+
218
+ return tokens, amounts, nil
219
+ }
220
+
221
+ func buildTokenConditions(tokens, amounts []string, f func(string) error) (tokenConditionMap, error) {
222
+ condition := make(tokenConditionMap)
223
+
224
+ for i, tok := range tokens {
225
+ if tok == "" {
226
+ return nil, ufmt.Errorf("invalid token(%s)", tok)
227
+ }
228
+ if err := f(tok); err != nil {
229
+ return nil, ufmt.Errorf("token(%s) not registered", tok)
230
+ }
231
+ if _, exists := condition[tok]; exists {
232
+ return nil, ufmt.Errorf("duplicated condition token(%s)", tok)
233
+ }
234
+
235
+ amtv, err := strconv.ParseUint(amounts[i], 10, 64)
236
+ if err != nil {
237
+ return nil, ufmt.Errorf("invalid amount(%s)", amounts[i])
238
+ }
239
+
240
+ condition[tok] = Condition{
241
+ tokenPath: tok,
242
+ minAmount: amtv,
243
+ }
244
+ }
245
+ return condition, nil
246
+ }
247
+
124
248
// region: ProjectCalculationResult
125
249
126
250
// ProjectCalculationResult middle result of project params calculation
0 commit comments