@@ -2,6 +2,7 @@ package market
22
33import (
44 "context"
5+ "errors"
56 "sync"
67 "time"
78
@@ -11,6 +12,7 @@ import (
1112 "github.com/ethereum/go-ethereum/event"
1213
1314 "github.com/status-im/status-go/internal/circuitbreaker"
15+ provider_errors "github.com/status-im/status-go/internal/healthmanager/provider_errors"
1416 "github.com/status-im/status-go/internal/logutils"
1517 "github.com/status-im/status-go/services/wallet/thirdparty"
1618 tokentypes "github.com/status-im/status-go/services/wallet/token/types"
@@ -100,6 +102,7 @@ func (pm *Manager) setIsConnected(value bool) {
100102
101103func (pm * Manager ) makeCall (providers []thirdparty.MarketDataProvider , f func (provider thirdparty.MarketDataProvider ) (interface {}, error )) (interface {}, error ) {
102104 cmd := circuitbreaker .NewCommand (context .Background (), nil )
105+ cmd .SetNonFailureErrorClassifier (provider_errors .IsIgnorableForConnectivity )
103106 for _ , provider := range providers {
104107 provider := provider
105108 // FIXME: we might want a different circuitName. See other uses of NewFunctor
@@ -111,16 +114,52 @@ func (pm *Manager) makeCall(providers []thirdparty.MarketDataProvider, f func(pr
111114 }
112115
113116 result := pm .circuitbreaker .Execute (cmd )
114- pm .setIsConnected (result .Error () == nil )
117+ isConnectivityError := result .Error () != nil && ! provider_errors .IsIgnorableForConnectivity (result .Error ())
118+ pm .setIsConnected (! isConnectivityError )
115119
116120 if result .Error () != nil {
117- logutils .ZapLogger ().Error ("Error fetching prices" , zap .Error (result .Error ()))
121+ if provider_errors .IsIgnorableForConnectivity (result .Error ()) {
122+ logutils .ZapLogger ().Warn ("market data unavailable for token mapping" , zap .Error (result .Error ()))
123+ } else {
124+ logutils .ZapLogger ().Error ("Error fetching prices" , zap .Error (result .Error ()))
125+ }
118126 return nil , result .Error ()
119127 }
120128
121129 return result .Result ()[0 ], nil
122130}
123131
132+ func (pm * Manager ) fetchHistoricalPricesWithFallback (
133+ token * tokentypes.Token ,
134+ call func (provider thirdparty.MarketDataProvider , token * tokentypes.Token ) ([]thirdparty.HistoricalPrice , error ),
135+ ) ([]thirdparty.HistoricalPrice , error ) {
136+ var sibling * tokentypes.Token
137+ if allTokens , err := pm .tokenManager .GetTokensForFetchingMarketData (); err == nil {
138+ sibling = tokentypes .EthereumMainnetSibling (token , allTokens )
139+ }
140+
141+ for _ , t := range []* tokentypes.Token {token , sibling } {
142+ if t == nil {
143+ continue
144+ }
145+
146+ result , err := pm .makeCall (pm .providers , func (provider thirdparty.MarketDataProvider ) (interface {}, error ) {
147+ return call (provider , t )
148+ })
149+ if err == nil {
150+ return result .([]thirdparty.HistoricalPrice ), nil
151+ }
152+ if ! errors .Is (err , thirdparty .ErrTokenNotMapped ) {
153+ return nil , err
154+ }
155+ }
156+
157+ logutils .ZapLogger ().Warn ("no mapped market history token found" ,
158+ zap .String ("tokenKey" , token .Key ()),
159+ zap .String ("crossChainID" , token .CrossChainID ))
160+ return []thirdparty.HistoricalPrice {}, nil
161+ }
162+
124163func (pm * Manager ) getTokensByKeys (tokensKeys []string ) (tokens []* tokentypes.Token , err error ) {
125164 if len (tokensKeys ) > 0 {
126165 tokens , err = pm .tokenManager .GetTokensByKeysForFetchingMarketData (tokensKeys )
@@ -136,17 +175,9 @@ func (pm *Manager) FetchHistoricalDailyPrices(tokenKey string, currency string,
136175 return nil , err
137176 }
138177
139- result , err := pm .makeCall ( pm . providers , func (provider thirdparty.MarketDataProvider ) (interface {} , error ) {
140- return provider .FetchHistoricalDailyPrices (token , currency , limit , allData , aggregate )
178+ return pm .fetchHistoricalPricesWithFallback ( token , func (provider thirdparty.MarketDataProvider , t * tokentypes. Token ) ([]thirdparty. HistoricalPrice , error ) {
179+ return provider .FetchHistoricalDailyPrices (t , currency , limit , allData , aggregate )
141180 })
142-
143- if err != nil {
144- logutils .ZapLogger ().Error ("Error fetching prices" , zap .Error (err ))
145- return nil , err
146- }
147-
148- prices := result .([]thirdparty.HistoricalPrice )
149- return prices , nil
150181}
151182
152183func (pm * Manager ) FetchHistoricalHourlyPrices (tokenKey string , currency string , limit int , aggregate int ) ([]thirdparty.HistoricalPrice , error ) {
@@ -155,17 +186,9 @@ func (pm *Manager) FetchHistoricalHourlyPrices(tokenKey string, currency string,
155186 return nil , err
156187 }
157188
158- result , err := pm .makeCall ( pm . providers , func (provider thirdparty.MarketDataProvider ) (interface {} , error ) {
159- return provider .FetchHistoricalHourlyPrices (token , currency , limit , aggregate )
189+ return pm .fetchHistoricalPricesWithFallback ( token , func (provider thirdparty.MarketDataProvider , t * tokentypes. Token ) ([]thirdparty. HistoricalPrice , error ) {
190+ return provider .FetchHistoricalHourlyPrices (t , currency , limit , aggregate )
160191 })
161-
162- if err != nil {
163- logutils .ZapLogger ().Error ("Error fetching prices" , zap .Error (err ))
164- return nil , err
165- }
166-
167- prices := result .([]thirdparty.HistoricalPrice )
168- return prices , nil
169192}
170193
171194// FetchTokenMarketValues fetches market values for a given token keys and currency. If no tokens are provided, all tokens are fetched.
0 commit comments