Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(osmoutils): coin math helpers #6427

Merged
merged 4 commits into from
Sep 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Features

* [#6427](https://github.com/osmosis-labs/osmosis/pull/6427) sdk.Coins Mul and Quo helpers in osmoutils

### Misc Improvements

* [#6309](https://github.com/osmosis-labs/osmosis/pull/6309) Add Cosmwasm Pool Queries to Stargate Query
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ require (
github.com/mattn/go-sqlite3 v1.14.17
github.com/ory/dockertest/v3 v3.10.0
github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20230911120014-b14342e08daf
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20230918184012-da92c9cdf6bd
github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20230911120014-b14342e08daf
github.com/osmosis-labs/osmosis/x/epochs v0.0.3-0.20230911120014-b14342e08daf
github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.9-0.20230911120014-b14342e08daf
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,8 @@ github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3 h1:Ylmch
github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3/go.mod h1:lV6KnqXYD/ayTe7310MHtM3I2q8Z6bBfMAi+bhwPYtI=
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20230911120014-b14342e08daf h1:sXSC/RG9sxQCB5QJ5JB+M9Bok7Xbpv2zx9ee6287glw=
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20230911120014-b14342e08daf/go.mod h1:pIItelRYvonB+H8A6KqucOi7xFnJxzDHaWJqOdFNLI4=
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20230918184012-da92c9cdf6bd h1:U7r0uBLTWeLrgGOu1re0aTl10yreX1j3dNDu12KqBpE=
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20230918184012-da92c9cdf6bd/go.mod h1:pIItelRYvonB+H8A6KqucOi7xFnJxzDHaWJqOdFNLI4=
github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20230911120014-b14342e08daf h1:r5R/L3tzH+vGPahAdvnVB2Vo0KPhZR0oMNyX4+G2FEo=
github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20230911120014-b14342e08daf/go.mod h1:7VoXHwrSSx8Sii0UFc9YIixF6C/9XfV1pdU2Dliu4WA=
github.com/osmosis-labs/osmosis/x/epochs v0.0.3-0.20230911120014-b14342e08daf h1:8lkIsAj3L7zxvOZbqVLNJRpSdDxaYhYfAIG7XjPaJiU=
Expand Down
138 changes: 138 additions & 0 deletions osmoutils/coins/coin_math.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package coins

import (
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/osmosis-labs/osmosis/osmomath"
)

// Mutative helpers that mutate the input coins

// MulIntMut multiplies the coins by the given integer
// Mutates the input coins
func MulIntMut(coins sdk.Coins, num osmomath.Int) {
for i := range coins {
coins[i].Amount = coins[i].Amount.Mul(num)
}
}

// MulRawMut multiplies the coins by the given integer
// Mutates the input coins
func MulRawMut(coins sdk.Coins, num int64) sdk.Coins {
for i := range coins {
coins[i].Amount = coins[i].Amount.MulRaw(num)
}
return coins
}

// MulDecMut multiplies the coins by the given decimal
// Mutates the input coins
func MulDecMut(coins sdk.Coins, num osmomath.Dec) {
for i := range coins {
coins[i].Amount = coins[i].Amount.ToLegacyDec().Mul(num).TruncateInt()
}
}

// QuoIntMut divides the coins by the given integer
// Mutates the input coins
func QuoIntMut(coins sdk.Coins, num osmomath.Int) {
for i := range coins {
coins[i].Amount = coins[i].Amount.Quo(num)
}
}

// QuoRawMut divides the coins by the given integer
// Mutates the input coins
func QuoRawMut(coins sdk.Coins, num int64) {
for i := range coins {
coins[i].Amount = coins[i].Amount.QuoRaw(num)
}
}

// QuoIntMut divides the coins by the given decimal
// Mutates the input coins
func QuoDecMut(coins sdk.Coins, num osmomath.Dec) {
for i := range coins {
coins[i].Amount = coins[i].Amount.ToLegacyDec().Quo(num).TruncateInt()
}
}

// Non-mutative coin helpers that reallocate and return new coins

// MulInt multiplies the coins by the given integer
// Does not mutate the input coins and returns new coins.
func MulInt(coins sdk.Coins, num osmomath.Int) sdk.Coins {
newCoins := make(sdk.Coins, len(coins))

for i := range coins {
newCoins[i].Amount = coins[i].Amount.Mul(num)
newCoins[i].Denom = coins[i].Denom
}

return newCoins
}

// MulRaw multiplies the coins by the given integer
// Does not mutate the input coins and returns new coins.
func MulRaw(coins sdk.Coins, num int64) sdk.Coins {
newCoins := make(sdk.Coins, len(coins))

for i := range coins {
newCoins[i].Amount = coins[i].Amount.MulRaw(num)
newCoins[i].Denom = coins[i].Denom
}

return newCoins
}

// MulDec multiplies the coins by the given decimal
// Does not mutate the input coins and returns new coins.
func MulDec(coins sdk.Coins, num osmomath.Dec) sdk.Coins {
newCoins := make(sdk.Coins, len(coins))

for i := range coins {
newCoins[i].Amount = coins[i].Amount.ToLegacyDec().Mul(num).TruncateInt()
newCoins[i].Denom = coins[i].Denom
}

return newCoins
}

// QuoInt divides the coins by the given integer
// Does not mutate the input coins and returns new coins.
func QuoInt(coins sdk.Coins, num osmomath.Int) sdk.Coins {
newCoins := make(sdk.Coins, len(coins))

for i := range coins {
newCoins[i].Amount = coins[i].Amount.Quo(num)
newCoins[i].Denom = coins[i].Denom
}

return newCoins
}

// QuoRaw divides the coins by the given integer
// Does not mutate the input coins and returns new coins.
func QuoRaw(coins sdk.Coins, num int64) sdk.Coins {
newCoins := make(sdk.Coins, len(coins))

for i := range coins {
newCoins[i].Amount = coins[i].Amount.QuoRaw(num)
newCoins[i].Denom = coins[i].Denom
}

return newCoins
}

// QuoDec divides the coins by the given integer
// Does not mutate the input coins and returns new coins.
func QuoDec(coins sdk.Coins, num osmomath.Dec) sdk.Coins {
newCoins := make(sdk.Coins, len(coins))

for i := range coins {
newCoins[i].Amount = coins[i].Amount.ToLegacyDec().Quo(num).TruncateInt()
newCoins[i].Denom = coins[i].Denom
}

return newCoins
}
135 changes: 135 additions & 0 deletions osmoutils/coins/coin_math_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package coins_test

import (
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"

"github.com/osmosis-labs/osmosis/osmomath"
"github.com/osmosis-labs/osmosis/osmoutils/coins"
)

var (
defaultCoins = sdk.NewCoins(
sdk.NewCoin("foo", sdk.NewInt(100)),
sdk.NewCoin("bar", sdk.NewInt(200)),
)

defaultMultiplier = osmomath.NewInt(2)

defaultMulExpectedResult = sdk.NewCoins(
sdk.NewCoin(defaultCoins[0].Denom, defaultCoins[0].Amount.Mul(defaultMultiplier)),
sdk.NewCoin(defaultCoins[1].Denom, defaultCoins[1].Amount.Mul(defaultMultiplier)),
)

defaultQuoExpectedResult = sdk.NewCoins(
sdk.NewCoin(defaultCoins[0].Denom, defaultCoins[0].Amount.Quo(defaultMultiplier)),
sdk.NewCoin(defaultCoins[1].Denom, defaultCoins[1].Amount.Quo(defaultMultiplier)),
)
)

// makes a deep copy to avoid accidentally mutating the input to a test.
func deepCopy(coins sdk.Coins) sdk.Coins {
newCoins := make(sdk.Coins, len(coins))
for i := range coins {
newCoins[i].Amount = coins[i].Amount
newCoins[i].Denom = coins[i].Denom
}
return newCoins
}

// Basic multiplication test.
func TestMul(t *testing.T) {
t.Run("test mutative multiplication", func(t *testing.T) {
t.Run("MulIntMut", func(t *testing.T) {
defaulCoins := deepCopy(defaultCoins)
coins.MulIntMut(defaulCoins, defaultMultiplier)
require.Equal(t, defaultMulExpectedResult, defaulCoins)
})

t.Run("MulIntRawMut", func(t *testing.T) {
defaulCoins := deepCopy(defaultCoins)
coins.MulRawMut(defaulCoins, defaultMultiplier.Int64())
require.Equal(t, defaultMulExpectedResult, defaulCoins)
})

t.Run("MulDecMut", func(t *testing.T) {
defaulCoins := deepCopy(defaultCoins)
coins.MulDecMut(defaulCoins, osmomath.NewDecFromInt(defaultMultiplier))
require.Equal(t, defaultMulExpectedResult, defaulCoins)
})
})

// Make a deep copy of the default coins for the input.
// Validate that the copy input coins are not mutated.
t.Run("test non-mutative multiplication", func(t *testing.T) {
t.Run("MulInt", func(t *testing.T) {
defaulCoinsCopy := deepCopy(defaultCoins)
result := coins.MulInt(defaulCoinsCopy, defaultMultiplier)
require.Equal(t, defaultMulExpectedResult, result)
require.Equal(t, defaultCoins, defaulCoinsCopy)
})

t.Run("MulIntRaw", func(t *testing.T) {
defaulCoinsCopy := deepCopy(defaultCoins)
result := coins.MulRaw(defaulCoinsCopy, defaultMultiplier.Int64())
require.Equal(t, defaultMulExpectedResult, result)
require.Equal(t, defaultCoins, defaulCoinsCopy)
})

t.Run("MulDec", func(t *testing.T) {
defaulCoinsCopy := deepCopy(defaultCoins)
result := coins.MulDec(defaulCoinsCopy, osmomath.NewDecFromInt(defaultMultiplier))
require.Equal(t, defaultMulExpectedResult, result)
require.Equal(t, defaultCoins, defaulCoinsCopy)
})
})
}

func TestQuo(t *testing.T) {
t.Run("test mutative division", func(t *testing.T) {
t.Run("QuoIntMut", func(t *testing.T) {
defaulCoins := deepCopy(defaultCoins)
coins.QuoIntMut(defaulCoins, defaultMultiplier)
require.Equal(t, defaultQuoExpectedResult, defaulCoins)
})

t.Run("QuoIntRawMut", func(t *testing.T) {
defaulCoins := deepCopy(defaultCoins)
coins.QuoRawMut(defaulCoins, defaultMultiplier.Int64())
require.Equal(t, defaultQuoExpectedResult, defaulCoins)
})

t.Run("QuoDecMut", func(t *testing.T) {
defaulCoins := deepCopy(defaultCoins)
coins.QuoDecMut(defaulCoins, osmomath.NewDecFromInt(defaultMultiplier))
require.Equal(t, defaultQuoExpectedResult, defaulCoins)
})
})

// Make a deep copy of the default coins for the input.
// Validate that the copy input coins are not mutated.
t.Run("test non-mutative division", func(t *testing.T) {
t.Run("QuoInt", func(t *testing.T) {
defaulCoinsCopy := deepCopy(defaultCoins)
result := coins.QuoInt(defaulCoinsCopy, defaultMultiplier)
require.Equal(t, defaultQuoExpectedResult, result)
require.Equal(t, defaultCoins, defaulCoinsCopy)
})

t.Run("QuoIntRaw", func(t *testing.T) {
defaulCoinsCopy := deepCopy(defaultCoins)
result := coins.QuoRaw(defaulCoinsCopy, defaultMultiplier.Int64())
require.Equal(t, defaultQuoExpectedResult, result)
require.Equal(t, defaultCoins, defaulCoinsCopy)
})

t.Run("QuoDec", func(t *testing.T) {
defaulCoinsCopy := deepCopy(defaultCoins)
result := coins.QuoDec(defaulCoinsCopy, osmomath.NewDecFromInt(defaultMultiplier))
require.Equal(t, defaultQuoExpectedResult, result)
require.Equal(t, defaultCoins, defaulCoinsCopy)
})
})
}