Skip to content
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
28 changes: 28 additions & 0 deletions td2/alert.go
Original file line number Diff line number Diff line change
Expand Up @@ -950,6 +950,19 @@ func evaluateUnclaimedRewardsAlert(cc *ChainConfig) (bool, bool) {
}
}

// fallback to cosmos.directory chain data if available
if cc.denomMetadata == nil && cc.hasCosmosDirectoryData() {
if bankMeta := cc.getBankMetadataFromCosmosDirectory(targetDenom); bankMeta != nil {
cc.denomMetadata = bankMeta
addDenom(cc.denomMetadata.Base)
addDenom(cc.denomMetadata.Display)
targetDenom = cc.denomMetadata.Display
if targetDenom == "" {
targetDenom = cc.denomMetadata.Base
}
}
}

// when `cc.denomMetadata` is nil, we try to infer the denom from the rewards
if len(targetDenoms) == 0 {
if selfRewardsLen > 0 {
Expand Down Expand Up @@ -1011,6 +1024,21 @@ func evaluateUnclaimedRewardsAlert(cc *ChainConfig) (bool, bool) {
return alert, resolved
}

if err := github_com_cosmos_cosmos_sdk_types.ValidateDenom(targetDenom); err != nil {
fallback := ""
if len(nativeCoins) > 0 {
if errFallback := github_com_cosmos_cosmos_sdk_types.ValidateDenom(nativeCoins[0].Denom); errFallback == nil {
fallback = nativeCoins[0].Denom
}
}
if fallback == "" {
l(fmt.Errorf("invalid target denom %q for %s: %w", targetDenom, cc.name, err))
return alert, resolved
}
l(fmt.Errorf("invalid target denom %q for %s: %w; falling back to %q", targetDenom, cc.name, err, fallback))
targetDenom = fallback
}

totalRewards := github_com_cosmos_cosmos_sdk_types.NewDecCoinFromDec(targetDenom, totalAmount)

coinPrice, err := td.coinMarketCapClient.GetPrice(td.ctx, cc.Slug)
Expand Down
33 changes: 31 additions & 2 deletions td2/chain-details.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,8 @@ type CosmosDirectoryChainData struct {
Path string `json:"path"`
ChainName string `json:"chain_name"`
Symbol string `json:"symbol"`
Decimals int `json:"decimals"`
Display string `json:"display"`
Decimals uint32 `json:"decimals"`
Denom string `json:"denom"`
Params CDParams `json:"params"`
Assets []CDAsset `json:"assets"`
Expand Down Expand Up @@ -387,7 +388,35 @@ func (cc *ChainConfig) getChainInfoFromCosmosDirectory() (communityTax float64,
func (cc *ChainConfig) getBankMetadataFromCosmosDirectory(denom string) *bank.Metadata {
cdAsset := cc.getDenomMetadataFromCosmosDirectory(denom)
if cdAsset == nil {
return nil
if cc.cosmosDirectoryData == nil || cc.cosmosDirectoryData.Denom == "" {
return nil
}
display := cc.cosmosDirectoryData.Display
if display == "" {
display = cc.cosmosDirectoryData.Symbol
}

denomUnits := []*bank.DenomUnit{
{
Denom: cc.cosmosDirectoryData.Denom,
Exponent: 0,
},
}
if display != "" && display != cc.cosmosDirectoryData.Denom {
denomUnits = append(denomUnits, &bank.DenomUnit{
Denom: display,
Exponent: cc.cosmosDirectoryData.Decimals,
})
}

return &bank.Metadata{
Description: "",
DenomUnits: denomUnits,
Base: cc.cosmosDirectoryData.Denom,
Display: display,
Name: cc.cosmosDirectoryData.ChainName,
Symbol: cc.cosmosDirectoryData.Symbol,
}
}

// Convert CDDenomUnit to bank.DenomUnit
Expand Down
21 changes: 21 additions & 0 deletions td2/provider-default.go
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,27 @@ func (d *DefaultProvider) QuerySlashingParams(ctx context.Context) (*slashing.Pa
return &params.Params, nil
}

func (d *DefaultProvider) QueryStakingParams(ctx context.Context) (*staking.Params, error) {
qParams := &staking.QueryParamsRequest{}
b, err := qParams.Marshal()
if err != nil {
return nil, fmt.Errorf("marshal staking params: %w", err)
}
resp, err := d.ChainConfig.client.ABCIQuery(ctx, "/cosmos.staking.v1beta1.Query/Params", b)
if err != nil {
return nil, fmt.Errorf("query staking params: %w", err)
}
if resp.Response.Value == nil {
return nil, errors.New("🛑 could not query staking params, got empty response")
}
params := &staking.QueryParamsResponse{}
err = params.Unmarshal(resp.Response.Value)
if err != nil {
return nil, fmt.Errorf("unmarshal staking params: %w", err)
}
return &params.Params, nil
}

func (d *DefaultProvider) QueryChainInfo(ctx context.Context) (totalSupply float64, communityTax float64, inflationRate float64, err error) {
// Query total supply using bank module
supplyQueryParams := bank.QuerySupplyOfRequest{
Expand Down
4 changes: 4 additions & 0 deletions td2/provider-namada.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,10 @@ func (d *NamadaProvider) QuerySlashingParams(ctx context.Context) (*slashing.Par
return &slashing.Params{SignedBlocksWindow: int64(livenessInfo.LivenessWindowLen), MinSignedPerWindow: cosmos_sdk_types.MustNewDecFromStr(livenessInfo.LivenessThreshold.String())}, nil
}

func (d *NamadaProvider) QueryStakingParams(ctx context.Context) (*staking.Params, error) {
return nil, errors.New("QueryStakingParams with ABCIQuery not implemented for Namada")
}

func (d *NamadaProvider) QueryDenomMetadata(ctx context.Context, denom string) (medatada *bank.Metadata, err error) {
return nil, errors.New("QueryDenomMetadata with ABCIQuery not implemented for Namada")
}
Expand Down
1 change: 1 addition & 0 deletions td2/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,7 @@ type ChainProvider interface {
QueryValidatorInfo(ctx context.Context) (pub []byte, moniker string, jailed bool, bonded bool, delegatedTokens float64, commissionRate float64, err error)
QuerySigningInfo(ctx context.Context) (*slashing.ValidatorSigningInfo, error)
QuerySlashingParams(ctx context.Context) (*slashing.Params, error)
QueryStakingParams(ctx context.Context) (*staking.Params, error)
QueryValidatorVotingPool(ctx context.Context) (votingPool *staking.Pool, err error)
QueryValidatorSelfDelegationRewardsAndCommission(ctx context.Context) (rewards *github_com_cosmos_cosmos_sdk_types.DecCoins, commission *github_com_cosmos_cosmos_sdk_types.DecCoins, err error)
QueryDenomMetadata(ctx context.Context, denom string) (medatada *bank.Metadata, err error)
Expand Down
9 changes: 9 additions & 0 deletions td2/utils/price-conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,9 @@ func ConvertDecCoinToDisplayUnit(coins []github_com_cosmos_cosmos_sdk_types.DecC
} else {
displayDenom = metadata.Display
}
if err := github_com_cosmos_cosmos_sdk_types.ValidateDenom(displayDenom); err != nil {
return nil, fmt.Errorf("invalid display denom %q for base %q: %w", displayDenom, metadata.Base, err)
}

// Find the exponent for the display denom
foundDisplayDenom := false
Expand Down Expand Up @@ -325,11 +328,17 @@ func ConvertFloatInBaseUnitToDisplayUnit(value float64, metadata bank.Metadata)
// If no display is set, default to base
if metadata.Display == "" {
displayDenom = metadata.Base
if err := github_com_cosmos_cosmos_sdk_types.ValidateDenom(displayDenom); err != nil {
return 0, "", fmt.Errorf("invalid display denom %q for base %q: %w", displayDenom, metadata.Base, err)
}
// If display is base, no conversion needed
return value, displayDenom, nil
} else {
displayDenom = metadata.Display
}
if err := github_com_cosmos_cosmos_sdk_types.ValidateDenom(displayDenom); err != nil {
return 0, "", fmt.Errorf("invalid display denom %q for base %q: %w", displayDenom, metadata.Base, err)
}

// Find the exponent for the display denom
foundDisplayDenom := false
Expand Down
46 changes: 34 additions & 12 deletions td2/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,26 +196,48 @@ func (cc *ChainConfig) GetValInfo(first bool) (err error) {
rewards, commission, err := provider.QueryValidatorSelfDelegationRewardsAndCommission(ctx)
if err == nil {
// query the chain's denom metadata, only query once since this does not change
if first && rewards != nil && len(*rewards) > 0 {
bankMeta, err := provider.QueryDenomMetadata(ctx, (*rewards)[0].Denom)
if first {
bondDenom := ""
stakingParams, err := provider.QueryStakingParams(ctx)
if err == nil {
cc.denomMetadata = bankMeta
bondDenom = stakingParams.BondDenom
} else {
l(fmt.Errorf("cannot query bank metadata for chain %s via ABCI, err: %w, trying cosmos.directory fallback", cc.name, err))
// Try cosmos.directory fallback first
bankMeta = cc.getBankMetadataFromCosmosDirectory((*rewards)[0].Denom)
if bankMeta != nil {
l(fmt.Errorf("cannot query staking params for chain %s via ABCI, err: %w", cc.name, err))
}
if bondDenom == "" && cc.hasCosmosDirectoryData() {
if cc.cosmosDirectoryData.Params.Staking.BondDenom != "" {
bondDenom = cc.cosmosDirectoryData.Params.Staking.BondDenom
} else if cc.cosmosDirectoryData.Denom != "" {
bondDenom = cc.cosmosDirectoryData.Denom
}
}
if bondDenom == "" && rewards != nil && len(*rewards) > 0 {
bondDenom = (*rewards)[0].Denom
}

if bondDenom != "" {
bankMeta, err := provider.QueryDenomMetadata(ctx, bondDenom)
if err == nil {
cc.denomMetadata = bankMeta
l(fmt.Sprintf("✅ loaded bank metadata for chain %s from cosmos.directory", cc.name))
} else {
l(fmt.Sprintf("ℹ️ cosmos.directory bank metadata not available for chain %s, trying GitHub fallback", cc.name))
bankMeta, err = cc.fetchBankMetadataFromGitHub()
if err == nil {
l(fmt.Errorf("cannot query bank metadata for chain %s via ABCI, err: %w, trying cosmos.directory fallback", cc.name, err))
// Try cosmos.directory fallback (assets first, then chain data)
bankMeta = cc.getBankMetadataFromCosmosDirectory(bondDenom)
if bankMeta != nil {
cc.denomMetadata = bankMeta
l(fmt.Sprintf("✅ loaded bank metadata for chain %s from cosmos.directory", cc.name))
} else {
l(fmt.Errorf("cannot find bank metadata for chain %s in the GitHub JSON file, err: %w", cc.name, err))
l(fmt.Sprintf("ℹ️ cosmos.directory bank metadata not available for chain %s, trying GitHub fallback", cc.name))
bankMeta, err = cc.fetchBankMetadataFromGitHub()
if err == nil {
cc.denomMetadata = bankMeta
} else {
l(fmt.Errorf("cannot find bank metadata for chain %s in the GitHub JSON file, err: %w", cc.name, err))
}
}
}
} else {
l(fmt.Sprintf("⚠️ could not determine bond denom for chain %s, skipping denom metadata query", cc.name))
}
}

Expand Down
Loading