Skip to content

Commit

Permalink
feat: allow ignoring denoms
Browse files Browse the repository at this point in the history
  • Loading branch information
freak12techno committed Jul 9, 2024
1 parent 3a4edb8 commit b1262f4
Show file tree
Hide file tree
Showing 16 changed files with 256 additions and 6 deletions.
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

0 comments on commit b1262f4

Please sign in to comment.