feat: add Coins.Find method (#11959)
Added a new helper method to find a coin in a set of `sdk.Coins` by denom. --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [x] added `!` to the type prefix if API or client breaking change - [x] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/main/CONTRIBUTING.md#pr-targeting)) - [ ] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/main/docs/building-modules) - [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/main/CONTRIBUTING.md#testing) - [ ] added a changelog entry to `CHANGELOG.md` - [ ] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [ ] reviewed "Files changed" and left comments if necessary - [ ] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable)
This commit is contained in:
parent
450cd7fc87
commit
23baecf220
|
@ -86,6 +86,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
|||
* (types) [\#10948](https://github.com/cosmos/cosmos-sdk/issues/10948) Add `app-db-backend` to the `app.toml` config to replace the compile-time `types.DBbackend` variable.
|
||||
* (authz)[\#11060](https://github.com/cosmos/cosmos-sdk/pull/11060) Support grant with no expire time.
|
||||
* (rosetta) [\#11590](https://github.com/cosmos/cosmos-sdk/pull/11590) Add fee suggestion for rosetta and enable offline mode. Also force set events about Fees to Success to pass reconciliation test.
|
||||
* (types) [\#11959](https://github.com/cosmos/cosmos-sdk/pull/11959) Added `sdk.Coins.Find` helper method to find a coin by denom.
|
||||
|
||||
### API Breaking Changes
|
||||
|
||||
|
|
|
@ -703,28 +703,37 @@ func (coins Coins) AmountOf(denom string) Int {
|
|||
// AmountOfNoDenomValidation returns the amount of a denom from coins
|
||||
// without validating the denomination.
|
||||
func (coins Coins) AmountOfNoDenomValidation(denom string) Int {
|
||||
if ok, c := coins.Find(denom); ok {
|
||||
return c.Amount
|
||||
}
|
||||
return ZeroInt()
|
||||
}
|
||||
|
||||
// Find returns true and coin if the denom exists in coins. Otherwise it returns false
|
||||
// and a zero coin. Uses binary search.
|
||||
// CONTRACT: coins must be valid (sorted).
|
||||
func (coins Coins) Find(denom string) (bool, Coin) {
|
||||
switch len(coins) {
|
||||
case 0:
|
||||
return ZeroInt()
|
||||
return false, Coin{}
|
||||
|
||||
case 1:
|
||||
coin := coins[0]
|
||||
if coin.Denom == denom {
|
||||
return coin.Amount
|
||||
return true, coin
|
||||
}
|
||||
return ZeroInt()
|
||||
return false, Coin{}
|
||||
|
||||
default:
|
||||
// Binary search the amount of coins remaining
|
||||
midIdx := len(coins) / 2 // 2:1, 3:1, 4:2
|
||||
coin := coins[midIdx]
|
||||
switch {
|
||||
case denom < coin.Denom:
|
||||
return coins[:midIdx].AmountOfNoDenomValidation(denom)
|
||||
return coins[:midIdx].Find(denom)
|
||||
case denom == coin.Denom:
|
||||
return coin.Amount
|
||||
return true, coin
|
||||
default:
|
||||
return coins[midIdx+1:].AmountOfNoDenomValidation(denom)
|
||||
return coins[midIdx+1:].Find(denom)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -931,7 +931,8 @@ func (s *coinTestSuite) TestSortCoins() {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *coinTestSuite) TestAmountOf() {
|
||||
func (s *coinTestSuite) TestSearch() {
|
||||
require := s.Require()
|
||||
case0 := sdk.Coins{}
|
||||
case1 := sdk.Coins{
|
||||
sdk.NewInt64Coin("gold", 0),
|
||||
|
@ -949,7 +950,7 @@ func (s *coinTestSuite) TestAmountOf() {
|
|||
sdk.NewInt64Coin("gas", 8),
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
amountOfCases := []struct {
|
||||
coins sdk.Coins
|
||||
amountOf int64
|
||||
amountOfSpace int64
|
||||
|
@ -964,13 +965,38 @@ func (s *coinTestSuite) TestAmountOf() {
|
|||
{case4, 0, 0, 8, 0, 0},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
s.Require().Equal(sdk.NewInt(tc.amountOfGAS), tc.coins.AmountOf("gas"))
|
||||
s.Require().Equal(sdk.NewInt(tc.amountOfMINERAL), tc.coins.AmountOf("mineral"))
|
||||
s.Require().Equal(sdk.NewInt(tc.amountOfTREE), tc.coins.AmountOf("tree"))
|
||||
s.Run("AmountOf", func() {
|
||||
for i, tc := range amountOfCases {
|
||||
require.Equal(sdk.NewInt(tc.amountOfGAS), tc.coins.AmountOf("gas"), i)
|
||||
require.Equal(sdk.NewInt(tc.amountOfMINERAL), tc.coins.AmountOf("mineral"), i)
|
||||
require.Equal(sdk.NewInt(tc.amountOfTREE), tc.coins.AmountOf("tree"), i)
|
||||
}
|
||||
require.Panics(func() { amountOfCases[0].coins.AmountOf("10Invalid") })
|
||||
})
|
||||
|
||||
s.Require().Panics(func() { cases[0].coins.AmountOf("10Invalid") })
|
||||
zeroCoin := sdk.Coin{}
|
||||
findCases := []struct {
|
||||
coins sdk.Coins
|
||||
denom string
|
||||
expectedOk bool
|
||||
expectedCoin sdk.Coin
|
||||
}{
|
||||
{case0, "any", false, zeroCoin},
|
||||
{case1, "other", false, zeroCoin},
|
||||
{case1, "gold", true, case1[0]},
|
||||
{case4, "gas", true, case4[0]},
|
||||
{case2, "gas", true, case2[0]},
|
||||
{case2, "mineral", true, case2[1]},
|
||||
{case2, "tree", true, case2[2]},
|
||||
{case2, "other", false, zeroCoin},
|
||||
}
|
||||
s.Run("Find", func() {
|
||||
for i, tc := range findCases {
|
||||
ok, c := tc.coins.Find(tc.denom)
|
||||
require.Equal(tc.expectedOk, ok, i)
|
||||
require.Equal(tc.expectedCoin, c, i)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (s *coinTestSuite) TestCoinsIsAnyGTE() {
|
||||
|
|
Loading…
Reference in New Issue