@@ -125,36 +125,44 @@ type RateSource interface {
125125 ToggleSource (newSource string ) error
126126 AddRateListener (listener * RateListener , uniqueIdentifier string ) error
127127 RemoveRateListener (uniqueIdentifier string )
128+ AddWarningMsgListener (listener * WarningMsgListener , uniqueIdentifier string ) error
129+ RemoveWarningMsgListener (uniqueIdentifier string )
128130 IsRateListenerExist (uniqueIdentifier string ) bool
131+ IsWarningMsgListenerExist (uniqueIdentifier string ) bool
129132}
130133
131134// RateListener listens for new tickers and rate source change notifications.
132135type RateListener struct {
133136 OnRateUpdated func ()
134137}
135138
139+ // WarningMsgListener listens for new fetch exchange rate settings warning message.
140+ type WarningMsgListener struct {
141+ OnWarningMsgUpdated func (string )
142+ }
143+
136144type tickerFunc func (market values.Market ) (* Ticker , error )
137145
138146// CommonRateSource is an external rate source for fiat and crypto-currency
139147// rates. These rates are estimates and maybe be affected by server latency and
140148// should not be used for actual buy or sell orders except to display reasonable
141149// estimates. CommonRateSource is embedded in all of the rate sources supported.
142150type CommonRateSource struct {
143- ctx context.Context
144- source string
145- disabled bool
146- mtx sync.RWMutex
147- tickers map [values.Market ]* Ticker
148- refreshing bool
149- cond * sync.Cond
150- getTicker tickerFunc
151- sourceChanged chan * struct {}
152- lastUpdate time.Time
153-
151+ ctx context.Context
152+ source string
153+ disabled bool
154+ mtx sync.RWMutex
155+ tickers map [values.Market ]* Ticker
156+ refreshing bool
157+ cond * sync.Cond
158+ getTicker tickerFunc
159+ sourceChanged chan * struct {}
160+ lastUpdate time.Time
154161 disableConversionExchange func ()
155162
156163 notificationListenersMu sync.RWMutex
157164 ratesListeners map [string ]* RateListener
165+ warningMsgListeners map [string ]* WarningMsgListener
158166}
159167
160168// Used to initialize a rate source.
@@ -170,6 +178,7 @@ func NewCommonRateSource(ctx context.Context, source string, disableConversionEx
170178 sourceChanged : make (chan * struct {}),
171179 disableConversionExchange : disableConversionExchange ,
172180 ratesListeners : make (map [string ]* RateListener ),
181+ warningMsgListeners : make (map [string ]* WarningMsgListener ),
173182 }
174183 s .getTicker = s .sourceGetTickerFunc (source )
175184 s .cond = sync .NewCond (& s .mtx )
@@ -220,6 +229,17 @@ func (cs *CommonRateSource) isDisabled() bool {
220229 return cs .disabled
221230}
222231
232+ func (cs * CommonRateSource ) AddWarningMsgListener (listener * WarningMsgListener , uniqueIdentifier string ) error {
233+ if _ , ok := cs .warningMsgListeners [uniqueIdentifier ]; ok {
234+ return errors .New (utils .ErrListenerAlreadyExist )
235+ }
236+
237+ cs .notificationListenersMu .Lock ()
238+ defer cs .notificationListenersMu .Unlock ()
239+ cs .warningMsgListeners [uniqueIdentifier ] = listener
240+ return nil
241+ }
242+
223243func (cs * CommonRateSource ) AddRateListener (listener * RateListener , uniqueIdentifier string ) error {
224244 if _ , ok := cs .ratesListeners [uniqueIdentifier ]; ok {
225245 return errors .New (utils .ErrListenerAlreadyExist )
@@ -236,6 +256,17 @@ func (cs *CommonRateSource) IsRateListenerExist(uniqueIdentifier string) bool {
236256 return ok
237257}
238258
259+ func (cs * CommonRateSource ) IsWarningMsgListenerExist (uniqueIdentifier string ) bool {
260+ _ , ok := cs .warningMsgListeners [uniqueIdentifier ]
261+ return ok
262+ }
263+
264+ func (cs * CommonRateSource ) RemoveWarningMsgListener (uniqueIdentifier string ) {
265+ cs .notificationListenersMu .Lock ()
266+ defer cs .notificationListenersMu .Unlock ()
267+ delete (cs .warningMsgListeners , uniqueIdentifier )
268+ }
269+
239270func (cs * CommonRateSource ) RemoveRateListener (uniqueIdentifier string ) {
240271 cs .notificationListenersMu .Lock ()
241272 defer cs .notificationListenersMu .Unlock ()
@@ -250,6 +281,14 @@ func (cs *CommonRateSource) pushlishRateUpdated() {
250281 }
251282}
252283
284+ func (cs * CommonRateSource ) pushlishWarningMsgUpdated (warningMsg string ) {
285+ for _ , listener := range cs .warningMsgListeners {
286+ if listener .OnWarningMsgUpdated != nil {
287+ listener .OnWarningMsgUpdated (warningMsg )
288+ }
289+ }
290+ }
291+
253292// ToggleSource changes the rate source to newSource. This method takes some
254293// time to refresh the rates and should be executed a a goroutine.
255294func (cs * CommonRateSource ) ToggleSource (newSource string ) error {
@@ -413,21 +452,24 @@ func (cs *CommonRateSource) retryGetTicker(market values.Market) (*Ticker, error
413452 }
414453 // fetch ticker from available exchanges
415454 log .Infof ("fetching from other exchanges" )
455+ invalidSource := cs .source
416456 for _ , source := range sources {
417- if source == cs . source {
457+ if source == invalidSource {
418458 continue
419459 }
420460 getTickerFn := cs .sourceGetTickerFunc (source )
421461 select {
422462 case <- cs .ctx .Done ():
423463 log .Errorf ("fetching ticker canceled: %v" , cs .ctx .Err ())
464+ cs .source = invalidSource
424465 return nil , cs .ctx .Err ()
425466 default :
426467 log .Infof ("fetching %s rate from %v" , market , source )
468+ cs .source = source
427469 newTicker , err = getTickerFn (market )
428470 if err == nil {
471+ cs .pushlishWarningMsgUpdated (fmt .Sprintf (values .String (values .StrFetchRateWarningContent ), invalidSource , source ))
429472 log .Infof ("%s is chosen" , source )
430- cs .source = source
431473 return newTicker , nil
432474 }
433475 }
0 commit comments