Search Apps Documentation Source Content File Folder Download Copy Actions Download

validation.gno

3.35 Kb · 145 lines
  1package block
  2
  3import (
  4	"strconv"
  5	"strings"
  6	"unicode/utf8"
  7
  8	"gno.land/p/akkadia/v0/validate"
  9)
 10
 11const maxBlockNameLength = 30
 12
 13// Validation helpers in this file are for value-level checks at public API boundaries.
 14//
 15// Add helpers here when they validate a parameter or payload value without
 16// depending on mutable contract state or call flow. Store-owned existence,
 17// duplicate, and index consistency checks stay in the relevant store.
 18func assertBlockName(name string) {
 19	if name == "" {
 20		panic("name cannot be empty")
 21	}
 22	if utf8.RuneCountInString(name) > maxBlockNameLength {
 23		panic("name too long (max 30)")
 24	}
 25	trimmed := strings.TrimSpace(name)
 26	if trimmed == "" {
 27		panic("name cannot be only whitespace")
 28	}
 29	if name != trimmed {
 30		panic("name cannot have leading or trailing whitespace")
 31	}
 32	for i := 0; i < len(name); i++ {
 33		switch name[i] {
 34		case ',', '|', '/', '\\', '<', '>', '[', ']', '(', ')', '{', '}', '#', '*', '`':
 35			panic("name contains invalid characters")
 36		}
 37		if name[i] < 0x20 || name[i] == 0x7f {
 38			panic("name contains invalid characters")
 39		}
 40	}
 41}
 42
 43func assertNormalMaxSupply(maxSupply uint32) {
 44	if maxSupply == 0 {
 45		panic("max supply must be greater than 0")
 46	}
 47}
 48
 49func assertSystemMaxSupply(maxSupply int64) {
 50	if maxSupply < -1 {
 51		panic("max supply must be greater than -2")
 52	}
 53}
 54
 55func assertInstallerBPS(installerBPS uint32) {
 56	if installerBPS > 10000 {
 57		panic("installer bps must be between 0 and 10000")
 58	}
 59}
 60
 61func assertMetadata(metadata string) {
 62	validate.AssertStringTextLen(metadata, true, "block metadata")
 63}
 64
 65func assertExactPayment(expected int64, actual int64) {
 66	if actual != expected {
 67		panic("exact payment required: expected " + strconv.FormatInt(expected, 10) + ", got " + strconv.FormatInt(actual, 10))
 68	}
 69}
 70
 71func mustParseUint32Field(props map[string]string, key string) uint32 {
 72	return mustParseUint32(props[key])
 73}
 74
 75func mustParseInt64Field(props map[string]string, key string) int64 {
 76	return mustParseInt64(props[key])
 77}
 78
 79func mustParseUint32(val string) uint32 {
 80	value, err := strconv.ParseUint(val, 10, 32)
 81	if err != nil {
 82		panic("invalid uint32: " + err.Error())
 83	}
 84	return uint32(value)
 85}
 86
 87func mustParseUint8(val string) uint8 {
 88	value, err := strconv.ParseUint(val, 10, 8)
 89	if err != nil {
 90		panic("invalid uint8: " + err.Error())
 91	}
 92	return uint8(value)
 93}
 94
 95func mustParseInt64(val string) int64 {
 96	value, err := strconv.ParseInt(val, 10, 64)
 97	if err != nil {
 98		panic("invalid int64: " + err.Error())
 99	}
100	return value
101}
102
103func mustParseAddress(str string) address {
104	addr := address(str)
105	if !addr.IsValid() {
106		panic("invalid address: " + str)
107	}
108	return addr
109}
110
111func assertListPageCount(page int, count int) {
112	if page < 1 {
113		panic("page must be at least 1")
114	}
115	if count < 1 {
116		panic("count must be at least 1")
117	}
118	assertListLimit("count", count)
119}
120
121func assertListLimit(field string, count int) {
122	if count > listLimit {
123		panic(field + " exceeds listLimit (max: " + strconv.Itoa(listLimit) + ")")
124	}
125}
126
127func parseMintAllowlistCSV(minters string) []address {
128	if minters == "" {
129		panic("minters must not be empty")
130	}
131
132	result := []address{}
133	start := 0
134	for i := 0; i <= len(minters); i++ {
135		if i == len(minters) || minters[i] == ',' {
136			addr := strings.TrimSpace(minters[start:i])
137			if addr == "" {
138				panic("empty address not allowed")
139			}
140			result = append(result, mustParseAddress(addr))
141			start = i + 1
142		}
143	}
144	return result
145}