Governor should handle duplicate coin gecko ids
This commit is contained in:
parent
09b33552df
commit
5ca2faa9a3
|
@ -105,7 +105,7 @@ type ChainGovernor struct {
|
|||
logger *zap.Logger
|
||||
mutex sync.Mutex
|
||||
tokens map[tokenKey]*tokenEntry
|
||||
tokensByCoinGeckoId map[string]*tokenEntry
|
||||
tokensByCoinGeckoId map[string][]*tokenEntry
|
||||
chains map[vaa.ChainID]*chainEntry
|
||||
msgsToPublish []*common.MessagePublication
|
||||
dayLengthInMinutes int
|
||||
|
@ -122,7 +122,7 @@ func NewChainGovernor(
|
|||
db: db,
|
||||
logger: logger,
|
||||
tokens: make(map[tokenKey]*tokenEntry),
|
||||
tokensByCoinGeckoId: make(map[string]*tokenEntry),
|
||||
tokensByCoinGeckoId: make(map[string][]*tokenEntry),
|
||||
chains: make(map[vaa.ChainID]*chainEntry),
|
||||
env: env,
|
||||
}
|
||||
|
@ -185,6 +185,17 @@ func (gov *ChainGovernor) initConfig() error {
|
|||
te := &tokenEntry{cfgPrice: cfgPrice, price: initialPrice, decimals: decimals, symbol: ct.symbol, coinGeckoId: ct.coinGeckoId, token: key}
|
||||
te.updatePrice()
|
||||
|
||||
gov.tokens[key] = te
|
||||
|
||||
// Multiple tokens can share a CoinGecko price, so we keep an array of tokens per CoinGecko ID.
|
||||
cge, cgExists := gov.tokensByCoinGeckoId[te.coinGeckoId]
|
||||
if !cgExists {
|
||||
gov.tokensByCoinGeckoId[te.coinGeckoId] = []*tokenEntry{te}
|
||||
} else {
|
||||
cge = append(cge, te)
|
||||
gov.tokensByCoinGeckoId[te.coinGeckoId] = cge
|
||||
}
|
||||
|
||||
gov.logger.Info("cgov: will monitor token:", zap.Stringer("chain", key.chain),
|
||||
zap.Stringer("addr", key.addr),
|
||||
zap.String("symbol", te.symbol),
|
||||
|
@ -193,9 +204,6 @@ func (gov *ChainGovernor) initConfig() error {
|
|||
zap.Int64("decimals", dec),
|
||||
zap.Int64("origDecimals", ct.decimals),
|
||||
)
|
||||
|
||||
gov.tokens[key] = te
|
||||
gov.tokensByCoinGeckoId[te.coinGeckoId] = te
|
||||
}
|
||||
|
||||
if len(gov.tokens) == 0 {
|
||||
|
|
|
@ -109,13 +109,13 @@ func (gov *ChainGovernor) queryCoinGecko() {
|
|||
gov.mutex.Lock()
|
||||
defer gov.mutex.Unlock()
|
||||
|
||||
localTokenMap := make(map[string]*tokenEntry)
|
||||
for coinGeckoId, te := range gov.tokensByCoinGeckoId {
|
||||
localTokenMap[coinGeckoId] = te
|
||||
localTokenMap := make(map[string][]*tokenEntry)
|
||||
for coinGeckoId, cge := range gov.tokensByCoinGeckoId {
|
||||
localTokenMap[coinGeckoId] = cge
|
||||
}
|
||||
|
||||
for coinGeckoId, data := range result {
|
||||
te, exists := gov.tokensByCoinGeckoId[coinGeckoId]
|
||||
cge, exists := gov.tokensByCoinGeckoId[coinGeckoId]
|
||||
if exists {
|
||||
price, ok := data.(map[string]interface{})["usd"].(float64)
|
||||
if !ok {
|
||||
|
@ -123,6 +123,8 @@ func (gov *ChainGovernor) queryCoinGecko() {
|
|||
// By continuing, we leave this one in the local map so the price will get reverted below.
|
||||
continue
|
||||
}
|
||||
|
||||
for _, te := range cge {
|
||||
te.coinGeckoPrice = big.NewFloat(price)
|
||||
te.updatePrice()
|
||||
te.priceTime = now
|
||||
|
@ -135,6 +137,7 @@ func (gov *ChainGovernor) queryCoinGecko() {
|
|||
zap.Stringer("cfgPrice", te.cfgPrice),
|
||||
zap.Stringer("coinGeckoPrice", te.coinGeckoPrice),
|
||||
)
|
||||
}
|
||||
|
||||
delete(localTokenMap, coinGeckoId)
|
||||
} else {
|
||||
|
@ -143,7 +146,8 @@ func (gov *ChainGovernor) queryCoinGecko() {
|
|||
}
|
||||
|
||||
if len(localTokenMap) != 0 {
|
||||
for _, te := range localTokenMap {
|
||||
for _, lcge := range localTokenMap {
|
||||
for _, te := range lcge {
|
||||
gov.logger.Error("cgov: did not receive a CoinGecko response for symbol, reverting to configured price",
|
||||
zap.String("symbol", te.symbol),
|
||||
zap.String("coinGeckoId",
|
||||
|
@ -156,12 +160,14 @@ func (gov *ChainGovernor) queryCoinGecko() {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (gov *ChainGovernor) revertAllPrices() {
|
||||
gov.mutex.Lock()
|
||||
defer gov.mutex.Unlock()
|
||||
|
||||
for _, te := range gov.tokensByCoinGeckoId {
|
||||
for _, cge := range gov.tokensByCoinGeckoId {
|
||||
for _, te := range cge {
|
||||
gov.logger.Error("cgov: reverting to configured price",
|
||||
zap.String("symbol", te.symbol),
|
||||
zap.String("coinGeckoId",
|
||||
|
@ -173,6 +179,7 @@ func (gov *ChainGovernor) revertAllPrices() {
|
|||
// Don't update the timestamp so we'll know when we last received an update from CoinGecko.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We should use the max(coinGeckoPrice, configuredPrice) as our price for computing notional value.
|
||||
func (te tokenEntry) updatePrice() {
|
||||
|
|
|
@ -78,7 +78,13 @@ func (gov *ChainGovernor) setTokenForTesting(tokenChainID vaa.ChainID, tokenAddr
|
|||
key := tokenKey{chain: vaa.ChainID(tokenChainID), addr: tokenAddr}
|
||||
te := &tokenEntry{cfgPrice: bigPrice, price: bigPrice, decimals: decimals, symbol: symbol, coinGeckoId: symbol, token: key}
|
||||
gov.tokens[key] = te
|
||||
gov.tokensByCoinGeckoId[symbol] = te
|
||||
cge, cgExists := gov.tokensByCoinGeckoId[te.coinGeckoId]
|
||||
if !cgExists {
|
||||
gov.tokensByCoinGeckoId[te.coinGeckoId] = []*tokenEntry{te}
|
||||
} else {
|
||||
cge = append(cge, te)
|
||||
gov.tokensByCoinGeckoId[te.coinGeckoId] = cge
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue