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 5a2ee98
Show file tree
Hide file tree
Showing 10 changed files with 155 additions and 2 deletions.
7 changes: 7 additions & 0 deletions services/wallet/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,13 @@ func (api *API) GetCollectiblesByUniqueIDAsync(requestID int32, uniqueIDs []thir
return nil
}

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

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

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
83 changes: 83 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 @@ -1036,3 +1037,85 @@ func (o *Manager) SearchCollections(ctx context.Context, chainID walletCommon.Ch
}
return nil, ErrNoProvidersAvailableForChainID
}

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 {
log.Debug("FetchCollectibleSocials failed for", "chainID", uniqueID.ContractID.ChainID, "id", uniqueID, "err", err)
return err
}

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 err
})

group.Wait()
return group.Error()
return nil
}

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

// Some provider was found for the chainID
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)

// Only update website if non empty website is found
if len(cmdRes.Result()[0].(string)) > 0 {
website = cmdRes.Result()[0].(string)
}
// Only update twitterHandle if non empty twitterHandle is found
if len(cmdRes.Result()[1].(string)) > 0 {
twitterHandle = cmdRes.Result()[1].(string)
}

if cmdRes.Error() == nil && len(website) > 0 && len(twitterHandle) > 0 {
break
} else {
continue
}
}

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

return website, twitterHandle, cmdRes.Error()
}
18 changes: 17 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 @@ -547,3 +557,9 @@ func (s *Service) notifyCommunityCollectiblesReceived(ownedCollectibles OwnedCol
Message: string(encodedMessage),
})
}

func (s *Service) FetchCollectibleSocialsAsync(requestID int32, uniqueID thirdparty.CollectibleUniqueID) {
s.scheduler.Enqueue(requestID, fetchCollectibleSocialsTask, func(ctx context.Context) (interface{}, error) {
return "", s.manager.FetchCollectibleSocialsAsync(ctx, uniqueID)
}, func(result interface{}, taskType async.TaskType, err error) {})
}
11 changes: 11 additions & 0 deletions services/wallet/thirdparty/alchemy/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,17 @@ 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 {
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
12 changes: 12 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,18 @@ 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) {
resp, err := o.FetchCollectionsDataByContractID(ctx, []thirdparty.ContractID{uniqueID.ContractID})
if err != nil {
return "", "", err
}
if len(resp) > 0 {
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: 12 additions & 1 deletion services/wallet/thirdparty/rarible/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ type Client struct {

func NewClient(mainnetAPIKey string, testnetAPIKey string) *Client {
if mainnetAPIKey == "" {
log.Warn("Rarible API key not available for Mainnet")
log.Warn("Rarible API key not available for Mainnet")
}

if testnetAPIKey == "" {
Expand Down Expand Up @@ -390,6 +390,17 @@ 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 {
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 5a2ee98

Please sign in to comment.