-
Notifications
You must be signed in to change notification settings - Fork 3.6k
/
denom.go
147 lines (121 loc) · 3.63 KB
/
denom.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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package types
import (
"fmt"
)
// denomUnits contains a mapping of denomination mapped to their respective unit
// multipliers (e.g. 1atom = 10^-6uatom).
var denomUnits = map[string]Dec{}
// baseDenom is the denom of smallest unit registered
var baseDenom string
// RegisterDenom registers a denomination with a corresponding unit. If the
// denomination is already registered, an error will be returned.
func RegisterDenom(denom string, unit Dec) error {
if err := ValidateDenom(denom); err != nil {
return err
}
if _, ok := denomUnits[denom]; ok {
return fmt.Errorf("denom %s already registered", denom)
}
denomUnits[denom] = unit
if baseDenom == "" || unit.LT(denomUnits[baseDenom]) {
baseDenom = denom
}
return nil
}
// GetDenomUnit returns a unit for a given denomination if it exists. A boolean
// is returned if the denomination is registered.
func GetDenomUnit(denom string) (Dec, bool) {
if err := ValidateDenom(denom); err != nil {
return ZeroDec(), false
}
unit, ok := denomUnits[denom]
if !ok {
return ZeroDec(), false
}
return unit, true
}
// GetBaseDenom returns the denom of smallest unit registered
func GetBaseDenom() (string, error) {
if baseDenom == "" {
return "", fmt.Errorf("no denom is registered")
}
return baseDenom, nil
}
// ConvertCoin attempts to convert a coin to a given denomination. If the given
// denomination is invalid or if neither denomination is registered, an error
// is returned.
func ConvertCoin(coin Coin, denom string) (Coin, error) {
if err := ValidateDenom(denom); err != nil {
return Coin{}, err
}
srcUnit, ok := GetDenomUnit(coin.Denom)
if !ok {
return Coin{}, fmt.Errorf("source denom not registered: %s", coin.Denom)
}
dstUnit, ok := GetDenomUnit(denom)
if !ok {
return Coin{}, fmt.Errorf("destination denom not registered: %s", denom)
}
if srcUnit.Equal(dstUnit) {
return NewCoin(denom, coin.Amount), nil
}
return NewCoin(denom, coin.Amount.ToDec().Mul(srcUnit).Quo(dstUnit).TruncateInt()), nil
}
// ConvertDecCoin attempts to convert a decimal coin to a given denomination. If the given
// denomination is invalid or if neither denomination is registered, an error
// is returned.
func ConvertDecCoin(coin DecCoin, denom string) (DecCoin, error) {
if err := ValidateDenom(denom); err != nil {
return DecCoin{}, err
}
srcUnit, ok := GetDenomUnit(coin.Denom)
if !ok {
return DecCoin{}, fmt.Errorf("source denom not registered: %s", coin.Denom)
}
dstUnit, ok := GetDenomUnit(denom)
if !ok {
return DecCoin{}, fmt.Errorf("destination denom not registered: %s", denom)
}
if srcUnit.Equal(dstUnit) {
return NewDecCoinFromDec(denom, coin.Amount), nil
}
return NewDecCoinFromDec(denom, coin.Amount.Mul(srcUnit).Quo(dstUnit)), nil
}
// NormalizeCoin try to convert a coin to the smallest unit registered,
// returns original one if failed.
func NormalizeCoin(coin Coin) Coin {
base, err := GetBaseDenom()
if err != nil {
return coin
}
newCoin, err := ConvertCoin(coin, base)
if err != nil {
return coin
}
return newCoin
}
// NormalizeDecCoin try to convert a decimal coin to the smallest unit registered,
// returns original one if failed.
func NormalizeDecCoin(coin DecCoin) DecCoin {
base, err := GetBaseDenom()
if err != nil {
return coin
}
newCoin, err := ConvertDecCoin(coin, base)
if err != nil {
return coin
}
return newCoin
}
// NormalizeCoins normalize and truncate a list of decimal coins
func NormalizeCoins(coins []DecCoin) Coins {
if coins == nil {
return nil
}
result := make([]Coin, 0, len(coins))
for _, coin := range coins {
newCoin, _ := NormalizeDecCoin(coin).TruncateDecimal()
result = append(result, newCoin)
}
return result
}