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: allow ignoring denoms #73

Merged
merged 1 commit into from
Jul 10, 2024
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
12 changes: 11 additions & 1 deletion config.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,21 @@ base-denom = "uatom"
# 4. denom-exponent
# The exponent of a coefficient you need to multiply base denom to get 1 token on Coingecko.
# Optional, defaults to 6 (so a coefficient == 1_000_000).
# 5. ignore
# Whether the denom should be ignored and not returned in metrics.
# If specified as true, the exporter would not export this value as metric value in all the places
# when it does a denom conversion (rewards, commission, self-delegation, voting power etc.)
# Ignoring a base denom is quite pointless as it would effectively strip most of the useful metrics.
# Useful for chains where there are tokens of really low value (see Cosmos Hub and their stXXX dust
# tokens for example).
# Optional, defaults to false (so, not ignored).
# Keep in mind that if ignore = false, but coingecko-currency is provided, it will still fetch
# Coingecko price for this token.
#
# You can calculate the actual price of something by multiplying the metric that has denoms by the
# `cosmos_validators_exporter_price` metric (by chain + denom).
denoms = [
{ denom = "uatom", display-denom = "atom", coingecko-currency = "cosmos", denom-exponent = 6 },
{ denom = "uatom", display-denom = "atom", coingecko-currency = "cosmos", denom-exponent = 6, ignore = false },
]
# Bech32 prefix for a wallet address (example: "cosmos" for a Cosmos wallet). If omitted,
# the self-delegation metric will not be present.
Expand Down
17 changes: 12 additions & 5 deletions pkg/config/denom_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,24 @@ import (
"errors"
"main/pkg/types"
"math"

"github.com/guregu/null/v5"
)

type DenomInfo struct {
Denom string `toml:"denom"`
DenomExponent int64 `default:"6" toml:"denom-exponent"`
DisplayDenom string `toml:"display-denom"`
CoingeckoCurrency string `toml:"coingecko-currency"`
Denom string `toml:"denom"`
DenomExponent int64 `default:"6" toml:"denom-exponent"`
DisplayDenom string `toml:"display-denom"`
CoingeckoCurrency string `toml:"coingecko-currency"`
Ignore null.Bool `default:"false" toml:"ignore"`
}

