package pancakeswapnft import ( "bytes" "encoding/json" "fmt" "github.com/pkg/errors" "github.com/rs/zerolog/log" "io" "net/http" "sync" ) type Profile struct { Address string `json:"address"` Username string `json:"username"` } func getUsernameFromAddress(address string) (string, error) { resp, err := http.Get(fmt.Sprintf("https://profile.pancakeswap.com/api/users/%s", address)) if err != nil { return "", err } defer func(Body io.ReadCloser) { _ = Body.Close() }(resp.Body) raw, err := io.ReadAll(resp.Body) if err != nil { return "", err } if resp.StatusCode != http.StatusOK { return "", errors.Errorf("non 200 http status : %d / raw : %s", resp.StatusCode, raw) } var profile Profile err = json.NewDecoder(bytes.NewReader(raw)).Decode(&profile) if err != nil { return "", err } return profile.Username, nil } type ProfileService struct { cache map[string]string lock *sync.Mutex } func NewProfileService() *ProfileService { return &ProfileService{ cache: make(map[string]string), lock: &sync.Mutex{}, } } func (s *ProfileService) GetUsername(address string) string { s.lock.Lock() defer s.lock.Unlock() if name, ok := s.cache[address]; ok { return name } if name, err := getUsernameFromAddress(address); err != nil { s.cache[address] = address } else { s.cache[address] = name } log.Debug().Msgf("[PROFILE] %s -> %s", address, s.cache[address]) return s.cache[address] }