R4R: Add custom validation for denom (#6755)
Allow ValidateDenom to be customized per application. closes: #6744
This commit is contained in:
+24
-7
@@ -602,15 +602,32 @@ var (
|
||||
reAmt = `[[:digit:]]+`
|
||||
reDecAmt = `[[:digit:]]*\.[[:digit:]]+`
|
||||
reSpc = `[[:space:]]*`
|
||||
reDnm = regexp.MustCompile(fmt.Sprintf(`^%s$`, reDnmString))
|
||||
reCoin = regexp.MustCompile(fmt.Sprintf(`^(%s)%s(%s)$`, reAmt, reSpc, reDnmString))
|
||||
reDecCoin = regexp.MustCompile(fmt.Sprintf(`^(%s)%s(%s)$`, reDecAmt, reSpc, reDnmString))
|
||||
reDnm = returnReDnm
|
||||
reCoin = returnReCoin
|
||||
reDecCoin = returnDecCoin
|
||||
)
|
||||
|
||||
// ValidateDenom validates a denomination string returning an error if it is
|
||||
// invalid.
|
||||
func returnDecCoin() *regexp.Regexp {
|
||||
return regexp.MustCompile(fmt.Sprintf(`^(%s)%s(%s)$`, reDecAmt, reSpc, CoinDenomRegex()))
|
||||
}
|
||||
func returnReCoin() *regexp.Regexp {
|
||||
return regexp.MustCompile(fmt.Sprintf(`^(%s)%s(%s)$`, reAmt, reSpc, CoinDenomRegex()))
|
||||
}
|
||||
func returnReDnm() *regexp.Regexp {
|
||||
return regexp.MustCompile(fmt.Sprintf(`^%s$`, CoinDenomRegex()))
|
||||
}
|
||||
|
||||
// DefaultCoinDenomRegex returns the default regex string
|
||||
func DefaultCoinDenomRegex() string {
|
||||
return reDnmString
|
||||
}
|
||||
|
||||
// CoinDenomRegex returns the current regex string and can be overwritten for custom validation
|
||||
var CoinDenomRegex = DefaultCoinDenomRegex
|
||||
|
||||
// ValidateDenom is the default validation function for Coin.Denom.
|
||||
func ValidateDenom(denom string) error {
|
||||
if !reDnm.MatchString(denom) {
|
||||
if !reDnm().MatchString(denom) {
|
||||
return fmt.Errorf("invalid denom: %s", denom)
|
||||
}
|
||||
return nil
|
||||
@@ -628,7 +645,7 @@ func mustValidateDenom(denom string) {
|
||||
func ParseCoin(coinStr string) (coin Coin, err error) {
|
||||
coinStr = strings.TrimSpace(coinStr)
|
||||
|
||||
matches := reCoin.FindStringSubmatch(coinStr)
|
||||
matches := reCoin().FindStringSubmatch(coinStr)
|
||||
if matches == nil {
|
||||
return Coin{}, fmt.Errorf("invalid coin expression: %s", coinStr)
|
||||
}
|
||||
|
||||
@@ -98,6 +98,30 @@ func (s *coinTestSuite) TestCoinIsValid() {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *coinTestSuite) TestCustomValidation() {
|
||||
|
||||
newDnmRegex := `[\x{1F600}-\x{1F6FF}]`
|
||||
sdk.CoinDenomRegex = func() string {
|
||||
return newDnmRegex
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
coin sdk.Coin
|
||||
expectPass bool
|
||||
}{
|
||||
{sdk.Coin{"🙂", sdk.NewInt(1)}, true},
|
||||
{sdk.Coin{"🙁", sdk.NewInt(1)}, true},
|
||||
{sdk.Coin{"🌶", sdk.NewInt(1)}, false}, // outside the unicode range listed above
|
||||
{sdk.Coin{"asdf", sdk.NewInt(1)}, false},
|
||||
{sdk.Coin{"", sdk.NewInt(1)}, false},
|
||||
}
|
||||
|
||||
for i, tc := range cases {
|
||||
s.Require().Equal(tc.expectPass, tc.coin.IsValid(), "unexpected result for IsValid, tc #%d", i)
|
||||
}
|
||||
sdk.CoinDenomRegex = sdk.DefaultCoinDenomRegex
|
||||
}
|
||||
|
||||
func (s *coinTestSuite) TestAddCoin() {
|
||||
cases := []struct {
|
||||
inputOne sdk.Coin
|
||||
|
||||
+1
-1
@@ -615,7 +615,7 @@ func (coins DecCoins) Sort() DecCoins {
|
||||
func ParseDecCoin(coinStr string) (coin DecCoin, err error) {
|
||||
coinStr = strings.TrimSpace(coinStr)
|
||||
|
||||
matches := reDecCoin.FindStringSubmatch(coinStr)
|
||||
matches := reDecCoin().FindStringSubmatch(coinStr)
|
||||
if matches == nil {
|
||||
return DecCoin{}, fmt.Errorf("invalid decimal coin expression: %s", coinStr)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user