Merge PR #3818: Introduce sdk.NewCoins

This commit is contained in:
Alessio Treglia
2019-03-07 16:55:08 -08:00
committed by Jack Zampolin
parent a24dee0155
commit fbd79d0cad
20 changed files with 219 additions and 149 deletions
+38
View File
@@ -130,6 +130,28 @@ func (coin Coin) IsNegative() bool {
// Coins is a set of Coin, one per currency
type Coins []Coin
// NewCoins constructs a new coin set.
func NewCoins(coins ...Coin) Coins {
// remove zeroes
newCoins := removeZeroCoins(Coins(coins))
if len(newCoins) == 0 {
return Coins{}
}
newCoins.Sort()
// detect duplicate Denoms
if dupIndex := findDup(newCoins); dupIndex != -1 {
panic(fmt.Errorf("find duplicate denom: %s", newCoins[dupIndex]))
}
if !newCoins.IsValid() {
panic(fmt.Errorf("invalid coin set: %s", newCoins))
}
return newCoins
}
func (coins Coins) String() string {
if len(coins) == 0 {
return ""
@@ -552,3 +574,19 @@ func ParseCoins(coinsStr string) (coins Coins, err error) {
return coins, nil
}
// findDup works on the assumption that coins is sorted
func findDup(coins Coins) int {
if len(coins) <= 1 {
return -1
}
prevDenom := coins[0]
for i := 1; i < len(coins); i++ {
if coins[i] == prevDenom {
return i
}
}
return -1
}
+28
View File
@@ -519,3 +519,31 @@ func TestCoinsIsAnyGTE(t *testing.T) {
assert.True(t, Coins{{testDenom1, one}, {testDenom2, one}}.IsAnyGTE(Coins{{testDenom1, one}, {testDenom2, two}}))
assert.True(t, Coins{{"xxx", one}, {"yyy", one}}.IsAnyGTE(Coins{{testDenom2, one}, {"ccc", one}, {"yyy", one}, {"zzz", one}}))
}
func TestNewCoins(t *testing.T) {
tenatom := NewInt64Coin("atom", 10)
tenbtc := NewInt64Coin("btc", 10)
zeroeth := NewInt64Coin("eth", 0)
tests := []struct {
name string
coins Coins
want Coins
wantPanic bool
}{
{"empty args", []Coin{}, Coins{}, false},
{"one coin", []Coin{tenatom}, Coins{tenatom}, false},
{"sort after create", []Coin{tenbtc, tenatom}, Coins{tenatom, tenbtc}, false},
{"sort and remove zeroes", []Coin{zeroeth, tenbtc, tenatom}, Coins{tenatom, tenbtc}, false},
{"panic on dups", []Coin{tenatom, tenatom}, Coins{}, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.wantPanic {
require.Panics(t, func() { NewCoins(tt.coins...) })
return
}
got := NewCoins(tt.coins...)
require.True(t, got.IsEqual(tt.want))
})
}
}