package evm import ( "sync" "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" ) type TokenService interface { TokenBySymbol(symbol string) (Token, error) TokenAddressBySymbol(symbol string) (common.Address, error) TokenByAddress(address common.Address) (Token, error) } type tokenService struct { client Client cache map[common.Address]Token cachelock *sync.Mutex tokenmapper TokenMapper } func NewTokenService(client Client, tm TokenMapper) TokenService { return &tokenService{ client: client, cache: make(map[common.Address]Token), cachelock: &sync.Mutex{}, tokenmapper: tm, } } func (s *tokenService) TokenBySymbol(symbol string) (Token, error) { address, err := s.tokenmapper.GetTokenAddress(symbol) if err != nil { return nil, errors.Wrapf(err, "getting address for symbol %s", symbol) } return s.TokenByAddress(address) } func (s *tokenService) TokenAddressBySymbol(symbol string) (common.Address, error) { return s.tokenmapper.GetTokenAddress(symbol) } func (s *tokenService) TokenByAddress(address common.Address) (Token, error) { s.cachelock.Lock() defer s.cachelock.Unlock() if t, ok := s.cache[address]; ok { return t, nil } t, err := NewToken(s.client, address) if err != nil { return nil, errors.Wrap(err, "getting token from blockchain") } s.cache[address] = t return t, nil }