feat(Wallet): add API to fetch collectibles in a paginated way

This commit is contained in:
Dario Gabriel Lipicar 2023-03-06 13:15:48 -03:00 committed by dlipicar
parent 7b6fc87f89
commit bac7eb08ca
3 changed files with 74 additions and 31 deletions

View File

@ -303,17 +303,36 @@ func (api *API) GetOpenseaCollectionsByOwner(ctx context.Context, chainID uint64
return client.FetchAllCollectionsByOwner(owner)
}
// Kept for compatibility with mobile app
func (api *API) GetOpenseaAssetsByOwnerAndCollection(ctx context.Context, chainID uint64, owner common.Address, collectionSlug string, limit int) ([]opensea.Asset, error) {
container, err := api.GetOpenseaAssetsByOwnerAndCollectionWithCursor(ctx, chainID, owner, collectionSlug, "", limit)
if err != nil {
return nil, err
}
return container.Assets, nil
}
func (api *API) GetOpenseaAssetsByOwnerAndCollectionWithCursor(ctx context.Context, chainID uint64, owner common.Address, collectionSlug string, cursor string, limit int) (*opensea.AssetContainer, error) {
log.Debug("call to get opensea assets")
client, err := opensea.NewOpenseaClient(chainID, api.s.openseaAPIKey)
if err != nil {
return nil, err
}
return client.FetchAllAssetsByOwnerAndCollection(owner, collectionSlug, limit)
return client.FetchAllAssetsByOwnerAndCollection(owner, collectionSlug, cursor, limit)
}
func (api *API) GetOpenseaAssetsByNFTUniqueID(ctx context.Context, chainID uint64, uniqueIDs []opensea.NFTUniqueID, limit int) ([]opensea.Asset, error) {
func (api *API) GetOpenseaAssetsByOwnerWithCursor(ctx context.Context, chainID uint64, owner common.Address, cursor string, limit int) (*opensea.AssetContainer, error) {
log.Debug("call to FetchAllAssetsByOwner")
client, err := opensea.NewOpenseaClient(chainID, api.s.openseaAPIKey)
if err != nil {
return nil, err
}
return client.FetchAllAssetsByOwner(owner, cursor, limit)
}
func (api *API) GetOpenseaAssetsByNFTUniqueID(ctx context.Context, chainID uint64, uniqueIDs []opensea.NFTUniqueID, limit int) (*opensea.AssetContainer, error) {
log.Debug("call to GetOpenseaAssetsByNFTUniqueID")
client, err := opensea.NewOpenseaClient(chainID, api.s.openseaAPIKey)

View File

@ -18,7 +18,7 @@ import (
"github.com/status-im/status-go/services/wallet/bigint"
)
const AssetLimit = 50
const AssetLimit = 200
const CollectionLimit = 300
const RequestRetryMaxCount = 1
@ -203,16 +203,32 @@ func (o *Client) FetchAllCollectionsByOwner(owner common.Address) ([]OwnedCollec
return collections, nil
}
func (o *Client) FetchAllAssetsByOwnerAndCollection(owner common.Address, collectionSlug string, limit int) ([]Asset, error) {
func (o *Client) FetchAllAssetsByOwnerAndCollection(owner common.Address, collectionSlug string, cursor string, limit int) (*AssetContainer, error) {
queryParams := url.Values{
"owner": {owner.String()},
"collection": {collectionSlug},
}
if len(cursor) > 0 {
queryParams["cursor"] = []string{cursor}
}
return o.fetchAssets(queryParams, limit)
}
func (o *Client) FetchAssetsByNFTUniqueID(uniqueIDs []NFTUniqueID, limit int) ([]Asset, error) {
func (o *Client) FetchAllAssetsByOwner(owner common.Address, cursor string, limit int) (*AssetContainer, error) {
queryParams := url.Values{
"owner": {owner.String()},
}
if len(cursor) > 0 {
queryParams["cursor"] = []string{cursor}
}
return o.fetchAssets(queryParams, limit)
}
func (o *Client) FetchAssetsByNFTUniqueID(uniqueIDs []NFTUniqueID, limit int) (*AssetContainer, error) {
queryParams := url.Values{}
for _, uniqueID := range uniqueIDs {
@ -223,10 +239,19 @@ func (o *Client) FetchAssetsByNFTUniqueID(uniqueIDs []NFTUniqueID, limit int) ([
return o.fetchAssets(queryParams, limit)
}
func (o *Client) fetchAssets(queryParams url.Values, limit int) ([]Asset, error) {
var assets []Asset
func (o *Client) fetchAssets(queryParams url.Values, limit int) (*AssetContainer, error) {
assets := new(AssetContainer)
queryParams["limit"] = []string{strconv.Itoa(AssetLimit)}
if len(queryParams["cursor"]) > 0 {
assets.PreviousCursor = queryParams["cursor"][0]
}
tmpLimit := limit
if AssetLimit < limit {
tmpLimit = AssetLimit
}
queryParams["limit"] = []string{strconv.Itoa(tmpLimit)}
for {
url := o.url + "/assets?" + queryParams.Encode()
@ -248,22 +273,17 @@ func (o *Client) fetchAssets(queryParams url.Values, limit int) ([]Asset, error)
asset.Traits[i].TraitType = strings.Replace(asset.Traits[i].TraitType, "_", " ", 1)
asset.Traits[i].Value = TraitValue(strings.Title(string(asset.Traits[i].Value)))
}
assets = append(assets, asset)
assets.Assets = append(assets.Assets, asset)
}
assets.NextCursor = container.NextCursor
if len(container.Assets) < AssetLimit {
if len(assets.NextCursor) == 0 {
break
}
nextCursor := container.NextCursor
queryParams["cursor"] = []string{assets.NextCursor}
if len(nextCursor) == 0 {
break
}
queryParams["cursor"] = []string{nextCursor}
if len(assets) >= limit {
if len(assets.Assets) >= limit {
break
}
}

View File

@ -43,17 +43,21 @@ func TestFetchAllCollectionsByOwner(t *testing.T) {
}
func TestFetchAllAssetsByOwnerAndCollection(t *testing.T) {
expected := []Asset{{
ID: 1,
Name: "Rocky",
Description: "Rocky Balboa",
Permalink: "permalink",
ImageThumbnailURL: "ImageThumbnailURL",
ImageURL: "ImageUrl",
Contract: Contract{Address: "1"},
Collection: Collection{Name: "Rocky"},
}}
response, _ := json.Marshal(AssetContainer{Assets: expected})
expected := AssetContainer{
Assets: []Asset{{
ID: 1,
Name: "Rocky",
Description: "Rocky Balboa",
Permalink: "permalink",
ImageThumbnailURL: "ImageThumbnailURL",
ImageURL: "ImageUrl",
Contract: Contract{Address: "1"},
Collection: Collection{Name: "Rocky"},
}},
NextCursor: "",
PreviousCursor: "",
}
response, _ := json.Marshal(expected)
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
_, err := w.Write(response)
@ -67,7 +71,7 @@ func TestFetchAllAssetsByOwnerAndCollection(t *testing.T) {
client: srv.Client(),
url: srv.URL,
}
res, err := opensea.FetchAllAssetsByOwnerAndCollection(common.Address{1}, "rocky", 200)
assert.Equal(t, expected, res)
res, err := opensea.FetchAllAssetsByOwnerAndCollection(common.Address{1}, "rocky", "", 200)
assert.Nil(t, err)
assert.Equal(t, expected, *res)
}