diff --git a/services/wallet/api.go b/services/wallet/api.go index 4e3e8c7d2..a3dc136f9 100644 --- a/services/wallet/api.go +++ b/services/wallet/api.go @@ -23,7 +23,6 @@ import ( "github.com/status-im/status-go/services/wallet/currency" "github.com/status-im/status-go/services/wallet/history" "github.com/status-im/status-go/services/wallet/thirdparty" - "github.com/status-im/status-go/services/wallet/thirdparty/opensea" "github.com/status-im/status-go/services/wallet/token" "github.com/status-im/status-go/services/wallet/transfer" "github.com/status-im/status-go/services/wallet/walletevent" @@ -361,34 +360,6 @@ func (api *API) GetCollectiblesDetailsAsync(requestID int32, uniqueIDs []thirdpa return nil } -// @deprecated -// Old Collectibles API - To be deprecated -func (api *API) GetOpenseaCollectionsByOwner(ctx context.Context, chainID wcommon.ChainID, owner common.Address) ([]opensea.OwnedCollection, error) { - log.Debug("call to GetOpenseaCollectionsByOwner") - return api.s.collectiblesManager.FetchAllCollectionsByOwner(chainID, owner) -} - -// @deprecated -func (api *API) GetOpenseaAssetsByOwnerAndCollectionWithCursor(ctx context.Context, chainID wcommon.ChainID, owner common.Address, collectionSlug string, cursor string, limit int) (*opensea.AssetContainer, error) { - log.Debug("call to GetOpenseaAssetsByOwnerAndCollectionWithCursor") - return api.s.collectiblesManager.FetchAllOpenseaAssetsByOwnerAndCollection(chainID, owner, collectionSlug, cursor, limit) -} - -// @deprecated -func (api *API) GetOpenseaAssetsByOwnerAndCollection(ctx context.Context, chainID wcommon.ChainID, 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 -} - -// @deprecated -func (api *API) GetCollectiblesByOwnerAndCollectionWithCursor(ctx context.Context, chainID wcommon.ChainID, owner common.Address, collectionSlug string, cursor string, limit int) (*thirdparty.FullCollectibleDataContainer, error) { - log.Debug("call to GetCollectiblesByOwnerAndCollectionWithCursor") - return api.s.collectiblesManager.FetchAllAssetsByOwnerAndCollection(chainID, owner, collectionSlug, cursor, limit) -} - // @deprecated func (api *API) GetCollectiblesByOwnerWithCursor(ctx context.Context, chainID wcommon.ChainID, owner common.Address, cursor string, limit int) (*thirdparty.FullCollectibleDataContainer, error) { log.Debug("call to GetCollectiblesByOwnerWithCursor") diff --git a/services/wallet/collectibles/manager.go b/services/wallet/collectibles/manager.go index f01fd8449..6e30ca492 100644 --- a/services/wallet/collectibles/manager.go +++ b/services/wallet/collectibles/manager.go @@ -22,7 +22,6 @@ import ( 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/opensea" "github.com/status-im/status-go/services/wallet/walletevent" ) @@ -58,7 +57,6 @@ type Manager struct { metadataProvider thirdparty.CollectibleMetadataProvider communityInfoProvider thirdparty.CollectibleCommunityInfoProvider - opensea *opensea.Client httpClient *http.Client collectiblesDataDB *CollectibleDataDB @@ -75,7 +73,6 @@ func NewManager( accountOwnershipProviders []thirdparty.CollectibleAccountOwnershipProvider, collectibleDataProviders []thirdparty.CollectibleDataProvider, collectionDataProviders []thirdparty.CollectionDataProvider, - opensea *opensea.Client, feed *event.Feed) *Manager { hystrix.ConfigureCommand(hystrixContractOwnershipClientName, hystrix.CommandConfig{ Timeout: 10000, @@ -132,7 +129,6 @@ func NewManager( collectibleDataProviders: collectibleDataProviders, collectionDataProviders: collectionDataProviders, collectibleProviders: collectibleProviders, - opensea: opensea, httpClient: &http.Client{ Timeout: requestTimeout, }, @@ -208,28 +204,6 @@ func (o *Manager) SetCommunityInfoProvider(communityInfoProvider thirdparty.Coll o.communityInfoProvider = communityInfoProvider } -func (o *Manager) FetchAllCollectionsByOwner(chainID walletCommon.ChainID, owner common.Address) ([]opensea.OwnedCollection, error) { - return o.opensea.FetchAllCollectionsByOwner(chainID, owner) -} - -func (o *Manager) FetchAllOpenseaAssetsByOwnerAndCollection(chainID walletCommon.ChainID, owner common.Address, collectionSlug string, cursor string, limit int) (*opensea.AssetContainer, error) { - return o.opensea.FetchAllOpenseaAssetsByOwnerAndCollection(chainID, owner, collectionSlug, cursor, limit) -} - -func (o *Manager) FetchAllAssetsByOwnerAndCollection(chainID walletCommon.ChainID, owner common.Address, collectionSlug string, cursor string, limit int) (*thirdparty.FullCollectibleDataContainer, error) { - assetContainer, err := o.opensea.FetchAllAssetsByOwnerAndCollection(chainID, owner, collectionSlug, cursor, limit) - if err != nil { - return nil, err - } - - err = o.processFullCollectibleData(assetContainer.Items) - if err != nil { - return nil, err - } - - return assetContainer, nil -} - // Need to combine different providers to support all needed ChainIDs func (o *Manager) FetchBalancesByOwnerAndContractAddress(chainID walletCommon.ChainID, ownerAddress common.Address, contractAddresses []common.Address) (thirdparty.TokenBalancesPerContractAddress, error) { ret := make(thirdparty.TokenBalancesPerContractAddress) diff --git a/services/wallet/service.go b/services/wallet/service.go index 62874d792..6e4be61e5 100644 --- a/services/wallet/service.go +++ b/services/wallet/service.go @@ -107,7 +107,6 @@ func NewService( blockChainState := NewBlockChainState(rpcClient, accountsDB) openseaHTTPClient := opensea.NewHTTPClient() - openseaClient := opensea.NewClient(config.WalletConfig.OpenseaAPIKey, openseaHTTPClient) openseaV2Client := opensea.NewClientV2(config.WalletConfig.OpenseaAPIKey, openseaHTTPClient) alchemyClient := alchemy.NewClient(config.WalletConfig.AlchemyAPIKeys) @@ -117,23 +116,20 @@ func NewService( } accountOwnershipProviders := []thirdparty.CollectibleAccountOwnershipProvider{ - openseaClient, openseaV2Client, alchemyClient, } collectibleDataProviders := []thirdparty.CollectibleDataProvider{ - openseaClient, openseaV2Client, alchemyClient, } collectionDataProviders := []thirdparty.CollectionDataProvider{ - openseaClient, alchemyClient, } - collectiblesManager := collectibles.NewManager(db, rpcClient, contractOwnershipProviders, accountOwnershipProviders, collectibleDataProviders, collectionDataProviders, openseaClient, feed) + collectiblesManager := collectibles.NewManager(db, rpcClient, contractOwnershipProviders, accountOwnershipProviders, collectibleDataProviders, collectionDataProviders, feed) collectibles := collectibles.NewService(db, feed, accountsDB, accountFeed, rpcClient.NetworkManager, collectiblesManager) activity := activity.NewService(db, tokenManager, collectiblesManager, feed) diff --git a/services/wallet/thirdparty/opensea/client.go b/services/wallet/thirdparty/opensea/client.go deleted file mode 100644 index 77b25f2db..000000000 --- a/services/wallet/thirdparty/opensea/client.go +++ /dev/null @@ -1,347 +0,0 @@ -package opensea - -import ( - "encoding/json" - "fmt" - "net/url" - "strconv" - "strings" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/log" - - 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" -) - -const AssetLimit = 200 -const CollectionLimit = 300 - -const ChainIDRequiringAPIKey = walletCommon.EthereumMainnet - -func getBaseURL(chainID walletCommon.ChainID) (string, error) { - // v1 Endpoints only support L1 chain - switch uint64(chainID) { - case walletCommon.EthereumMainnet: - return "https://api.opensea.io/api/v1", nil - case walletCommon.EthereumSepolia: - return "https://testnets-api.opensea.io/api/v1", nil - } - - return "", thirdparty.ErrChainIDNotSupported -} - -func (o *Client) ID() string { - return OpenseaV1ID -} - -func (o *Client) IsChainSupported(chainID walletCommon.ChainID) bool { - _, err := getBaseURL(chainID) - return err == nil -} - -func (o *Client) IsConnected() bool { - return o.connectionStatus.IsConnected() -} - -func getURL(chainID walletCommon.ChainID, path string) (string, error) { - baseURL, err := getBaseURL(chainID) - if err != nil { - return "", err - } - - return fmt.Sprintf("%s/%s", baseURL, path), nil -} - -type Client struct { - client *HTTPClient - apiKey string - connectionStatus *connection.Status - urlGetter urlGetter -} - -// new opensea v1 client. -func NewClient(apiKey string, httpClient *HTTPClient) *Client { - if apiKey == "" { - log.Warn("OpenseaV1 API key not available") - } - - return &Client{ - client: httpClient, - apiKey: apiKey, - connectionStatus: connection.NewStatus(), - urlGetter: getURL, - } -} - -func (o *Client) FetchAllCollectionsByOwner(chainID walletCommon.ChainID, owner common.Address) ([]OwnedCollection, error) { - offset := 0 - var collections []OwnedCollection - - for { - path := fmt.Sprintf("collections?asset_owner=%s&offset=%d&limit=%d", owner, offset, CollectionLimit) - url, err := o.urlGetter(chainID, path) - if err != nil { - return nil, err - } - - body, err := o.client.doGetRequest(url, o.apiKey) - if err != nil { - o.connectionStatus.SetIsConnected(false) - return nil, err - } - o.connectionStatus.SetIsConnected(true) - - // if Json is not returned there must be an error - if !json.Valid(body) { - return nil, fmt.Errorf("invalid json: %s", string(body)) - } - - var tmp []OwnedCollection - err = json.Unmarshal(body, &tmp) - if err != nil { - return nil, err - } - - collections = append(collections, tmp...) - - if len(tmp) < CollectionLimit { - break - } - } - return collections, nil -} - -func (o *Client) FetchCollectionsDataByContractID(ids []thirdparty.ContractID) ([]thirdparty.CollectionData, error) { - ret := make([]thirdparty.CollectionData, 0, len(ids)) - - for _, id := range ids { - path := fmt.Sprintf("asset_contract/%s", id.Address.String()) - url, err := o.urlGetter(id.ChainID, path) - if err != nil { - return nil, err - } - - body, err := o.client.doGetRequest(url, o.apiKey) - if err != nil { - o.connectionStatus.SetIsConnected(false) - return nil, err - } - o.connectionStatus.SetIsConnected(true) - - // if Json is not returned there must be an error - if !json.Valid(body) { - return nil, fmt.Errorf("invalid json: %s", string(body)) - } - - var tmp AssetContract - err = json.Unmarshal(body, &tmp) - if err != nil { - return nil, err - } - - ret = append(ret, tmp.Collection.toCollectionData(id)) - } - - return ret, nil -} - -func (o *Client) FetchAllAssetsByOwnerAndCollection(chainID walletCommon.ChainID, owner common.Address, collectionSlug string, cursor string, limit int) (*thirdparty.FullCollectibleDataContainer, error) { - queryParams := url.Values{ - "owner": {owner.String()}, - "collection": {collectionSlug}, - } - - if len(cursor) > 0 { - queryParams["cursor"] = []string{cursor} - } - - return o.fetchAssets(chainID, queryParams, limit) -} - -func (o *Client) FetchAllAssetsByOwnerAndContractAddress(chainID walletCommon.ChainID, owner common.Address, contractAddresses []common.Address, cursor string, limit int) (*thirdparty.FullCollectibleDataContainer, error) { - queryParams := url.Values{ - "owner": {owner.String()}, - } - - for _, contractAddress := range contractAddresses { - queryParams.Add("asset_contract_addresses", contractAddress.String()) - } - - if len(cursor) > 0 { - queryParams["cursor"] = []string{cursor} - } - - return o.fetchAssets(chainID, queryParams, limit) -} - -func (o *Client) FetchAllAssetsByOwner(chainID walletCommon.ChainID, owner common.Address, cursor string, limit int) (*thirdparty.FullCollectibleDataContainer, error) { - queryParams := url.Values{ - "owner": {owner.String()}, - } - - if len(cursor) > 0 { - queryParams["cursor"] = []string{cursor} - } - - return o.fetchAssets(chainID, queryParams, limit) -} - -func (o *Client) FetchAssetsByCollectibleUniqueID(uniqueIDs []thirdparty.CollectibleUniqueID) ([]thirdparty.FullCollectibleData, error) { - queryParams := url.Values{} - - ret := make([]thirdparty.FullCollectibleData, 0, len(uniqueIDs)) - - idsPerChainID := thirdparty.GroupCollectibleUIDsByChainID(uniqueIDs) - for chainID, ids := range idsPerChainID { - for _, id := range ids { - queryParams.Add("token_ids", id.TokenID.String()) - queryParams.Add("asset_contract_addresses", id.ContractID.Address.String()) - } - - data, err := o.fetchAssets(chainID, queryParams, thirdparty.FetchNoLimit) - if err != nil { - return nil, err - } - - ret = append(ret, data.Items...) - } - - return ret, nil -} - -func (o *Client) fetchAssets(chainID walletCommon.ChainID, queryParams url.Values, limit int) (*thirdparty.FullCollectibleDataContainer, error) { - assets := new(thirdparty.FullCollectibleDataContainer) - - if len(queryParams["cursor"]) > 0 { - assets.PreviousCursor = queryParams["cursor"][0] - } - assets.Provider = o.ID() - - tmpLimit := AssetLimit - if limit > thirdparty.FetchNoLimit && limit < tmpLimit { - tmpLimit = limit - } - - queryParams["limit"] = []string{strconv.Itoa(tmpLimit)} - for { - path := "assets?" + queryParams.Encode() - url, err := o.urlGetter(chainID, path) - if err != nil { - return nil, err - } - - body, err := o.client.doGetRequest(url, o.apiKey) - if err != nil { - o.connectionStatus.SetIsConnected(false) - return nil, err - } - o.connectionStatus.SetIsConnected(true) - - // if Json is not returned there must be an error - if !json.Valid(body) { - return nil, fmt.Errorf("invalid json: %s", string(body)) - } - - container := AssetContainer{} - err = json.Unmarshal(body, &container) - if err != nil { - return nil, err - } - - for _, asset := range container.Assets { - assets.Items = append(assets.Items, asset.toCommon()) - } - assets.NextCursor = container.NextCursor - - if len(assets.NextCursor) == 0 { - break - } - - queryParams["cursor"] = []string{assets.NextCursor} - - if limit > thirdparty.FetchNoLimit && len(assets.Items) >= limit { - break - } - } - - return assets, nil -} - -// Only here for compatibility with mobile app, to be removed -func (o *Client) FetchAllOpenseaAssetsByOwnerAndCollection(chainID walletCommon.ChainID, 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.fetchOpenseaAssets(chainID, queryParams, limit) -} - -func (o *Client) fetchOpenseaAssets(chainID walletCommon.ChainID, queryParams url.Values, limit int) (*AssetContainer, error) { - assets := new(AssetContainer) - - if len(queryParams["cursor"]) > 0 { - assets.PreviousCursor = queryParams["cursor"][0] - } - - tmpLimit := AssetLimit - if limit > 0 && limit < tmpLimit { - tmpLimit = limit - } - - baseURL, err := getBaseURL(chainID) - - if err != nil { - return nil, err - } - - queryParams["limit"] = []string{strconv.Itoa(tmpLimit)} - for { - url := baseURL + "/assets?" + queryParams.Encode() - - body, err := o.client.doGetRequest(url, o.apiKey) - if err != nil { - o.connectionStatus.SetIsConnected(false) - return nil, err - } - o.connectionStatus.SetIsConnected(true) - - // if Json is not returned there must be an error - if !json.Valid(body) { - return nil, fmt.Errorf("invalid json: %s", string(body)) - } - - container := AssetContainer{} - err = json.Unmarshal(body, &container) - if err != nil { - return nil, err - } - - for _, asset := range container.Assets { - for i := range asset.Traits { - asset.Traits[i].TraitType = strings.Replace(asset.Traits[i].TraitType, "_", " ", 1) - asset.Traits[i].Value = TraitValue(strings.Title(string(asset.Traits[i].Value))) - } - assets.Assets = append(assets.Assets, asset) - } - assets.NextCursor = container.NextCursor - - if len(assets.NextCursor) == 0 { - break - } - - queryParams["cursor"] = []string{assets.NextCursor} - - if limit > 0 && len(assets.Assets) >= limit { - break - } - } - - return assets, nil -} diff --git a/services/wallet/thirdparty/opensea/client_test.go b/services/wallet/thirdparty/opensea/client_test.go deleted file mode 100644 index f50f0b74a..000000000 --- a/services/wallet/thirdparty/opensea/client_test.go +++ /dev/null @@ -1,171 +0,0 @@ -package opensea - -import ( - "encoding/json" - "fmt" - "math/big" - "net/http" - "net/http/httptest" - "testing" - - "github.com/status-im/status-go/services/wallet/bigint" - 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/stretchr/testify/assert" - - "github.com/ethereum/go-ethereum/common" -) - -const ( - ExpiredKeyError = "Expired API key" - ExpectedExpiredKeyError = "invalid json: Expired API key" -) - -func initTestClient(srv *httptest.Server) *Client { - urlGetter := func(chainID walletCommon.ChainID, path string) (string, error) { - return srv.URL, nil - } - - status := connection.NewStatus() - - client := &HTTPClient{ - client: srv.Client(), - } - opensea := &Client{ - client: client, - connectionStatus: status, - urlGetter: urlGetter, - } - - return opensea -} - -func TestFetchAllCollectionsByOwner(t *testing.T) { - expectedOS := []OwnedCollection{{ - Collection: Collection{ - Name: "Rocky", - Slug: "rocky", - ImageURL: "ImageUrl", - }, - OwnedAssetCount: &bigint.BigInt{Int: big.NewInt(1)}, - }} - response, _ := json.Marshal(expectedOS) - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(200) - _, err := w.Write(response) - if err != nil { - return - } - })) - defer srv.Close() - - opensea := initTestClient(srv) - res, err := opensea.FetchAllCollectionsByOwner(walletCommon.ChainID(1), common.Address{1}) - assert.Equal(t, expectedOS, res) - assert.Nil(t, err) -} - -func TestFetchAllCollectionsByOwnerWithInValidJson(t *testing.T) { - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(200) - _, err := w.Write([]byte(ExpiredKeyError)) - if err != nil { - return - } - })) - defer srv.Close() - - opensea := initTestClient(srv) - res, err := opensea.FetchAllCollectionsByOwner(walletCommon.ChainID(1), common.Address{1}) - assert.Nil(t, res) - assert.Equal(t, err, fmt.Errorf(ExpectedExpiredKeyError)) -} - -func TestFetchAllAssetsByOwnerAndCollection(t *testing.T) { - expectedOS := AssetContainer{ - Assets: []Asset{{ - ID: 1, - TokenID: &bigint.BigInt{Int: big.NewInt(1)}, - Name: "Rocky", - Description: "Rocky Balboa", - Permalink: "permalink", - ImageThumbnailURL: "ImageThumbnailURL", - ImageURL: "ImageUrl", - Contract: Contract{ - Address: "1", - ChainIdentifier: "ethereum", - }, - Collection: Collection{ - Name: "Rocky", - Traits: map[string]CollectionTrait{}, - }, - Traits: []Trait{}, - }}, - NextCursor: "", - PreviousCursor: "", - } - expectedCommon := thirdparty.FullCollectibleDataContainer{ - Items: []thirdparty.FullCollectibleData{ - thirdparty.FullCollectibleData{ - CollectibleData: thirdparty.CollectibleData{ - ID: thirdparty.CollectibleUniqueID{ - ContractID: thirdparty.ContractID{ - ChainID: 1, - Address: common.HexToAddress("0x1"), - }, - TokenID: &bigint.BigInt{Int: big.NewInt(1)}, - }, - Provider: "openseaV1", - Name: "Rocky", - Description: "Rocky Balboa", - Permalink: "permalink", - ImageURL: "ImageUrl", - Traits: []thirdparty.CollectibleTrait{}, - }, - CollectionData: &thirdparty.CollectionData{ - ID: thirdparty.ContractID{ - ChainID: 1, - Address: common.HexToAddress("0x1"), - }, - Provider: "openseaV1", - Name: "Rocky", - Traits: map[string]thirdparty.CollectionTrait{}, - }, - }, - }, - NextCursor: "", - PreviousCursor: "", - } - response, _ := json.Marshal(expectedOS) - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(200) - _, err := w.Write(response) - if err != nil { - return - } - })) - defer srv.Close() - - opensea := initTestClient(srv) - res, err := opensea.FetchAllAssetsByOwnerAndCollection(walletCommon.ChainID(1), common.Address{1}, "rocky", "", 200) - assert.Nil(t, err) - assert.Equal(t, expectedCommon, *res) -} - -func TestFetchAllAssetsByOwnerAndCollectionInvalidJson(t *testing.T) { - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(200) - _, err := w.Write([]byte(ExpiredKeyError)) - if err != nil { - return - } - })) - defer srv.Close() - - opensea := initTestClient(srv) - res, err := opensea.FetchAllAssetsByOwnerAndCollection(walletCommon.ChainID(1), common.Address{1}, "rocky", "", 200) - assert.Nil(t, res) - assert.Equal(t, fmt.Errorf(ExpectedExpiredKeyError), err) -} diff --git a/services/wallet/thirdparty/opensea/client_v2.go b/services/wallet/thirdparty/opensea/client_v2.go index 369675589..a57111902 100644 --- a/services/wallet/thirdparty/opensea/client_v2.go +++ b/services/wallet/thirdparty/opensea/client_v2.go @@ -135,7 +135,7 @@ func (o *ClientV2) FetchAssetsByCollectibleUniqueID(uniqueIDs []thirdparty.Colle func (o *ClientV2) fetchAssets(chainID walletCommon.ChainID, pathParams []string, queryParams url.Values, limit int, cursor string) (*thirdparty.FullCollectibleDataContainer, error) { assets := new(thirdparty.FullCollectibleDataContainer) - tmpLimit := AssetLimit + tmpLimit := assetLimitV2 if limit > thirdparty.FetchNoLimit && limit < tmpLimit { tmpLimit = limit } diff --git a/services/wallet/thirdparty/opensea/types.go b/services/wallet/thirdparty/opensea/types.go deleted file mode 100644 index 6bafdc249..000000000 --- a/services/wallet/thirdparty/opensea/types.go +++ /dev/null @@ -1,183 +0,0 @@ -package opensea - -import ( - "encoding/json" - "strconv" - "strings" - - "github.com/ethereum/go-ethereum/common" - - "github.com/status-im/status-go/services/wallet/bigint" - walletCommon "github.com/status-im/status-go/services/wallet/common" - "github.com/status-im/status-go/services/wallet/thirdparty" - - "golang.org/x/text/cases" - "golang.org/x/text/language" -) - -const OpenseaV1ID = "openseaV1" - -type urlGetter func(walletCommon.ChainID, string) (string, error) - -type TraitValue string - -func (st *TraitValue) UnmarshalJSON(b []byte) error { - var item interface{} - if err := json.Unmarshal(b, &item); err != nil { - return err - } - - switch v := item.(type) { - case float64: - *st = TraitValue(strconv.FormatFloat(v, 'f', 2, 64)) - case int: - *st = TraitValue(strconv.Itoa(v)) - case string: - *st = TraitValue(v) - - } - return nil -} - -type AssetContainer struct { - Assets []Asset `json:"assets"` - NextCursor string `json:"next"` - PreviousCursor string `json:"previous"` -} - -type Contract struct { - Address string `json:"address"` - ChainIdentifier string `json:"chain_identifier"` -} - -type Trait struct { - TraitType string `json:"trait_type"` - Value TraitValue `json:"value"` - DisplayType string `json:"display_type"` - MaxValue string `json:"max_value"` -} - -type PaymentToken struct { - ID int `json:"id"` - Symbol string `json:"symbol"` - Address string `json:"address"` - ImageURL string `json:"image_url"` - Name string `json:"name"` - Decimals int `json:"decimals"` - EthPrice string `json:"eth_price"` - UsdPrice string `json:"usd_price"` -} - -type LastSale struct { - PaymentToken PaymentToken `json:"payment_token"` -} - -type SellOrder struct { - CurrentPrice string `json:"current_price"` -} - -type Asset struct { - ID int `json:"id"` - TokenID *bigint.BigInt `json:"token_id"` - Name string `json:"name"` - Description string `json:"description"` - Permalink string `json:"permalink"` - ImageThumbnailURL string `json:"image_thumbnail_url"` - ImageURL string `json:"image_url"` - AnimationURL string `json:"animation_url"` - Contract Contract `json:"asset_contract"` - Collection Collection `json:"collection"` - Traits []Trait `json:"traits"` - LastSale LastSale `json:"last_sale"` - SellOrders []SellOrder `json:"sell_orders"` - BackgroundColor string `json:"background_color"` - TokenURI string `json:"token_metadata"` -} - -type CollectionTrait struct { - Min float64 `json:"min"` - Max float64 `json:"max"` -} - -type Collection struct { - Name string `json:"name"` - Slug string `json:"slug"` - ImageURL string `json:"image_url"` - Traits map[string]CollectionTrait `json:"traits"` -} - -type OwnedCollection struct { - Collection - OwnedAssetCount *bigint.BigInt `json:"owned_asset_count"` -} - -type AssetContract struct { - Collection Collection `json:"collection"` -} - -func (c *Asset) id() thirdparty.CollectibleUniqueID { - return thirdparty.CollectibleUniqueID{ - ContractID: thirdparty.ContractID{ - ChainID: chainStringToChainID(c.Contract.ChainIdentifier), - Address: common.HexToAddress(c.Contract.Address), - }, - TokenID: c.TokenID, - } -} - -func openseaToCollectibleTraits(traits []Trait) []thirdparty.CollectibleTrait { - ret := make([]thirdparty.CollectibleTrait, 0, len(traits)) - caser := cases.Title(language.Und, cases.NoLower) - for _, orig := range traits { - dest := thirdparty.CollectibleTrait{ - TraitType: strings.Replace(orig.TraitType, "_", " ", 1), - Value: caser.String(string(orig.Value)), - DisplayType: orig.DisplayType, - MaxValue: orig.MaxValue, - } - - ret = append(ret, dest) - } - return ret -} - -func (c *Collection) toCollectionData(id thirdparty.ContractID) thirdparty.CollectionData { - ret := thirdparty.CollectionData{ - ID: id, - Provider: OpenseaV1ID, - Name: c.Name, - Slug: c.Slug, - ImageURL: c.ImageURL, - Traits: make(map[string]thirdparty.CollectionTrait), - } - for traitType, trait := range c.Traits { - ret.Traits[traitType] = thirdparty.CollectionTrait{ - Min: trait.Min, - Max: trait.Max, - } - } - return ret -} - -func (c *Asset) toCollectiblesData() thirdparty.CollectibleData { - return thirdparty.CollectibleData{ - ID: c.id(), - Provider: OpenseaV1ID, - Name: c.Name, - Description: c.Description, - Permalink: c.Permalink, - ImageURL: c.ImageURL, - AnimationURL: c.AnimationURL, - Traits: openseaToCollectibleTraits(c.Traits), - BackgroundColor: c.BackgroundColor, - TokenURI: c.TokenURI, - } -} - -func (c *Asset) toCommon() thirdparty.FullCollectibleData { - collection := c.Collection.toCollectionData(c.id().ContractID) - return thirdparty.FullCollectibleData{ - CollectibleData: c.toCollectiblesData(), - CollectionData: &collection, - } -} diff --git a/services/wallet/thirdparty/opensea/types_v2.go b/services/wallet/thirdparty/opensea/types_v2.go index 459d72af2..1979574a0 100644 --- a/services/wallet/thirdparty/opensea/types_v2.go +++ b/services/wallet/thirdparty/opensea/types_v2.go @@ -1,6 +1,8 @@ package opensea import ( + "encoding/json" + "strconv" "strings" "github.com/ethereum/go-ethereum/common" @@ -23,24 +25,7 @@ const ( optimismGoerliString = "optimism_goerli" ) -func chainStringToChainID(chainString string) walletCommon.ChainID { - chainID := walletCommon.UnknownChainID - switch chainString { - case ethereumMainnetString: - chainID = walletCommon.EthereumMainnet - case arbitrumMainnetString: - chainID = walletCommon.ArbitrumMainnet - case optimismMainnetString: - chainID = walletCommon.OptimismMainnet - case ethereumGoerliString: - chainID = walletCommon.EthereumGoerli - case arbitrumGoerliString: - chainID = walletCommon.ArbitrumGoerli - case optimismGoerliString: - chainID = walletCommon.OptimismGoerli - } - return walletCommon.ChainID(chainID) -} +type urlGetter func(walletCommon.ChainID, string) (string, error) func chainIDToChainString(chainID walletCommon.ChainID) string { chainString := "" @@ -99,6 +84,26 @@ type OwnerV2 struct { Quantity *bigint.BigInt `json:"quantity"` } +type TraitValue string + +func (st *TraitValue) UnmarshalJSON(b []byte) error { + var item interface{} + if err := json.Unmarshal(b, &item); err != nil { + return err + } + + switch v := item.(type) { + case float64: + *st = TraitValue(strconv.FormatFloat(v, 'f', 2, 64)) + case int: + *st = TraitValue(strconv.Itoa(v)) + case string: + *st = TraitValue(v) + + } + return nil +} + type TraitV2 struct { TraitType string `json:"trait_type"` DisplayType string `json:"display_type"`