Skip to content

Commit

Permalink
Merge pull request #1380 from consolelabs/fix/support-market-cap-data…
Browse files Browse the repository at this point in the history
…-for-evm-chains

fix: get coin - support market cap data for evm tokens
  • Loading branch information
anhnh12 authored Apr 16, 2024
2 parents 4bbd4b7 + 94f9ed4 commit c06b161
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 11 deletions.
21 changes: 21 additions & 0 deletions pkg/chain/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,27 @@ func (ch *Chain) Balances(address string, tokens []model.Token) (map[string]floa
return balances, nil
}

func (ch *Chain) TokenTotalSupply(address string, decimal int) (float64, error) {
v, err := ch.scan.TokenTotalSupply(address)
if err != nil {
return 0, err
}

if v == nil {
return 0, nil
}

str := v.Int().String()
f, ok := new(big.Float).SetString(str)
f.Quo(f, big.NewFloat(math.Pow10(decimal)))
if !ok {
return 0, nil
}

supply, _ := f.Float64()
return supply, nil
}

// func (ch *Chain) RawBalances(address string, tokens []model.Token) (map[string]*big.Int, error) {
// balances := make(map[string]*big.Int, 0)
// for _, token := range tokens {
Expand Down
81 changes: 70 additions & 11 deletions pkg/entities/defi.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/defipod/mochi/pkg/logger"
"github.com/defipod/mochi/pkg/model"
baseerrs "github.com/defipod/mochi/pkg/model/errors"
"github.com/defipod/mochi/pkg/repo/chain"
coingeckosupportedtokens "github.com/defipod/mochi/pkg/repo/coingecko_supported_tokens"
"github.com/defipod/mochi/pkg/repo/token"
usertokenpricealert "github.com/defipod/mochi/pkg/repo/user_token_price_alert"
Expand Down Expand Up @@ -227,22 +228,80 @@ func (e *Entity) GetCoinData(coinID string, isDominanceChart bool) (*response.Ge

// if no market cap data, get token supply to calculate it
// support solana only for now
if data.AssetPlatformID == "solana" && data.Platforms != nil {
currency := "usd"
if _, ok := data.Platforms[data.AssetPlatformID]; ok && data.MarketData.MarketCap[currency] == 0 {
supply, err := util.GetSplTokenSupply(data.Platforms[data.AssetPlatformID])
if err != nil {
e.log.Fields(logger.Fields{"id": data.AssetPlatformID}).Error(err, "[entity.GetCoinData] util.GetSplTokenSupply() failed")
return data, nil, http.StatusOK
}
price := data.MarketData.CurrentPrice[currency]
data.MarketData.MarketCap[currency] = price * supply
}
// if data.AssetPlatformID == "solana" && data.Platforms != nil {
// currency := "usd"
// if _, ok := data.Platforms[data.AssetPlatformID]; ok && data.MarketData.MarketCap[currency] == 0 {
// supply, err := util.GetSplTokenSupply(data.Platforms[data.AssetPlatformID])
// if err != nil {
// e.log.Fields(logger.Fields{"id": data.AssetPlatformID}).Error(err, "[entity.GetCoinData] util.GetSplTokenSupply() failed")
// return data, nil, http.StatusOK
// }
// price := data.MarketData.CurrentPrice[currency]
// data.MarketData.MarketCap[currency] = price * supply
// }
// }

// if no market cap data, try to find from network api
currency := "usd"
var supply float64
if data.DetailPlatforms != nil && data.Platforms != nil && data.MarketData.MarketCap[currency] == 0 {
platformId := data.AssetPlatformID
detail := data.DetailPlatforms[platformId]
contractAddr := data.Platforms[platformId]
supply = e.getTokenTotalSupply(contractAddr, platformId, detail.DecimalPlace)
price := data.MarketData.CurrentPrice[currency]
data.MarketData.MarketCap[currency] = price * supply
}

return data, nil, http.StatusOK
}

func (e *Entity) getTokenTotalSupply(address, assetPlatformId string, decimal int) float64 {
// no address data -> returns 0
if address == "" || assetPlatformId == "" || decimal == 0 {
return 0
}

// solana
if assetPlatformId == "solana" {
supply, err := util.GetSplTokenSupply(address)
if err != nil {
e.log.Fields(logger.Fields{"address": address, "platform_id": assetPlatformId}).Error(err, "[entity.getTokenTotalSupply] util.GetSplTokenSupply() failed")
}
return supply
}

// evm-based chains
chain, err := e.repo.Chain.GetOne(chain.GetOneQuery{CoingeckoId: assetPlatformId, Type: "evm"})
if err != nil {
e.log.Fields(logger.Fields{"address": address, "platform_id": assetPlatformId}).Error(err, "[entity.getTokenTotalSupply] repo.Chain.GetOne() failed")
return 0
}

apiKey := chain.APIKey
apiBaseUrl := chain.APIBaseURL
if apiKey == "" || apiBaseUrl == "" {
return 0
}

if strings.HasSuffix(apiBaseUrl, "api") {
apiBaseUrl += "?"
}

w := e.dcwallet.Chain(chain.ID)
if w == nil {
e.log.Info("[entity.getTokenTotalSupply] chain not supported")
return 0
}

supply, err := w.TokenTotalSupply(address, decimal)
if err != nil {
e.log.Fields(logger.Fields{"address": address, "platform_id": assetPlatformId}).Error(err, "[entity.getTokenTotalSupply] chain.TokenTotalSupply() failed")
}

return supply
}

func (e *Entity) GetTokenInfo(tokenId string) (*response.TokenInfoResponse, error) {
// get coin data
coinData, err, status := e.GetCoinData(tokenId, false)
Expand Down
11 changes: 11 additions & 0 deletions pkg/repo/chain/pg.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,14 @@ func (pg *pg) GetByShortName(shortName string) (*model.Chain, error) {
}
return chain, nil
}

func (pg *pg) GetOne(q GetOneQuery) (chain *model.Chain, err error) {
db := pg.db
if q.CoingeckoId != "" {
db = db.Where("coin_gecko_id = ?", q.CoingeckoId)
}
if q.Type != "" {
db = db.Where("\"type\" = ?", q.Type)
}
return chain, db.First(&chain).Error
}
6 changes: 6 additions & 0 deletions pkg/repo/chain/query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package chain

type GetOneQuery struct {
CoingeckoId string
Type string
}
1 change: 1 addition & 0 deletions pkg/repo/chain/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ type Store interface {
GetAll() ([]model.Chain, error)
GetByID(id int) (model.Chain, error)
GetByShortName(shortName string) (*model.Chain, error)
GetOne(GetOneQuery) (*model.Chain, error)
}

0 comments on commit c06b161

Please sign in to comment.