diff --git a/oracle/update.go b/oracle/update.go index afd388b08..d645f58a5 100644 --- a/oracle/update.go +++ b/oracle/update.go @@ -19,14 +19,19 @@ func (o *OracleImpl) UpdateMarketMap(marketMap mmtypes.MarketMap) error { o.mut.Lock() defer o.mut.Unlock() - if err := marketMap.ValidateBasic(); err != nil { + validSubset, err := marketMap.GetValidSubset() + if err != nil { o.logger.Error("failed to validate market map", zap.Error(err)) return err } + if len(validSubset.Markets) == 0 { + o.logger.Warn("market map update produced no valid markets to fetch") + } + // Iterate over all existing price providers and update their market maps. for name, state := range o.priceProviders { - providerTickers, err := types.ProviderTickersFromMarketMap(name, marketMap) + providerTickers, err := types.ProviderTickersFromMarketMap(name, validSubset) if err != nil { o.logger.Error("failed to create provider market map", zap.String("provider", name), zap.Error(err)) return err @@ -42,7 +47,7 @@ func (o *OracleImpl) UpdateMarketMap(marketMap mmtypes.MarketMap) error { o.priceProviders[name] = updatedState } - o.marketMap = marketMap + o.marketMap = validSubset if o.aggregator != nil { o.aggregator.UpdateMarketMap(o.marketMap) } diff --git a/oracle/update_test.go b/oracle/update_test.go index 351fd3993..d9aa7d137 100644 --- a/oracle/update_test.go +++ b/oracle/update_test.go @@ -18,7 +18,7 @@ import ( ) func TestUpdateWithMarketMap(t *testing.T) { - t.Run("bad market map is rejected", func(t *testing.T) { + t.Run("bad market map is not rejected", func(t *testing.T) { orc, err := oracle.New( oracleCfg, noOpPriceAggregator{}, @@ -35,7 +35,7 @@ func TestUpdateWithMarketMap(t *testing.T) { "bad": {}, }, }) - require.Error(t, err) + require.NoError(t, err) o.Stop() }) @@ -626,4 +626,60 @@ func TestUpdateProviderState(t *testing.T) { 500*time.Millisecond, ) }) + + t.Run("can update the market map with partial failure on NormalizeBy", func(t *testing.T) { + orc, err := oracle.New( + oracleCfg, + noOpPriceAggregator{}, + oracle.WithLogger(logger), + oracle.WithPriceAPIQueryHandlerFactory(oraclefactory.APIQueryHandlerFactory), + oracle.WithPriceWebSocketQueryHandlerFactory(oraclefactory.WebSocketQueryHandlerFactory), + ) + require.NoError(t, err) + o := orc.(*oracle.OracleImpl) + require.NoError(t, o.Init(context.TODO())) + + providers := o.GetProviderState() + require.Len(t, providers, 3) + + // Update the oracle's market map. + require.NoError(t, o.UpdateMarketMap(partialInvalidMarketMap)) + + providers = o.GetProviderState() + + cbTickers, err := types.ProviderTickersFromMarketMap(coinbase.Name, validMarketMapSubset) + require.NoError(t, err) + + // Check the state after the update. + coinbaseState, ok := providers[coinbase.Name] + require.True(t, ok) + checkProviderState( + t, + cbTickers, + coinbase.Name, + providertypes.API, + false, + coinbaseState, + ) + + okxTickers, err := types.ProviderTickersFromMarketMap(okx.Name, validMarketMapSubset) + require.NoError(t, err) + + okxState, ok := providers[okx.Name] + require.True(t, ok) + checkProviderState( + t, + okxTickers, + okx.Name, + providertypes.WebSockets, + false, + okxState, + ) + + binanceState, ok := providers[binance.Name] + require.True(t, ok) + checkProviderState(t, nil, binance.Name, providertypes.API, false, binanceState) + + o.Stop() + }) }