2023-02-17 14:11:07 +00:00
|
|
|
package currency
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"database/sql"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/event"
|
2024-09-26 22:37:32 +00:00
|
|
|
gocommon "github.com/status-im/status-go/common"
|
2023-02-21 09:05:16 +00:00
|
|
|
"github.com/status-im/status-go/services/wallet/market"
|
2023-02-17 14:11:07 +00:00
|
|
|
"github.com/status-im/status-go/services/wallet/token"
|
|
|
|
"github.com/status-im/status-go/services/wallet/walletevent"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
EventCurrencyTickUpdateFormat walletevent.EventType = "wallet-currency-tick-update-format"
|
|
|
|
|
|
|
|
currencyFormatUpdateInterval = 1 * time.Hour
|
|
|
|
)
|
|
|
|
|
|
|
|
type Service struct {
|
|
|
|
currency *Currency
|
|
|
|
db *DB
|
|
|
|
|
|
|
|
tokenManager *token.Manager
|
|
|
|
walletFeed *event.Feed
|
|
|
|
cancelFn context.CancelFunc
|
|
|
|
}
|
|
|
|
|
2023-02-21 09:05:16 +00:00
|
|
|
func NewService(db *sql.DB, walletFeed *event.Feed, tokenManager *token.Manager, marketManager *market.Manager) *Service {
|
2023-02-17 14:11:07 +00:00
|
|
|
return &Service{
|
2023-02-21 09:05:16 +00:00
|
|
|
currency: NewCurrency(marketManager),
|
2023-02-17 14:11:07 +00:00
|
|
|
db: NewCurrencyDB(db),
|
|
|
|
tokenManager: tokenManager,
|
|
|
|
walletFeed: walletFeed,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Service) Start() {
|
|
|
|
// Update all fiat currency formats in cache
|
|
|
|
fiatFormats, err := s.getAllFiatCurrencyFormats()
|
|
|
|
|
|
|
|
if err == nil {
|
|
|
|
_ = s.db.UpdateCachedFormats(fiatFormats)
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
s.cancelFn = cancel
|
|
|
|
|
|
|
|
go func() {
|
2024-09-26 22:37:32 +00:00
|
|
|
defer gocommon.LogOnPanic()
|
2023-02-17 14:11:07 +00:00
|
|
|
ticker := time.NewTicker(currencyFormatUpdateInterval)
|
|
|
|
defer ticker.Stop()
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
return
|
|
|
|
case <-ticker.C:
|
|
|
|
s.walletFeed.Send(walletevent.Event{
|
|
|
|
Type: EventCurrencyTickUpdateFormat,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Service) Stop() {
|
|
|
|
if s.cancelFn != nil {
|
|
|
|
s.cancelFn()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Service) GetCachedCurrencyFormats() (FormatPerSymbol, error) {
|
|
|
|
return s.db.GetCachedFormats()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Service) FetchAllCurrencyFormats() (FormatPerSymbol, error) {
|
|
|
|
// Only token prices can change, so we fetch those
|
|
|
|
tokenFormats, err := s.fetchAllTokenCurrencyFormats()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
err = s.db.UpdateCachedFormats(tokenFormats)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return s.GetCachedCurrencyFormats()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Service) getAllFiatCurrencyFormats() (FormatPerSymbol, error) {
|
|
|
|
return GetFiatCurrencyFormats(GetAllFiatCurrencySymbols())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Service) fetchAllTokenCurrencyFormats() (FormatPerSymbol, error) {
|
2023-10-17 15:05:05 +00:00
|
|
|
tokens, err := s.tokenManager.GetAllTokens()
|
2023-02-17 14:11:07 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
tokenPerSymbolMap := make(map[string]bool)
|
|
|
|
tokenSymbols := make([]string, 0)
|
|
|
|
for _, t := range tokens {
|
|
|
|
symbol := t.Symbol
|
|
|
|
if !tokenPerSymbolMap[symbol] {
|
|
|
|
tokenPerSymbolMap[symbol] = true
|
|
|
|
tokenSymbols = append(tokenSymbols, symbol)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-07 11:02:52 +00:00
|
|
|
tokenFormats, err := s.currency.FetchTokenCurrencyFormats(tokenSymbols)
|
2023-11-09 15:25:29 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2023-09-07 11:02:52 +00:00
|
|
|
gweiSymbol := "Gwei"
|
|
|
|
tokenFormats[gweiSymbol] = Format{
|
|
|
|
Symbol: gweiSymbol,
|
|
|
|
DisplayDecimals: 9,
|
|
|
|
StripTrailingZeroes: true,
|
|
|
|
}
|
|
|
|
return tokenFormats, err
|
2023-02-17 14:11:07 +00:00
|
|
|
}
|