chore: use single opensea client instance

This commit is contained in:
Dario Gabriel Lipicar 2023-07-10 06:02:17 -03:00 committed by dlipicar
parent f138964a9c
commit 849be69299
4 changed files with 100 additions and 112 deletions

View File

@ -2189,6 +2189,8 @@ func (m *Manager) GetOwnedERC721Tokens(walletAddresses []gethcommon.Address, tok
ownedERC721Tokens := make(CollectiblesByChain) ownedERC721Tokens := make(CollectiblesByChain)
client := m.openseaClientBuilder.NewOpenseaClient(m.walletConfig.OpenseaAPIKey, nil)
for chainID, erc721Tokens := range tokenRequirements { for chainID, erc721Tokens := range tokenRequirements {
skipChain := true skipChain := true

View File

@ -38,10 +38,9 @@ type Manager struct {
mainContractOwnershipProvider thirdparty.CollectibleContractOwnershipProvider mainContractOwnershipProvider thirdparty.CollectibleContractOwnershipProvider
fallbackContractOwnershipProvider thirdparty.CollectibleContractOwnershipProvider fallbackContractOwnershipProvider thirdparty.CollectibleContractOwnershipProvider
metadataProvider thirdparty.CollectibleMetadataProvider metadataProvider thirdparty.CollectibleMetadataProvider
openseaAPIKey string opensea *opensea.Client
nftCache map[uint64]map[string]opensea.Asset nftCache map[uint64]map[string]opensea.Asset
nftCacheLock sync.RWMutex nftCacheLock sync.RWMutex
walletFeed *event.Feed
} }
func NewManager(rpcClient *rpc.Client, mainContractOwnershipProvider thirdparty.CollectibleContractOwnershipProvider, fallbackContractOwnershipProvider thirdparty.CollectibleContractOwnershipProvider, openseaAPIKey string, walletFeed *event.Feed) *Manager { func NewManager(rpcClient *rpc.Client, mainContractOwnershipProvider thirdparty.CollectibleContractOwnershipProvider, fallbackContractOwnershipProvider thirdparty.CollectibleContractOwnershipProvider, openseaAPIKey string, walletFeed *event.Feed) *Manager {
@ -56,9 +55,8 @@ func NewManager(rpcClient *rpc.Client, mainContractOwnershipProvider thirdparty.
rpcClient: rpcClient, rpcClient: rpcClient,
mainContractOwnershipProvider: mainContractOwnershipProvider, mainContractOwnershipProvider: mainContractOwnershipProvider,
fallbackContractOwnershipProvider: fallbackContractOwnershipProvider, fallbackContractOwnershipProvider: fallbackContractOwnershipProvider,
openseaAPIKey: openseaAPIKey, opensea: opensea.NewClient(openseaAPIKey, walletFeed),
nftCache: make(map[uint64]map[string]opensea.Asset), nftCache: make(map[uint64]map[string]opensea.Asset),
walletFeed: walletFeed,
} }
} }
@ -97,20 +95,11 @@ func (o *Manager) SetMetadataProvider(metadataProvider thirdparty.CollectibleMet
} }
func (o *Manager) FetchAllCollectionsByOwner(chainID uint64, owner common.Address) ([]opensea.OwnedCollection, error) { func (o *Manager) FetchAllCollectionsByOwner(chainID uint64, owner common.Address) ([]opensea.OwnedCollection, error) {
client, err := opensea.NewOpenseaClient(chainID, o.openseaAPIKey, o.walletFeed) return o.opensea.FetchAllCollectionsByOwner(chainID, owner)
if err != nil {
return nil, err
}
return client.FetchAllCollectionsByOwner(owner)
} }
func (o *Manager) FetchAllAssetsByOwnerAndCollection(chainID uint64, owner common.Address, collectionSlug string, cursor string, limit int) (*opensea.AssetContainer, error) { func (o *Manager) FetchAllAssetsByOwnerAndCollection(chainID uint64, owner common.Address, collectionSlug string, cursor string, limit int) (*opensea.AssetContainer, error) {
client, err := opensea.NewOpenseaClient(chainID, o.openseaAPIKey, o.walletFeed) assetContainer, err := o.opensea.FetchAllAssetsByOwnerAndCollection(chainID, owner, collectionSlug, cursor, limit)
if err != nil {
return nil, err
}
assetContainer, err := client.FetchAllAssetsByOwnerAndCollection(owner, collectionSlug, cursor, limit)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -166,12 +155,7 @@ func (o *Manager) FetchBalancesByOwnerAndContractAddress(chainID uint64, ownerAd
} }
func (o *Manager) FetchAllAssetsByOwnerAndContractAddress(chainID uint64, owner common.Address, contractAddresses []common.Address, cursor string, limit int) (*opensea.AssetContainer, error) { func (o *Manager) FetchAllAssetsByOwnerAndContractAddress(chainID uint64, owner common.Address, contractAddresses []common.Address, cursor string, limit int) (*opensea.AssetContainer, error) {
client, err := opensea.NewOpenseaClient(chainID, o.openseaAPIKey, o.walletFeed) assetContainer, err := o.opensea.FetchAllAssetsByOwnerAndContractAddress(chainID, owner, contractAddresses, cursor, limit)
if err != nil {
return nil, err
}
assetContainer, err := client.FetchAllAssetsByOwnerAndContractAddress(owner, contractAddresses, cursor, limit)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -185,12 +169,7 @@ func (o *Manager) FetchAllAssetsByOwnerAndContractAddress(chainID uint64, owner
} }
func (o *Manager) FetchAllAssetsByOwner(chainID uint64, owner common.Address, cursor string, limit int) (*opensea.AssetContainer, error) { func (o *Manager) FetchAllAssetsByOwner(chainID uint64, owner common.Address, cursor string, limit int) (*opensea.AssetContainer, error) {
client, err := opensea.NewOpenseaClient(chainID, o.openseaAPIKey, o.walletFeed) assetContainer, err := o.opensea.FetchAllAssetsByOwner(chainID, owner, cursor, limit)
if err != nil {
return nil, err
}
assetContainer, err := client.FetchAllAssetsByOwner(owner, cursor, limit)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -208,12 +187,7 @@ func (o *Manager) FetchAssetsByNFTUniqueID(chainID uint64, uniqueIDs []thirdpart
idsToFetch := o.getIDsNotInCache(chainID, uniqueIDs) idsToFetch := o.getIDsNotInCache(chainID, uniqueIDs)
if len(idsToFetch) > 0 { if len(idsToFetch) > 0 {
client, err := opensea.NewOpenseaClient(chainID, o.openseaAPIKey, o.walletFeed) fetchedAssetContainer, err := o.opensea.FetchAssetsByNFTUniqueID(chainID, idsToFetch, limit)
if err != nil {
return nil, err
}
fetchedAssetContainer, err := client.FetchAssetsByNFTUniqueID(idsToFetch, limit)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -0,0 +1,56 @@
package connection
import (
"sync"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/event"
"github.com/status-im/status-go/services/wallet/walletevent"
)
type Status struct {
eventType walletevent.EventType
feed *event.Feed
isConnected bool
lastCheckedAt int64
isConnectedLock sync.RWMutex
}
func NewStatus(eventType walletevent.EventType, feed *event.Feed) *Status {
return &Status{
eventType: eventType,
feed: feed,
isConnected: true,
lastCheckedAt: time.Now().Unix(),
}
}
func (c *Status) SetIsConnected(value bool) {
c.isConnectedLock.Lock()
defer c.isConnectedLock.Unlock()
c.lastCheckedAt = time.Now().Unix()
if value != c.isConnected {
message := "down"
if value {
message = "up"
}
if c.feed != nil {
c.feed.Send(walletevent.Event{
Type: c.eventType,
Accounts: []common.Address{},
Message: message,
At: time.Now().Unix(),
})
}
}
c.isConnected = value
}
func (c *Status) IsConnected() bool {
c.isConnectedLock.RLock()
defer c.isConnectedLock.RUnlock()
return c.isConnected
}

View File

@ -18,6 +18,7 @@ import (
"github.com/status-im/status-go/services/wallet/bigint" "github.com/status-im/status-go/services/wallet/bigint"
walletCommon "github.com/status-im/status-go/services/wallet/common" walletCommon "github.com/status-im/status-go/services/wallet/common"
"github.com/status-im/status-go/services/wallet/connection"
"github.com/status-im/status-go/services/wallet/thirdparty" "github.com/status-im/status-go/services/wallet/thirdparty"
"github.com/status-im/status-go/services/wallet/walletevent" "github.com/status-im/status-go/services/wallet/walletevent"
) )
@ -50,10 +51,6 @@ func getbaseURL(chainID uint64) (string, error) {
return "", ErrChainIDNotSupported return "", ErrChainIDNotSupported
} }
var OpenseaClientInstances = make(map[uint64]*Client)
var OpenseaClientInstancesLock = sync.RWMutex{}
var OpenseaHTTPClient *HTTPClient = nil
type TraitValue string type TraitValue string
func (st *TraitValue) UnmarshalJSON(b []byte) error { func (st *TraitValue) UnmarshalJSON(b []byte) error {
@ -242,81 +239,37 @@ func (o *HTTPClient) doContentTypeRequest(url string) (string, error) {
} }
type Client struct { type Client struct {
client *HTTPClient client *HTTPClient
url string apiKey string
apiKey string connectionStatus *connection.Status
IsConnected bool
LastCheckedAt int64
IsConnectedLock sync.RWMutex
feed *event.Feed
} }
// new opensea client. // new opensea client.
func NewOpenseaClient(chainID uint64, apiKey string, feed *event.Feed) (*Client, error) { func NewClient(apiKey string, feed *event.Feed) *Client {
OpenseaClientInstancesLock.Lock() return &Client{
defer OpenseaClientInstancesLock.Unlock() client: newHTTPClient(),
apiKey: apiKey,
connectionStatus: connection.NewStatus(EventCollectibleStatusChanged, feed),
}
}
if OpenseaHTTPClient == nil { func (o *Client) FetchAllCollectionsByOwner(chainID uint64, owner common.Address) ([]OwnedCollection, error) {
OpenseaHTTPClient = newHTTPClient() offset := 0
} var collections []OwnedCollection
var tmpAPIKey string = ""
if chainID == ChainIDRequiringAPIKey {
tmpAPIKey = apiKey
}
if client, ok := OpenseaClientInstances[chainID]; ok {
if client.apiKey == tmpAPIKey {
return client, nil
}
}
baseURL, err := getbaseURL(chainID) baseURL, err := getbaseURL(chainID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
openseaClient := &Client{
client: OpenseaHTTPClient,
url: baseURL,
apiKey: tmpAPIKey,
IsConnected: true,
LastCheckedAt: time.Now().Unix(),
feed: feed,
}
OpenseaClientInstances[chainID] = openseaClient
return openseaClient, nil
}
func (o *Client) setIsConnected(value bool) {
o.IsConnectedLock.Lock()
defer o.IsConnectedLock.Unlock()
o.LastCheckedAt = time.Now().Unix()
if value != o.IsConnected {
message := "down"
if value {
message = "up"
}
if o.feed != nil {
o.feed.Send(walletevent.Event{
Type: EventCollectibleStatusChanged,
Accounts: []common.Address{},
Message: message,
At: time.Now().Unix(),
})
}
}
o.IsConnected = value
}
func (o *Client) FetchAllCollectionsByOwner(owner common.Address) ([]OwnedCollection, error) {
offset := 0
var collections []OwnedCollection
for { for {
url := fmt.Sprintf("%s/collections?asset_owner=%s&offset=%d&limit=%d", o.url, owner, offset, CollectionLimit) url := fmt.Sprintf("%s/collections?asset_owner=%s&offset=%d&limit=%d", baseURL, owner, offset, CollectionLimit)
body, err := o.client.doGetRequest(url, o.apiKey) body, err := o.client.doGetRequest(url, o.apiKey)
if err != nil { if err != nil {
o.setIsConnected(false) o.connectionStatus.SetIsConnected(false)
return nil, err return nil, err
} }
o.connectionStatus.SetIsConnected(true)
// if Json is not returned there must be an error // if Json is not returned there must be an error
if !json.Valid(body) { if !json.Valid(body) {
@ -326,7 +279,6 @@ func (o *Client) FetchAllCollectionsByOwner(owner common.Address) ([]OwnedCollec
var tmp []OwnedCollection var tmp []OwnedCollection
err = json.Unmarshal(body, &tmp) err = json.Unmarshal(body, &tmp)
if err != nil { if err != nil {
o.setIsConnected(false)
return nil, err return nil, err
} }
@ -336,11 +288,10 @@ func (o *Client) FetchAllCollectionsByOwner(owner common.Address) ([]OwnedCollec
break break
} }
} }
o.setIsConnected(true)
return collections, nil return collections, nil
} }
func (o *Client) FetchAllAssetsByOwnerAndCollection(owner common.Address, collectionSlug string, cursor string, limit int) (*AssetContainer, error) { func (o *Client) FetchAllAssetsByOwnerAndCollection(chainID uint64, owner common.Address, collectionSlug string, cursor string, limit int) (*AssetContainer, error) {
queryParams := url.Values{ queryParams := url.Values{
"owner": {owner.String()}, "owner": {owner.String()},
"collection": {collectionSlug}, "collection": {collectionSlug},
@ -350,10 +301,10 @@ func (o *Client) FetchAllAssetsByOwnerAndCollection(owner common.Address, collec
queryParams["cursor"] = []string{cursor} queryParams["cursor"] = []string{cursor}
} }
return o.fetchAssets(queryParams, limit) return o.fetchAssets(chainID, queryParams, limit)
} }
func (o *Client) FetchAllAssetsByOwnerAndContractAddress(owner common.Address, contractAddresses []common.Address, cursor string, limit int) (*AssetContainer, error) { func (o *Client) FetchAllAssetsByOwnerAndContractAddress(chainID uint64, owner common.Address, contractAddresses []common.Address, cursor string, limit int) (*AssetContainer, error) {
queryParams := url.Values{ queryParams := url.Values{
"owner": {owner.String()}, "owner": {owner.String()},
} }
@ -366,10 +317,10 @@ func (o *Client) FetchAllAssetsByOwnerAndContractAddress(owner common.Address, c
queryParams["cursor"] = []string{cursor} queryParams["cursor"] = []string{cursor}
} }
return o.fetchAssets(queryParams, limit) return o.fetchAssets(chainID, queryParams, limit)
} }
func (o *Client) FetchAllAssetsByOwner(owner common.Address, cursor string, limit int) (*AssetContainer, error) { func (o *Client) FetchAllAssetsByOwner(chainID uint64, owner common.Address, cursor string, limit int) (*AssetContainer, error) {
queryParams := url.Values{ queryParams := url.Values{
"owner": {owner.String()}, "owner": {owner.String()},
} }
@ -378,10 +329,10 @@ func (o *Client) FetchAllAssetsByOwner(owner common.Address, cursor string, limi
queryParams["cursor"] = []string{cursor} queryParams["cursor"] = []string{cursor}
} }
return o.fetchAssets(queryParams, limit) return o.fetchAssets(chainID, queryParams, limit)
} }
func (o *Client) FetchAssetsByNFTUniqueID(uniqueIDs []thirdparty.CollectibleUniqueID, limit int) (*AssetContainer, error) { func (o *Client) FetchAssetsByNFTUniqueID(chainID uint64, uniqueIDs []thirdparty.CollectibleUniqueID, limit int) (*AssetContainer, error) {
queryParams := url.Values{} queryParams := url.Values{}
for _, uniqueID := range uniqueIDs { for _, uniqueID := range uniqueIDs {
@ -389,10 +340,10 @@ func (o *Client) FetchAssetsByNFTUniqueID(uniqueIDs []thirdparty.CollectibleUniq
queryParams.Add("asset_contract_addresses", uniqueID.ContractAddress.String()) queryParams.Add("asset_contract_addresses", uniqueID.ContractAddress.String())
} }
return o.fetchAssets(queryParams, limit) return o.fetchAssets(chainID, queryParams, limit)
} }
func (o *Client) fetchAssets(queryParams url.Values, limit int) (*AssetContainer, error) { func (o *Client) fetchAssets(chainID uint64, queryParams url.Values, limit int) (*AssetContainer, error) {
assets := new(AssetContainer) assets := new(AssetContainer)
if len(queryParams["cursor"]) > 0 { if len(queryParams["cursor"]) > 0 {
@ -404,15 +355,22 @@ func (o *Client) fetchAssets(queryParams url.Values, limit int) (*AssetContainer
tmpLimit = limit tmpLimit = limit
} }
baseURL, err := getbaseURL(chainID)
if err != nil {
return nil, err
}
queryParams["limit"] = []string{strconv.Itoa(tmpLimit)} queryParams["limit"] = []string{strconv.Itoa(tmpLimit)}
for { for {
url := o.url + "/assets?" + queryParams.Encode() url := baseURL + "/assets?" + queryParams.Encode()
body, err := o.client.doGetRequest(url, o.apiKey) body, err := o.client.doGetRequest(url, o.apiKey)
if err != nil { if err != nil {
o.setIsConnected(false) o.connectionStatus.SetIsConnected(false)
return nil, err return nil, err
} }
o.connectionStatus.SetIsConnected(true)
// if Json is not returned there must be an error // if Json is not returned there must be an error
if !json.Valid(body) { if !json.Valid(body) {
@ -422,7 +380,6 @@ func (o *Client) fetchAssets(queryParams url.Values, limit int) (*AssetContainer
container := AssetContainer{} container := AssetContainer{}
err = json.Unmarshal(body, &container) err = json.Unmarshal(body, &container)
if err != nil { if err != nil {
o.setIsConnected(false)
return nil, err return nil, err
} }
@ -452,6 +409,5 @@ func (o *Client) fetchAssets(queryParams url.Values, limit int) (*AssetContainer
} }
} }
o.setIsConnected(true)
return assets, nil return assets, nil
} }