@@ -3,10 +3,18 @@ package launchpad
33import (
44 "errors"
55 "std"
6+ "strconv"
7+ "strings"
68
79 "gno.land/p/demo/ufmt"
810)
911
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+
1018// region: projectInput
1119
1220// ProjectInput defines the input parameters required to create a project.
@@ -87,8 +95,37 @@ func NewProjectInput(
8795 }
8896}
8997
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 {
92129 if p.name == "" {
93130 return errors.New("project name cannot be empty")
94131 }
@@ -98,8 +135,8 @@ func (p *projectInput) CheckName() error {
98135 return nil
99136}
100137
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 {
103140 if p.tierSum() != 100 {
104141 return ufmt.Errorf(
105142 "invalid ratio, sum of all tiers(30:%d, 90:%d, 180:%d) should be 100",
@@ -113,14 +150,101 @@ func (p *projectInput) tierSum() uint64 {
113150 return p.Tier30Ratio() + p.Tier90Ratio() + p.Tier180Ratio()
114151}
115152
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 {
118155 if p.startTime <= now {
119156 return errors.New("start time must be greater than now")
120157 }
121158 return nil
122159}
123160
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+
124248// region: ProjectCalculationResult
125249
126250// ProjectCalculationResult middle result of project params calculation
0 commit comments