func (d *DenomInfo) Validate() error {
if d.Denom == "" {
return errors.New("empty denom name")
}

if d.DisplayDenom == "" {
if d.DisplayDenom == "" && !d.Ignore.Bool {
return errors.New("empty display denom name")
}

Expand Down Expand Up @@ -55,6 +58,10 @@ func (d DenomInfos) Find(denom string) *DenomInfo {
func (d DenomInfos) Convert(amount *types.Amount) *types.Amount {
for _, info := range d {
if info.Denom == amount.Denom {
if info.Ignore.Bool {
return nil
}

return &types.Amount{
Amount: amount.Amount / math.Pow(10, float64(info.DenomExponent)),
Denom: info.DisplayDenom,
Expand Down
4 changes: 4 additions & 0 deletions pkg/generators/active_set_tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ func (g *ActiveSetTokensGenerator) Generate(state *statePkg.State) []prometheus.
Denom: chain.BaseDenom,
})

if lastValidatorAmount == nil {
continue
}

if chainStakingParams != nil && len(activeValidators) >= chainStakingParams.StakingParams.MaxValidators {
activeSetTokensGauge.With(prometheus.Labels{
"chain": chain.Name,
Expand Down
38 changes: 38 additions & 0 deletions pkg/generators/active_set_tokens_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"main/pkg/types"
"testing"

"github.com/guregu/null/v5"

"cosmossdk.io/math"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/testutil"
Expand Down Expand Up @@ -147,3 +149,39 @@ func TestActiveSetTokensGeneratorEnoughValidators(t *testing.T) {
"denom": "atom",
})), 0.01)
}

func TestActiveSetTokensGeneratorDenomIgnored(t *testing.T) {
t.Parallel()

chains := []*config.Chain{{
Name: "chain",
BaseDenom: "uatom",
Denoms: config.DenomInfos{{Denom: "uatom", Ignore: null.BoolFrom(true)}},
}}
state := statePkg.NewState()
state.Set(constants.FetcherNameValidators, fetchers.ValidatorsData{
Validators: map[string]*types.ValidatorsResponse{
"chain": {
Validators: []types.Validator{
{DelegatorShares: math.LegacyMustNewDecFromStr("2000000"), Status: constants.ValidatorStatusBonded},
{DelegatorShares: math.LegacyMustNewDecFromStr("1000000")},
{DelegatorShares: math.LegacyMustNewDecFromStr("3000000"), Status: constants.ValidatorStatusBonded},
},
},
},
})
state.Set(constants.FetcherNameStakingParams, fetchers.StakingParamsData{
Params: map[string]*types.StakingParamsResponse{
"chain": {
StakingParams: types.StakingParams{MaxValidators: 2},
},
},
})
generator := NewActiveSetTokensGenerator(chains)
results := generator.Generate(state)
assert.NotEmpty(t, results)

gauge, ok := results[0].(*prometheus.GaugeVec)
assert.True(t, ok)
assert.Zero(t, testutil.CollectAndCount(gauge))
}
8 changes: 8 additions & 0 deletions pkg/generators/balance.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ func (g *BalanceGenerator) Generate(state *statePkg.State) []prometheus.Collecto

for _, balance := range validatorBalances {
amountConverted := consumer.Denoms.Convert(&balance)
if amountConverted == nil {
continue
}

walletBalanceTokens.With(prometheus.Labels{
"chain": consumer.Name,
"address": validator.Address,
Expand All @@ -70,6 +74,10 @@ func (g *BalanceGenerator) Generate(state *statePkg.State) []prometheus.Collecto

for _, balance := range validatorBalances {
amountConverted := chain.Denoms.Convert(&balance)
if amountConverted == nil {
continue
}

walletBalanceTokens.With(prometheus.Labels{
"chain": chain.Name,
"address": validator.Address,
Expand Down
7 changes: 7 additions & 0 deletions pkg/generators/balance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"main/pkg/types"
"testing"

"github.com/guregu/null/v5"

"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/testutil"

Expand All @@ -33,12 +35,14 @@ func TestBalanceGeneratorNotEmptyState(t *testing.T) {
"validator": {
{Amount: 100000, Denom: "uatom"},
{Amount: 200000, Denom: "ustake"},
{Amount: 300000, Denom: "uignored"},
},
},
"consumer": {
"validator": {
{Amount: 100000, Denom: "untrn"},
{Amount: 200000, Denom: "ustake"},
{Amount: 300000, Denom: "uignored"},
},
},
},
Expand All @@ -50,11 +54,13 @@ func TestBalanceGeneratorNotEmptyState(t *testing.T) {
Validators: []config.Validator{{Address: "validator"}, {Address: "validator2"}},
Denoms: config.DenomInfos{
{Denom: "uatom", DisplayDenom: "atom", DenomExponent: 6},
{Denom: "uignored", Ignore: null.BoolFrom(true)},
},
ConsumerChains: []*config.ConsumerChain{{
Name: "consumer",
Denoms: config.DenomInfos{
{Denom: "untrn", DisplayDenom: "ntrn", DenomExponent: 6},
{Denom: "uignored", Ignore: null.BoolFrom(true)},
},
}},
},
Expand All @@ -72,6 +78,7 @@ func TestBalanceGeneratorNotEmptyState(t *testing.T) {

gauge, ok := results[0].(*prometheus.GaugeVec)
assert.True(t, ok)
assert.Equal(t, 4, testutil.CollectAndCount(gauge))
assert.InEpsilon(t, 0.1, testutil.ToFloat64(gauge.With(prometheus.Labels{
"chain": "chain",
"address": "validator",
Expand Down
4 changes: 4 additions & 0 deletions pkg/generators/commission.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ func (g *CommissionGenerator) Generate(state *statePkg.State) []prometheus.Colle

for _, balance := range validatorCommissions {
amountConverted := chain.Denoms.Convert(&balance)
if amountConverted == nil {
continue
}

commissionUnclaimedTokens.With(prometheus.Labels{
"chain": chain.Name,
"address": validator.Address,
Expand Down
5 changes: 5 additions & 0 deletions pkg/generators/commission_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"main/pkg/types"
"testing"

"github.com/guregu/null/v5"

"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/testutil"

Expand All @@ -33,6 +35,7 @@ func TestCommissionGeneratorNotEmptyState(t *testing.T) {
"validator": []types.Amount{
{Amount: 100000, Denom: "uatom"},
{Amount: 200000, Denom: "ustake"},
{Amount: 300000, Denom: "uignored"},
},
},
},
Expand All @@ -44,6 +47,7 @@ func TestCommissionGeneratorNotEmptyState(t *testing.T) {
Validators: []config.Validator{{Address: "validator"}, {Address: "validator2"}},
Denoms: config.DenomInfos{
{Denom: "uatom", DisplayDenom: "atom", DenomExponent: 6},
{Denom: "uignored", Ignore: null.BoolFrom(true)},
},
},
{
Expand All @@ -57,6 +61,7 @@ func TestCommissionGeneratorNotEmptyState(t *testing.T) {

gauge, ok := results[0].(*prometheus.GaugeVec)
assert.True(t, ok)
assert.Equal(t, 2, testutil.CollectAndCount(gauge))
assert.InEpsilon(t, 0.1, testutil.ToFloat64(gauge.With(prometheus.Labels{
"chain": "chain",
"address": "validator",
Expand Down
4 changes: 4 additions & 0 deletions pkg/generators/rewards.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ func (g *RewardsGenerator) Generate(state *statePkg.State) []prometheus.Collecto

for _, balance := range validatorRewards {
amountConverted := chain.Denoms.Convert(&balance)
if amountConverted == nil {
continue
}

selfDelegationRewardsTokens.With(prometheus.Labels{
"chain": chain.Name,
"address": validator.Address,
Expand Down
5 changes: 5 additions & 0 deletions pkg/generators/rewards_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"main/pkg/types"
"testing"

"github.com/guregu/null/v5"

"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/testutil"

Expand All @@ -33,6 +35,7 @@ func TestRewardsGeneratorNotEmptyState(t *testing.T) {
"validator": []types.Amount{
{Amount: 100000, Denom: "uatom"},
{Amount: 200000, Denom: "ustake"},
{Amount: 300000, Denom: "uignored"},
},
},
},
Expand All @@ -44,6 +47,7 @@ func TestRewardsGeneratorNotEmptyState(t *testing.T) {
Validators: []config.Validator{{Address: "validator"}, {Address: "validator2"}},
Denoms: config.DenomInfos{
{Denom: "uatom", DisplayDenom: "atom", DenomExponent: 6},
{Denom: "uignored", Ignore: null.BoolFrom(true)},
},
},
{
Expand All @@ -57,6 +61,7 @@ func TestRewardsGeneratorNotEmptyState(t *testing.T) {

gauge, ok := results[0].(*prometheus.GaugeVec)
assert.True(t, ok)
assert.Equal(t, 2, testutil.CollectAndCount(gauge))
assert.InEpsilon(t, 0.1, testutil.ToFloat64(gauge.With(prometheus.Labels{
"chain": "chain",
"address": "validator",
Expand Down
4 changes: 4 additions & 0 deletions pkg/generators/self_delegation.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ func (g *SelfDelegationGenerator) Generate(state *statePkg.State) []prometheus.C
}

amountConverted := chain.Denoms.Convert(validatorSelfDelegation)
if amountConverted == nil {
continue
}

selfDelegatedTokensGauge.With(prometheus.Labels{
"chain": chain.Name,
"address": validator.Address,
Expand Down
6 changes: 6 additions & 0 deletions pkg/generators/self_delegations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"main/pkg/types"
"testing"

"github.com/guregu/null/v5"

"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/testutil"

Expand All @@ -32,6 +34,7 @@ func TestSelfDelegationGeneratorNotEmptyState(t *testing.T) {
"chain": {
"validator": {Amount: 100000, Denom: "uatom"},
"validator2": {Amount: 200000, Denom: "ustake"},
"validator3": {Amount: 300000, Denom: "uignored"},
},
},
})
Expand All @@ -43,9 +46,11 @@ func TestSelfDelegationGeneratorNotEmptyState(t *testing.T) {
{Address: "validator"},
{Address: "validator2"},
{Address: "validator3"},
{Address: "validator4"},
},
Denoms: config.DenomInfos{
{Denom: "uatom", DisplayDenom: "atom", DenomExponent: 6},
{Denom: "uignored", Ignore: null.BoolFrom(true)},
},
},
{
Expand All @@ -59,6 +64,7 @@ func TestSelfDelegationGeneratorNotEmptyState(t *testing.T) {

gauge, ok := results[0].(*prometheus.GaugeVec)
assert.True(t, ok)
assert.Equal(t, 2, testutil.CollectAndCount(gauge))
assert.InEpsilon(t, 0.1, testutil.ToFloat64(gauge.With(prometheus.Labels{
"chain": "chain",
"address": "validator",
Expand Down
4 changes: 4 additions & 0 deletions pkg/generators/single_validator_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ func (g *SingleValidatorInfoGenerator) Generate(state *statePkg.State) []prometh
Denom: chain.BaseDenom,
})

if delegationsAmount == nil {
continue
}

delegationsGauge.With(prometheus.Labels{
"chain": chain.Name,
"address": validatorAddr.Address,
Expand Down
Loading
Loading