Skip to content

Commit 5671440

Browse files
authored
Merge pull request #70 from Firstset/69/fix-invalid-denom
2 parents 16b48fe + e650e7f commit 5671440

7 files changed

Lines changed: 128 additions & 14 deletions

File tree

td2/alert.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,19 @@ func evaluateUnclaimedRewardsAlert(cc *ChainConfig) (bool, bool) {
950950
}
951951
}
952952

953+
// fallback to cosmos.directory chain data if available
954+
if cc.denomMetadata == nil && cc.hasCosmosDirectoryData() {
955+
if bankMeta := cc.getBankMetadataFromCosmosDirectory(targetDenom); bankMeta != nil {
956+
cc.denomMetadata = bankMeta
957+
addDenom(cc.denomMetadata.Base)
958+
addDenom(cc.denomMetadata.Display)
959+
targetDenom = cc.denomMetadata.Display
960+
if targetDenom == "" {
961+
targetDenom = cc.denomMetadata.Base
962+
}
963+
}
964+
}
965+
953966
// when `cc.denomMetadata` is nil, we try to infer the denom from the rewards
954967
if len(targetDenoms) == 0 {
955968
if selfRewardsLen > 0 {
@@ -1011,6 +1024,21 @@ func evaluateUnclaimedRewardsAlert(cc *ChainConfig) (bool, bool) {
10111024
return alert, resolved
10121025
}
10131026

1027+
if err := github_com_cosmos_cosmos_sdk_types.ValidateDenom(targetDenom); err != nil {
1028+
fallback := ""
1029+
if len(nativeCoins) > 0 {
1030+
if errFallback := github_com_cosmos_cosmos_sdk_types.ValidateDenom(nativeCoins[0].Denom); errFallback == nil {
1031+
fallback = nativeCoins[0].Denom
1032+
}
1033+
}
1034+
if fallback == "" {
1035+
l(fmt.Errorf("invalid target denom %q for %s: %w", targetDenom, cc.name, err))
1036+
return alert, resolved
1037+
}
1038+
l(fmt.Errorf("invalid target denom %q for %s: %w; falling back to %q", targetDenom, cc.name, err, fallback))
1039+
targetDenom = fallback
1040+
}
1041+
10141042
totalRewards := github_com_cosmos_cosmos_sdk_types.NewDecCoinFromDec(targetDenom, totalAmount)
10151043

10161044
coinPrice, err := td.coinMarketCapClient.GetPrice(td.ctx, cc.Slug)

td2/chain-details.go

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,8 @@ type CosmosDirectoryChainData struct {
177177
Path string `json:"path"`
178178
ChainName string `json:"chain_name"`
179179
Symbol string `json:"symbol"`
180-
Decimals int `json:"decimals"`
180+
Display string `json:"display"`
181+
Decimals uint32 `json:"decimals"`
181182
Denom string `json:"denom"`
182183
Params CDParams `json:"params"`
183184
Assets []CDAsset `json:"assets"`
@@ -387,7 +388,35 @@ func (cc *ChainConfig) getChainInfoFromCosmosDirectory() (communityTax float64,
387388
func (cc *ChainConfig) getBankMetadataFromCosmosDirectory(denom string) *bank.Metadata {
388389
cdAsset := cc.getDenomMetadataFromCosmosDirectory(denom)
389390
if cdAsset == nil {
390-
return nil
391+
if cc.cosmosDirectoryData == nil || cc.cosmosDirectoryData.Denom == "" {
392+
return nil
393+
}
394+
display := cc.cosmosDirectoryData.Display
395+
if display == "" {
396+
display = cc.cosmosDirectoryData.Symbol
397+
}
398+
399+
denomUnits := []*bank.DenomUnit{
400+
{
401+
Denom: cc.cosmosDirectoryData.Denom,
402+
Exponent: 0,
403+
},
404+
}
405+
if display != "" && display != cc.cosmosDirectoryData.Denom {
406+
denomUnits = append(denomUnits, &bank.DenomUnit{
407+
Denom: display,
408+
Exponent: cc.cosmosDirectoryData.Decimals,
409+
})
410+
}
411+
412+
return &bank.Metadata{
413+
Description: "",
414+
DenomUnits: denomUnits,
415+
Base: cc.cosmosDirectoryData.Denom,
416+
Display: display,
417+
Name: cc.cosmosDirectoryData.ChainName,
418+
Symbol: cc.cosmosDirectoryData.Symbol,
419+
}
391420
}
392421

393422
// Convert CDDenomUnit to bank.DenomUnit

td2/provider-default.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,27 @@ func (d *DefaultProvider) QuerySlashingParams(ctx context.Context) (*slashing.Pa
362362
return &params.Params, nil
363363
}
364364

365+
func (d *DefaultProvider) QueryStakingParams(ctx context.Context) (*staking.Params, error) {
366+
qParams := &staking.QueryParamsRequest{}
367+
b, err := qParams.Marshal()
368+
if err != nil {
369+
return nil, fmt.Errorf("marshal staking params: %w", err)
370+
}
371+
resp, err := d.ChainConfig.client.ABCIQuery(ctx, "/cosmos.staking.v1beta1.Query/Params", b)
372+
if err != nil {
373+
return nil, fmt.Errorf("query staking params: %w", err)
374+
}
375+
if resp.Response.Value == nil {
376+
return nil, errors.New("🛑 could not query staking params, got empty response")
377+
}
378+
params := &staking.QueryParamsResponse{}
379+
err = params.Unmarshal(resp.Response.Value)
380+
if err != nil {
381+
return nil, fmt.Errorf("unmarshal staking params: %w", err)
382+
}
383+
return &params.Params, nil
384+
}
385+
365386
func (d *DefaultProvider) QueryChainInfo(ctx context.Context) (totalSupply float64, communityTax float64, inflationRate float64, err error) {
366387
// Query total supply using bank module
367388
supplyQueryParams := bank.QuerySupplyOfRequest{

td2/provider-namada.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,10 @@ func (d *NamadaProvider) QuerySlashingParams(ctx context.Context) (*slashing.Par
295295
return &slashing.Params{SignedBlocksWindow: int64(livenessInfo.LivenessWindowLen), MinSignedPerWindow: cosmos_sdk_types.MustNewDecFromStr(livenessInfo.LivenessThreshold.String())}, nil
296296
}
297297

298+
func (d *NamadaProvider) QueryStakingParams(ctx context.Context) (*staking.Params, error) {
299+
return nil, errors.New("QueryStakingParams with ABCIQuery not implemented for Namada")
300+
}
301+
298302
func (d *NamadaProvider) QueryDenomMetadata(ctx context.Context, denom string) (medatada *bank.Metadata, err error) {
299303
return nil, errors.New("QueryDenomMetadata with ABCIQuery not implemented for Namada")
300304
}

td2/types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,7 @@ type ChainProvider interface {
754754
QueryValidatorInfo(ctx context.Context) (pub []byte, moniker string, jailed bool, bonded bool, delegatedTokens float64, commissionRate float64, err error)
755755
QuerySigningInfo(ctx context.Context) (*slashing.ValidatorSigningInfo, error)
756756
QuerySlashingParams(ctx context.Context) (*slashing.Params, error)
757+
QueryStakingParams(ctx context.Context) (*staking.Params, error)
757758
QueryValidatorVotingPool(ctx context.Context) (votingPool *staking.Pool, err error)
758759
QueryValidatorSelfDelegationRewardsAndCommission(ctx context.Context) (rewards *github_com_cosmos_cosmos_sdk_types.DecCoins, commission *github_com_cosmos_cosmos_sdk_types.DecCoins, err error)
759760
QueryDenomMetadata(ctx context.Context, denom string) (medatada *bank.Metadata, err error)

td2/utils/price-conversion.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,9 @@ func ConvertDecCoinToDisplayUnit(coins []github_com_cosmos_cosmos_sdk_types.DecC
239239
} else {
240240
displayDenom = metadata.Display
241241
}
242+
if err := github_com_cosmos_cosmos_sdk_types.ValidateDenom(displayDenom); err != nil {
243+
return nil, fmt.Errorf("invalid display denom %q for base %q: %w", displayDenom, metadata.Base, err)
244+
}
242245

243246
// Find the exponent for the display denom
244247
foundDisplayDenom := false
@@ -325,11 +328,17 @@ func ConvertFloatInBaseUnitToDisplayUnit(value float64, metadata bank.Metadata)
325328
// If no display is set, default to base
326329
if metadata.Display == "" {
327330
displayDenom = metadata.Base
331+
if err := github_com_cosmos_cosmos_sdk_types.ValidateDenom(displayDenom); err != nil {
332+
return 0, "", fmt.Errorf("invalid display denom %q for base %q: %w", displayDenom, metadata.Base, err)
333+
}
328334
// If display is base, no conversion needed
329335
return value, displayDenom, nil
330336
} else {
331337
displayDenom = metadata.Display
332338
}
339+
if err := github_com_cosmos_cosmos_sdk_types.ValidateDenom(displayDenom); err != nil {
340+
return 0, "", fmt.Errorf("invalid display denom %q for base %q: %w", displayDenom, metadata.Base, err)
341+
}
333342

334343
// Find the exponent for the display denom
335344
foundDisplayDenom := false

td2/validator.go

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -196,26 +196,48 @@ func (cc *ChainConfig) GetValInfo(first bool) (err error) {
196196
rewards, commission, err := provider.QueryValidatorSelfDelegationRewardsAndCommission(ctx)
197197
if err == nil {
198198
// query the chain's denom metadata, only query once since this does not change
199-
if first && rewards != nil && len(*rewards) > 0 {
200-
bankMeta, err := provider.QueryDenomMetadata(ctx, (*rewards)[0].Denom)
199+
if first {
200+
bondDenom := ""
201+
stakingParams, err := provider.QueryStakingParams(ctx)
201202
if err == nil {
202-
cc.denomMetadata = bankMeta
203+
bondDenom = stakingParams.BondDenom
203204
} else {
204-
l(fmt.Errorf("cannot query bank metadata for chain %s via ABCI, err: %w, trying cosmos.directory fallback", cc.name, err))
205-
// Try cosmos.directory fallback first
206-
bankMeta = cc.getBankMetadataFromCosmosDirectory((*rewards)[0].Denom)
207-
if bankMeta != nil {
205+
l(fmt.Errorf("cannot query staking params for chain %s via ABCI, err: %w", cc.name, err))
206+
}
207+
if bondDenom == "" && cc.hasCosmosDirectoryData() {
208+
if cc.cosmosDirectoryData.Params.Staking.BondDenom != "" {
209+
bondDenom = cc.cosmosDirectoryData.Params.Staking.BondDenom
210+
} else if cc.cosmosDirectoryData.Denom != "" {
211+
bondDenom = cc.cosmosDirectoryData.Denom
212+
}
213+
}
214+
if bondDenom == "" && rewards != nil && len(*rewards) > 0 {
215+
bondDenom = (*rewards)[0].Denom
216+
}
217+
218+
if bondDenom != "" {
219+
bankMeta, err := provider.QueryDenomMetadata(ctx, bondDenom)
220+
if err == nil {
208221
cc.denomMetadata = bankMeta
209-
l(fmt.Sprintf("✅ loaded bank metadata for chain %s from cosmos.directory", cc.name))
210222
} else {
211-
l(fmt.Sprintf("ℹ️ cosmos.directory bank metadata not available for chain %s, trying GitHub fallback", cc.name))
212-
bankMeta, err = cc.fetchBankMetadataFromGitHub()
213-
if err == nil {
223+
l(fmt.Errorf("cannot query bank metadata for chain %s via ABCI, err: %w, trying cosmos.directory fallback", cc.name, err))
224+
// Try cosmos.directory fallback (assets first, then chain data)
225+
bankMeta = cc.getBankMetadataFromCosmosDirectory(bondDenom)
226+
if bankMeta != nil {
214227
cc.denomMetadata = bankMeta
228+
l(fmt.Sprintf("✅ loaded bank metadata for chain %s from cosmos.directory", cc.name))
215229
} else {
216-
l(fmt.Errorf("cannot find bank metadata for chain %s in the GitHub JSON file, err: %w", cc.name, err))
230+
l(fmt.Sprintf("ℹ️ cosmos.directory bank metadata not available for chain %s, trying GitHub fallback", cc.name))
231+
bankMeta, err = cc.fetchBankMetadataFromGitHub()
232+
if err == nil {
233+
cc.denomMetadata = bankMeta
234+
} else {
235+
l(fmt.Errorf("cannot find bank metadata for chain %s in the GitHub JSON file, err: %w", cc.name, err))
236+
}
217237
}
218238
}
239+
} else {
240+
l(fmt.Sprintf("⚠️ could not determine bond denom for chain %s, skipping denom metadata query", cc.name))
219241
}
220242
}
221243

0 commit comments

Comments
 (0)