-
Notifications
You must be signed in to change notification settings - Fork 48
/
utils.go
121 lines (100 loc) · 3.32 KB
/
utils.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
package types
import (
fmt "fmt"
errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
)
func GetPoolShareDenom(poolId uint64) string {
return fmt.Sprintf("amm/pool/%d", poolId)
}
// poolAssetsCoins returns all the coins corresponding to a slice of pool assets.
func poolAssetsCoins(assets []PoolAsset) sdk.Coins {
coins := sdk.Coins{}
for _, asset := range assets {
coins = coins.Add(asset.Token)
}
return coins
}
// ensureDenomInPool check to make sure the input denoms exist in the provided pool asset map
func EnsureDenomInPool(poolAssetsByDenom map[string]PoolAsset, tokensIn sdk.Coins) error {
for _, coin := range tokensIn {
_, ok := poolAssetsByDenom[coin.Denom]
if !ok {
return errorsmod.Wrapf(ErrDenomNotFoundInPool, InvalidInputDenomsErrFormat, coin.Denom)
}
}
return nil
}
// AbsDifferenceWithSign returns | a - b |, (a - b).sign()
// a is mutated and returned.
func AbsDifferenceWithSign(a, b sdk.Dec) (sdk.Dec, bool) {
if a.GTE(b) {
return a.SubMut(b), false
} else {
return a.NegMut().AddMut(b), true
}
}
// ApplyDiscount applies discount to swap fee if applicable
func ApplyDiscount(swapFee sdk.Dec, discount sdk.Dec) sdk.Dec {
// apply discount percentage to swap fee
swapFee = swapFee.Mul(sdk.OneDec().Sub(discount))
return swapFee
}
func GetWeightBreakingFee(weightIn, weightOut, targetWeightIn, targetWeightOut sdk.Dec, poolParams PoolParams) sdk.Dec {
weightBreakingFee := sdk.ZeroDec()
if !weightOut.IsZero() && !weightIn.IsZero() && !targetWeightOut.IsZero() && !targetWeightIn.IsZero() {
// (45/55*60/40) ^ 2.5
weightBreakingFee = poolParams.WeightBreakingFeeMultiplier.
Mul(Pow(weightIn.Mul(targetWeightOut).Quo(weightOut).Quo(targetWeightIn), poolParams.WeightBreakingFeeExponent))
if weightBreakingFee.GT(sdk.NewDecWithPrec(99, 2)) {
weightBreakingFee = sdk.NewDecWithPrec(99, 2)
}
}
return weightBreakingFee
}
func (params PoolParams) Validate(poolWeights []PoolAsset) error {
if params.ExitFee.IsNegative() {
return ErrNegativeExitFee
}
if params.ExitFee.GTE(sdk.OneDec()) {
return ErrTooMuchExitFee
}
if params.SwapFee.IsNegative() {
return ErrNegativeSwapFee
}
if params.SwapFee.GTE(sdk.OneDec()) {
return ErrTooMuchSwapFee
}
return nil
}
// GetPoolAssetsByDenom return a mapping from pool asset
// denom to the pool asset itself. There must be no duplicates.
// Returns error, if any found.
func GetPoolAssetsByDenom(poolAssets []PoolAsset) (map[string]PoolAsset, error) {
poolAssetsByDenom := make(map[string]PoolAsset)
for _, poolAsset := range poolAssets {
_, ok := poolAssetsByDenom[poolAsset.Token.Denom]
if ok {
return nil, fmt.Errorf(FormatRepeatingPoolAssetsNotAllowedErrFormat, poolAsset.Token.Denom)
}
poolAssetsByDenom[poolAsset.Token.Denom] = poolAsset
}
return poolAssetsByDenom, nil
}
func GetPoolAssetByDenom(assets []PoolAsset, denom string) (PoolAsset, bool) {
for _, asset := range assets {
if asset.Token.Denom == denom {
return asset, true
}
}
return PoolAsset{}, false
}
// validates a pool asset, to check if it has a valid weight.
func (pa PoolAsset) validateWeight() error {
if pa.Weight.LTE(sdk.ZeroInt()) {
return fmt.Errorf("a token's weight in the pool must be greater than 0")
}
// TODO: add validation for asset weight overflow:
// https://github.com/osmosis-labs/osmosis/issues/1958
return nil
}