Skip to content

Commit

Permalink
fix: Add twitterHandle for a collectible
Browse files Browse the repository at this point in the history
  • Loading branch information
Khushboo-dev-cpp committed Apr 8, 2024
1 parent 3bd00cb commit 76e70a5
Show file tree
Hide file tree
Showing 11 changed files with 190 additions and 1 deletion.
6 changes: 6 additions & 0 deletions services/wallet/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,12 @@ func (api *API) GetCollectiblesByUniqueIDAsync(requestID int32, uniqueIDs []thir
return nil
}

func (api *API) FetchCollectibleSocialsAsync(requestID int32, uniqueID thirdparty.CollectibleUniqueID, dataType collectibles.CollectibleDataType) error {
log.Debug("wallet.api.FetchCollectibleSocialsAsync", "requestID", requestID, "uniqueID", uniqueID, "dataType", dataType)

return api.s.collectibles.FetchCollectibleSocialsAsync(requestID, uniqueID, dataType)
}

func (api *API) GetCollectibleOwnersByContractAddress(ctx context.Context, chainID wcommon.ChainID, contractAddress common.Address) (*thirdparty.CollectibleContractOwnership, error) {
log.Debug("call to GetCollectibleOwnersByContractAddress")
return api.s.collectiblesManager.FetchCollectibleOwnersByContractAddress(ctx, chainID, contractAddress)
Expand Down
79 changes: 79 additions & 0 deletions services/wallet/collectibles/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ var (

type ManagerInterface interface {
FetchAssetsByCollectibleUniqueID(ctx context.Context, uniqueIDs []thirdparty.CollectibleUniqueID, asyncFetch bool) ([]thirdparty.FullCollectibleData, error)
FetchCollectibleSocialsAsync(ctx context.Context, uniqueID thirdparty.CollectibleUniqueID) error
}

type Manager struct {
Expand Down Expand Up @@ -385,6 +386,84 @@ func (o *Manager) FetchAssetsByCollectibleUniqueID(ctx context.Context, uniqueID
return o.getCacheFullCollectibleData(uniqueIDs)
}

func (o *Manager) FetchCollectibleSocialsAsync(ctx context.Context, uniqueID thirdparty.CollectibleUniqueID) error {

// Atomic group stores the error from the first failed command and stops other commands on error
group := async.NewAtomicGroup(ctx)
group.Add(func(ctx context.Context) error {
defer o.checkConnectionStatus(uniqueID.ContractID.ChainID)

website, twitterHandle, err := o.fetchSocialsForCollectibleUniqueID(ctx, uniqueID.ContractID.ChainID, uniqueID)
if err != nil {
fmt.Println("FetchCollectibleSocialsAsync failed for", "chainID", uniqueID.ContractID.ChainID, "id", uniqueID, "err", err)
return err
}
fmt.Println("website = ",website, " twitterHandle = ",twitterHandle)

socials := CollectibleSocialsMessage {
Website: website,
TwitterHandle: twitterHandle,
}

payload, err := json.Marshal(socials)
if err != nil {
log.Error("Error marshaling response: %v", err)
return nil
}

event := walletevent.Event{
Type: EventGetCollectibleSocialsDone,
Message: string(payload),
}

o.feed.Send(event)
return nil
})

group.Wait()
return group.Error()

}

func (o *Manager) fetchSocialsForCollectibleUniqueID(ctx context.Context, chainID walletCommon.ChainID, idToFetch thirdparty.CollectibleUniqueID) (string, string, error) {
cmdRes:= circuitbreaker.CommandResult{}
website := ""
twitterHandle := ""
providerFound:= false
for _, provider := range o.providers.CollectibleDataProviders {
cmd := circuitbreaker.Command{}
if !provider.IsChainSupported(chainID) {
continue
}

providerFound = true
provider := provider
cmd.Add(circuitbreaker.NewFunctor(func() ([]any, error) {
w, t, err := provider.FetchCollectibleSocialsByUniqueID(ctx, idToFetch)
return []any{w, t}, err
}))

cmdRes = o.getCircuitBreaker(chainID).Execute(cmd)
if cmdRes.Error() != nil || len(cmdRes.Result()[0].(string)) == 0 || len(cmdRes.Result()[1].(string)) == 0 {
log.Error("fetchSocialsForCollectibleUniqueID failed for", "provider", provider.ID(), "chainID", chainID, "err", cmdRes.Error())
continue
}
if len(cmdRes.Result()[0].(string)) != 0 {
website = cmdRes.Result()[0].(string)
}
if len(cmdRes.Result()[1].(string)) != 0 {
twitterHandle = cmdRes.Result()[1].(string)
}
break
}

if !providerFound {
return "", "", ErrNoProvidersAvailableForChainID // lets not stop the group if no providers are available for the chain
}

return website, twitterHandle, cmdRes.Error()
}

func (o *Manager) FetchMissingAssetsByCollectibleUniqueID(ctx context.Context, uniqueIDs []thirdparty.CollectibleUniqueID, asyncFetch bool) error {
missingIDs, err := o.collectiblesDataDB.GetIDsNotInDB(uniqueIDs)
if err != nil {
Expand Down
51 changes: 50 additions & 1 deletion services/wallet/collectibles/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const (

EventOwnedCollectiblesFilteringDone walletevent.EventType = "wallet-owned-collectibles-filtering-done"
EventGetCollectiblesDetailsDone walletevent.EventType = "wallet-get-collectibles-details-done"
EventGetCollectibleSocialsDone walletevent.EventType = "wallet-get-collectible-socials-done"
)

type OwnershipUpdateMessage struct {
Expand All @@ -52,6 +53,11 @@ const (
CollectibleDataTypeCommunityHeader
)

type CollectibleSocialsMessage struct {
Website string `json:"website"`
TwitterHandle string `json:"twitterHandle"`
}

type FetchType byte

const (
Expand Down Expand Up @@ -79,7 +85,11 @@ var (
getCollectiblesDataTask = async.TaskType{
ID: 2,
Policy: async.ReplacementPolicyCancelOld,
}
}
fetchCollectibleSocialsTask = async.TaskType{
ID: 3,
Policy: async.ReplacementPolicyCancelOld,
}
)

type Service struct {
Expand Down Expand Up @@ -150,6 +160,12 @@ type GetCollectiblesByUniqueIDResponse struct {
ErrorCode ErrorCode `json:"errorCode"`
}

type FetchCollectibleSocialsResponse struct {
Website string `json:"website"`
TwitterHandle string `json:"twitterHandle"`
ErrorCode ErrorCode `json:"errorCode"`
}

type GetOwnedCollectiblesReturnType struct {
collectibles []Collectible
hasMore bool
Expand All @@ -160,6 +176,11 @@ type GetCollectiblesByUniqueIDReturnType struct {
collectibles []Collectible
}

type FetchCollectibleSocialsReturnType struct {
website string
twitterHandle string
}

func (s *Service) GetOwnedCollectibles(
ctx context.Context,
chainIDs []walletCommon.ChainID,
Expand Down Expand Up @@ -318,6 +339,34 @@ func (s *Service) GetCollectiblesByUniqueIDAsync(
})
}

func (s *Service) FetchCollectibleSocials(
ctx context.Context,
uniqueID thirdparty.CollectibleUniqueID,
dataType CollectibleDataType) error {
result := s.manager.FetchCollectibleSocialsAsync(ctx, uniqueID)
return result
}

func (s *Service) FetchCollectibleSocialsAsync(
requestID int32,
uniqueID thirdparty.CollectibleUniqueID,
dataType CollectibleDataType) error {
s.scheduler.Enqueue(requestID, fetchCollectibleSocialsTask, func(ctx context.Context) (interface{}, error) {
return "", s.FetchCollectibleSocials(ctx, uniqueID, dataType)
}, func(result interface{}, taskType async.TaskType, err error) {
res := FetchCollectibleSocialsResponse{
ErrorCode: ErrorCodeFailed,
}

if errors.Is(err, context.Canceled) || errors.Is(err, async.ErrTaskOverwritten) {
res.ErrorCode = ErrorCodeTaskCanceled
} else if err == nil {
res.ErrorCode = ErrorCodeSuccess
}
})
return nil
}

func (s *Service) RefetchOwnedCollectibles() {
s.controller.RefetchOwnedCollectibles()
}
Expand Down
3 changes: 3 additions & 0 deletions services/wallet/collectibles/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type CollectionData struct {
Name string `json:"name"`
Slug string `json:"slug"`
ImageURL string `json:"image_url"`
TwitterHandle string `json:"twitter_handle"`
}

type CommunityData struct {
Expand Down Expand Up @@ -91,6 +92,7 @@ func fullCollectibleDataToHeader(c thirdparty.FullCollectibleData) Collectible {
Name: c.CollectionData.Name,
Slug: c.CollectionData.Slug,
ImageURL: c.CollectionData.ImageURL,
TwitterHandle: c.CollectionData.TwitterHandle,
}
}
if c.CollectibleData.CommunityID != "" {
Expand Down Expand Up @@ -132,6 +134,7 @@ func fullCollectibleDataToDetails(c thirdparty.FullCollectibleData) Collectible
Name: c.CollectionData.Name,
Slug: c.CollectionData.Slug,
ImageURL: c.CollectionData.ImageURL,
TwitterHandle: c.CollectionData.TwitterHandle,
}
}
if c.CollectibleData.CommunityID != "" {
Expand Down
12 changes: 12 additions & 0 deletions services/wallet/thirdparty/alchemy/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,18 @@ func (o *Client) FetchAssetsByCollectibleUniqueID(ctx context.Context, uniqueIDs
return ret, nil
}

func (o *Client) FetchCollectibleSocialsByUniqueID(ctx context.Context, uniqueID thirdparty.CollectibleUniqueID) (string, string, error) {
resp, err := o.FetchCollectionsDataByContractID(ctx, []thirdparty.ContractID{uniqueID.ContractID})
if err != nil {
return "", "", err
}
if len(resp) > 0 {
fmt.Println("ALCHEMY FetchCollectibleSocialsByUniqueID uniqueID ",uniqueID, "website = ",resp[0].Website, " TwitterHandle ", resp[0].TwitterHandle)
return resp[0].Website, resp[0].TwitterHandle, nil
}
return "", "", nil
}

func getContractAddressBatches(ids []thirdparty.ContractID) []BatchContractAddresses {
batches := make([]BatchContractAddresses, 0)

Expand Down
4 changes: 4 additions & 0 deletions services/wallet/thirdparty/alchemy/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ func (r *Raw) UnmarshalJSON(b []byte) error {

type OpenSeaMetadata struct {
ImageURL string `json:"imageUrl"`
TwitterUsername string `json:"twitterUsername"`
ExternalUrl string `json:"externalUrl"`
}

type Contract struct {
Expand Down Expand Up @@ -192,6 +194,8 @@ func (c *Contract) toCollectionData(id thirdparty.ContractID) thirdparty.Collect
Name: c.Name,
ImageURL: c.OpenSeaMetadata.ImageURL,
Traits: make(map[string]thirdparty.CollectionTrait, 0),
Website: c.OpenSeaMetadata.ExternalUrl,
TwitterHandle: c.OpenSeaMetadata.TwitterUsername,
}
return ret
}
Expand Down
3 changes: 3 additions & 0 deletions services/wallet/thirdparty/collectible_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ type CollectionData struct {
ImageURL string `json:"image_url"`
ImagePayload []byte
Traits map[string]CollectionTrait `json:"traits"`
Website string `json:"website"`
TwitterHandle string `json:"twitter_handle"`
}

type CollectibleTrait struct {
Expand Down Expand Up @@ -272,6 +274,7 @@ type CollectibleAccountOwnershipProvider interface {
type CollectibleDataProvider interface {
CollectibleProvider
FetchAssetsByCollectibleUniqueID(ctx context.Context, uniqueIDs []CollectibleUniqueID) ([]FullCollectibleData, error)
FetchCollectibleSocialsByUniqueID(ctx context.Context, uniqueID CollectibleUniqueID) (string, string, error)
}

type CollectionDataProvider interface {
Expand Down
14 changes: 14 additions & 0 deletions services/wallet/thirdparty/opensea/client_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,20 @@ func (o *ClientV2) FetchAssetsByCollectibleUniqueID(ctx context.Context, uniqueI
return o.fetchDetailedAssets(ctx, uniqueIDs)
}

func (o *ClientV2) FetchCollectibleSocialsByUniqueID(ctx context.Context, uniqueID thirdparty.CollectibleUniqueID) (string, string, error) {
ret := []thirdparty.ContractID{uniqueID.ContractID}
resp, err := o.FetchCollectionsDataByContractID(ctx, ret)
if err != nil {
return "", "", err
}
if len(resp) > 0 {
fmt.Println("OPENSEA FetchCollectibleSocialsByUniqueID uniqueID ",uniqueID, "website = ",resp[0].Website, "TwitterHandle ",resp[0].TwitterHandle)
return resp[0].Website, resp[0].TwitterHandle, nil
}
return "", "", nil
}


func (o *ClientV2) fetchAssets(ctx context.Context, chainID walletCommon.ChainID, pathParams []string, queryParams url.Values, limit int, cursor string) (*thirdparty.FullCollectibleDataContainer, error) {
assets := new(thirdparty.FullCollectibleDataContainer)

Expand Down
4 changes: 4 additions & 0 deletions services/wallet/thirdparty/opensea/types_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ type CollectionData struct {
Owner common.Address `json:"owner"`
ImageURL string `json:"image_url"`
Contracts []ContractID `json:"contracts"`
Website string `json:"project_url"`
TwitterHandle string `json:"twitter_username"`
}

func (c *NFT) id(chainID walletCommon.ChainID) thirdparty.CollectibleUniqueID {
Expand Down Expand Up @@ -233,6 +235,8 @@ func (c *CollectionData) toCommon(id thirdparty.ContractID, tokenStandard string
Name: c.Name,
Slug: c.Collection,
ImageURL: c.ImageURL,
Website: c.Website,
TwitterHandle: c.TwitterHandle,
}
return ret
}
13 changes: 13 additions & 0 deletions services/wallet/thirdparty/rarible/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,19 @@ func (o *Client) FetchAssetsByCollectibleUniqueID(ctx context.Context, uniqueIDs
return ret, nil
}

func (o *Client) FetchCollectibleSocialsByUniqueID(ctx context.Context, uniqueID thirdparty.CollectibleUniqueID) (string, string, error) {
ret := []thirdparty.ContractID{uniqueID.ContractID}
resp, err := o.FetchCollectionsDataByContractID(ctx, ret)
if err != nil {
return "", "", err
}
if len(resp) > 0 {
fmt.Println("RARIBLE FetchCollectibleSocialsByUniqueID uniqueID ",uniqueID, "Website = ", resp[0].Website, " TwitterHandle ",resp[0].TwitterHandle)
return resp[0].Website, resp[0].TwitterHandle, nil
}
return "", "", nil
}

func (o *Client) FetchCollectionsDataByContractID(ctx context.Context, contractIDs []thirdparty.ContractID) ([]thirdparty.CollectionData, error) {
ret := make([]thirdparty.CollectionData, 0, len(contractIDs))

Expand Down
2 changes: 2 additions & 0 deletions services/wallet/thirdparty/rarible/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ type CollectionMetadata struct {
Name string `json:"name"`
Description string `json:"description"`
Contents []Content `json:"content"`
ExternalLink string `json:"externalLink"`
}

type Content struct {
Expand Down Expand Up @@ -319,6 +320,7 @@ func (c *Collection) toCommon(id thirdparty.ContractID) thirdparty.CollectionDat
Slug: "", /* Missing from the API for now */
ImageURL: getImageURL(c.Metadata.Contents),
Traits: make(map[string]thirdparty.CollectionTrait, 0), /* Missing from the API for now */
Website: c.Metadata.ExternalLink,
}
return ret
}
Expand Down

0 comments on commit 76e70a5

Please sign in to comment.