-
Notifications
You must be signed in to change notification settings - Fork 31
/
metadata.go
100 lines (79 loc) · 2.58 KB
/
metadata.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package types
import (
"errors"
"fmt"
"strings"
sdk "github.com/Finschia/finschia-sdk/types"
)
// Validate performs a basic validation of the coin metadata fields. It checks:
// - Name and Symbol are not blank
// - Base and Display denominations are valid coin denominations
// - Base and Display denominations are present in the DenomUnit slice
// - Base denomination has exponent 0
// - Denomination units are sorted in ascending order
// - Denomination units not duplicated
func (m Metadata) Validate() error {
if strings.TrimSpace(m.Name) == "" {
return errors.New("name field cannot be blank")
}
if strings.TrimSpace(m.Symbol) == "" {
return errors.New("symbol field cannot be blank")
}
if err := sdk.ValidateDenom(m.Base); err != nil {
return fmt.Errorf("invalid metadata base denom: %w", err)
}
if err := sdk.ValidateDenom(m.Display); err != nil {
return fmt.Errorf("invalid metadata display denom: %w", err)
}
var (
hasDisplay bool
currentExponent uint32 // check that the exponents are increasing
)
seenUnits := make(map[string]bool)
for i, denomUnit := range m.DenomUnits {
// The first denomination unit MUST be the base
if i == 0 {
// validate denomination and exponent
if denomUnit.Denom != m.Base {
return fmt.Errorf("metadata's first denomination unit must be the one with base denom '%s'", m.Base)
}
if denomUnit.Exponent != 0 {
return fmt.Errorf("the exponent for base denomination unit %s must be 0", m.Base)
}
} else if currentExponent >= denomUnit.Exponent {
return errors.New("denom units should be sorted asc by exponent")
}
currentExponent = denomUnit.Exponent
if seenUnits[denomUnit.Denom] {
return fmt.Errorf("duplicate denomination unit %s", denomUnit.Denom)
}
if denomUnit.Denom == m.Display {
hasDisplay = true
}
if err := denomUnit.Validate(); err != nil {
return err
}
seenUnits[denomUnit.Denom] = true
}
if !hasDisplay {
return fmt.Errorf("metadata must contain a denomination unit with display denom '%s'", m.Display)
}
return nil
}
// Validate performs a basic validation of the denomination unit fields
func (du DenomUnit) Validate() error {
if err := sdk.ValidateDenom(du.Denom); err != nil {
return fmt.Errorf("invalid denom unit: %w", err)
}
seenAliases := make(map[string]bool)
for _, alias := range du.Aliases {
if seenAliases[alias] {
return fmt.Errorf("duplicate denomination unit alias %s", alias)
}
if strings.TrimSpace(alias) == "" {
return fmt.Errorf("alias for denom unit %s cannot be blank", du.Denom)
}
seenAliases[alias] = true
}
return nil
}