package pancakeswapnft import ( "bytes" "encoding/json" "fmt" "github.com/pkg/errors" "io" "net/http" "sync" "time" ) type Profile struct { Address string `json:"address"` Username string `json:"username"` Leaderboard struct { Global string `json:"global"` Team string `json:"team"` Volume int `json:"volume"` NextRank string `json:"next_rank"` } `json:"leaderboard"` LeaderboardFantoken struct { Global string `json:"global"` Team string `json:"team"` Volume int `json:"volume"` NextRank string `json:"next_rank"` } `json:"leaderboard_fantoken"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } 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, error) { s.lock.Lock() defer s.lock.Unlock() if name, ok := s.cache[address]; ok { return name, nil } name, err := getUsernameFromAddress(address) if err != nil { return "", err } s.cache[address] = name return name, nil }