feat: implement alchemy and infura collectible account ownership endpoints
This commit is contained in:
parent
51d676bb08
commit
c92a10b846
|
@ -60,7 +60,7 @@ func getNFTBaseURL(chainID walletCommon.ChainID, apiKey string) (string, error)
|
|||
return "", err
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s/nft/v2/%s", baseURL, getAPIKeySubpath(apiKey)), nil
|
||||
return fmt.Sprintf("%s/nft/v3/%s", baseURL, getAPIKeySubpath(apiKey)), nil
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
|
@ -89,37 +89,128 @@ func (o *Client) doQuery(url string) (*http.Response, error) {
|
|||
}
|
||||
|
||||
func (o *Client) FetchCollectibleOwnersByContractAddress(chainID walletCommon.ChainID, contractAddress common.Address) (*thirdparty.CollectibleContractOwnership, error) {
|
||||
ownership := thirdparty.CollectibleContractOwnership{
|
||||
ContractAddress: contractAddress,
|
||||
Owners: make([]thirdparty.CollectibleOwner, 0),
|
||||
}
|
||||
|
||||
queryParams := url.Values{
|
||||
"contractAddress": {contractAddress.String()},
|
||||
"withTokenBalances": {"true"},
|
||||
}
|
||||
|
||||
url, err := getNFTBaseURL(chainID, o.apiKeys[uint64(chainID)])
|
||||
baseURL, err := getNFTBaseURL(chainID, o.apiKeys[uint64(chainID)])
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
url = url + "/getOwnersForCollection?" + queryParams.Encode()
|
||||
for {
|
||||
url := fmt.Sprintf("%s/getOwnersForContract?%s", baseURL, queryParams.Encode())
|
||||
|
||||
resp, err := o.doQuery(url)
|
||||
resp, err := o.doQuery(url)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var alchemyOwnership CollectibleContractOwnership
|
||||
err = json.Unmarshal(body, &alchemyOwnership)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ownership.Owners = append(ownership.Owners, alchemyCollectibleOwnersToCommon(alchemyOwnership.Owners)...)
|
||||
|
||||
if alchemyOwnership.PageKey == "" {
|
||||
break
|
||||
}
|
||||
|
||||
queryParams["pageKey"] = []string{alchemyOwnership.PageKey}
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var alchemyOwnership CollectibleContractOwnership
|
||||
err = json.Unmarshal(body, &alchemyOwnership)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return alchemyOwnershipToCommon(contractAddress, alchemyOwnership)
|
||||
return &ownership, nil
|
||||
}
|
||||
|
||||
func (o *Client) FetchAllAssetsByOwner(chainID walletCommon.ChainID, owner common.Address, cursor string, limit int) (*thirdparty.FullCollectibleDataContainer, error) {
|
||||
queryParams := url.Values{}
|
||||
|
||||
return o.fetchOwnedAssets(chainID, owner, queryParams, cursor, limit)
|
||||
}
|
||||
|
||||
func (o *Client) FetchAllAssetsByOwnerAndContractAddress(chainID walletCommon.ChainID, owner common.Address, contractAddresses []common.Address, cursor string, limit int) (*thirdparty.FullCollectibleDataContainer, error) {
|
||||
queryParams := url.Values{}
|
||||
|
||||
for _, contractAddress := range contractAddresses {
|
||||
queryParams.Add("contractAddresses", contractAddress.String())
|
||||
}
|
||||
|
||||
return o.fetchOwnedAssets(chainID, owner, queryParams, cursor, limit)
|
||||
}
|
||||
|
||||
func (o *Client) fetchOwnedAssets(chainID walletCommon.ChainID, owner common.Address, queryParams url.Values, cursor string, limit int) (*thirdparty.FullCollectibleDataContainer, error) {
|
||||
assets := new(thirdparty.FullCollectibleDataContainer)
|
||||
|
||||
queryParams["owner"] = []string{owner.String()}
|
||||
queryParams["withMetadata"] = []string{"true"}
|
||||
|
||||
if len(cursor) > 0 {
|
||||
queryParams["pageKey"] = []string{cursor}
|
||||
assets.PreviousCursor = cursor
|
||||
}
|
||||
|
||||
baseURL, err := getNFTBaseURL(chainID, o.apiKeys[uint64(chainID)])
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for {
|
||||
url := fmt.Sprintf("%s/getNFTsForOwner?%s", baseURL, queryParams.Encode())
|
||||
|
||||
resp, err := o.doQuery(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// if Json is not returned there must be an error
|
||||
if !json.Valid(body) {
|
||||
return nil, fmt.Errorf("invalid json: %s", string(body))
|
||||
}
|
||||
|
||||
container := NFTList{}
|
||||
err = json.Unmarshal(body, &container)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
assets.Items = append(assets.Items, container.toCommon(chainID)...)
|
||||
assets.NextCursor = container.PageKey
|
||||
|
||||
if len(assets.NextCursor) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
queryParams["cursor"] = []string{assets.NextCursor}
|
||||
|
||||
if limit != thirdparty.FetchNoLimit && len(assets.Items) >= limit {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return assets, nil
|
||||
}
|
||||
|
|
|
@ -1,9 +1,18 @@
|
|||
package alchemy
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
type TokenBalance struct {
|
||||
|
@ -21,9 +30,9 @@ type CollectibleContractOwnership struct {
|
|||
PageKey string `json:"pageKey"`
|
||||
}
|
||||
|
||||
func alchemyOwnershipToCommon(contractAddress common.Address, alchemyOwnership CollectibleContractOwnership) (*thirdparty.CollectibleContractOwnership, error) {
|
||||
owners := make([]thirdparty.CollectibleOwner, 0, len(alchemyOwnership.Owners))
|
||||
for _, alchemyOwner := range alchemyOwnership.Owners {
|
||||
func alchemyCollectibleOwnersToCommon(alchemyOwners []CollectibleOwner) []thirdparty.CollectibleOwner {
|
||||
owners := make([]thirdparty.CollectibleOwner, 0, len(alchemyOwners))
|
||||
for _, alchemyOwner := range alchemyOwners {
|
||||
balances := make([]thirdparty.TokenBalance, 0, len(alchemyOwner.TokenBalances))
|
||||
|
||||
for _, alchemyBalance := range alchemyOwner.TokenBalances {
|
||||
|
@ -39,11 +48,129 @@ func alchemyOwnershipToCommon(contractAddress common.Address, alchemyOwnership C
|
|||
|
||||
owners = append(owners, owner)
|
||||
}
|
||||
return owners
|
||||
}
|
||||
|
||||
ownership := thirdparty.CollectibleContractOwnership{
|
||||
ContractAddress: contractAddress,
|
||||
Owners: owners,
|
||||
type AttributeValue string
|
||||
|
||||
func (st *AttributeValue) UnmarshalJSON(b []byte) error {
|
||||
var item interface{}
|
||||
if err := json.Unmarshal(b, &item); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return &ownership, nil
|
||||
switch v := item.(type) {
|
||||
case float64:
|
||||
*st = AttributeValue(strconv.FormatFloat(v, 'f', 2, 64))
|
||||
case int:
|
||||
*st = AttributeValue(strconv.Itoa(v))
|
||||
case string:
|
||||
*st = AttributeValue(v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Attribute struct {
|
||||
TraitType string `json:"trait_type"`
|
||||
Value AttributeValue `json:"value"`
|
||||
}
|
||||
|
||||
type RawMetadata struct {
|
||||
Attributes []Attribute `json:"attributes"`
|
||||
}
|
||||
|
||||
type Raw struct {
|
||||
RawMetadata RawMetadata `json:"metadata"`
|
||||
}
|
||||
|
||||
type OpenSeaMetadata struct {
|
||||
ImageURL string `json:"imageUrl"`
|
||||
}
|
||||
|
||||
type Contract struct {
|
||||
Address common.Address `json:"address"`
|
||||
Name string `json:"name"`
|
||||
Symbol string `json:"symbol"`
|
||||
TokenType string `json:"tokenType"`
|
||||
OpenSeaMetadata OpenSeaMetadata `json:"openSeaMetadata"`
|
||||
}
|
||||
|
||||
type Image struct {
|
||||
ImageURL string `json:"pngUrl"`
|
||||
CachedAnimationURL string `json:"cachedUrl"`
|
||||
OriginalAnimationURL string `json:"originalUrl"`
|
||||
}
|
||||
|
||||
type Asset struct {
|
||||
Contract Contract `json:"contract"`
|
||||
TokenID *bigint.BigInt `json:"tokenId"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Image Image `json:"image"`
|
||||
Raw Raw `json:"raw"`
|
||||
TokenURI string `json:"tokenUri"`
|
||||
}
|
||||
|
||||
type NFTList struct {
|
||||
OwnedNFTs []Asset `json:"ownedNfts"`
|
||||
TotalCount *bigint.BigInt `json:"totalCount"`
|
||||
PageKey string `json:"pageKey"`
|
||||
}
|
||||
|
||||
func alchemyToCollectibleTraits(attributes []Attribute) []thirdparty.CollectibleTrait {
|
||||
ret := make([]thirdparty.CollectibleTrait, 0, len(attributes))
|
||||
caser := cases.Title(language.Und, cases.NoLower)
|
||||
for _, orig := range attributes {
|
||||
dest := thirdparty.CollectibleTrait{
|
||||
TraitType: strings.Replace(orig.TraitType, "_", " ", 1),
|
||||
Value: caser.String(string(orig.Value)),
|
||||
}
|
||||
|
||||
ret = append(ret, dest)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *Asset) toCollectionData(id thirdparty.ContractID) thirdparty.CollectionData {
|
||||
ret := thirdparty.CollectionData{
|
||||
ID: id,
|
||||
Name: c.Contract.Name,
|
||||
ImageURL: c.Contract.OpenSeaMetadata.ImageURL,
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *Asset) toCollectiblesData(id thirdparty.CollectibleUniqueID) thirdparty.CollectibleData {
|
||||
return thirdparty.CollectibleData{
|
||||
ID: id,
|
||||
Name: c.Name,
|
||||
Description: c.Description,
|
||||
ImageURL: c.Image.ImageURL,
|
||||
AnimationURL: c.Image.OriginalAnimationURL,
|
||||
Traits: alchemyToCollectibleTraits(c.Raw.RawMetadata.Attributes),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Asset) toCommon(id thirdparty.CollectibleUniqueID) thirdparty.FullCollectibleData {
|
||||
contractData := c.toCollectionData(id.ContractID)
|
||||
return thirdparty.FullCollectibleData{
|
||||
CollectibleData: c.toCollectiblesData(id),
|
||||
CollectionData: &contractData,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *NFTList) toCommon(chainID walletCommon.ChainID) []thirdparty.FullCollectibleData {
|
||||
ret := make([]thirdparty.FullCollectibleData, 0, len(l.OwnedNFTs))
|
||||
for _, asset := range l.OwnedNFTs {
|
||||
id := thirdparty.CollectibleUniqueID{
|
||||
ContractID: thirdparty.ContractID{
|
||||
ChainID: chainID,
|
||||
Address: asset.Contract.Address,
|
||||
},
|
||||
TokenID: asset.TokenID,
|
||||
}
|
||||
item := asset.toCommon(id)
|
||||
ret = append(ret, item)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
|
|
@ -145,6 +145,12 @@ type CollectibleContractOwnership struct {
|
|||
}
|
||||
|
||||
type CollectibleContractOwnershipProvider interface {
|
||||
CollectibleProvider
|
||||
FetchCollectibleOwnersByContractAddress(chainID w_common.ChainID, contractAddress common.Address) (*CollectibleContractOwnership, error)
|
||||
IsChainSupported(chainID w_common.ChainID) bool
|
||||
}
|
||||
|
||||
type CollectibleAccountOwnershipProvider interface {
|
||||
CollectibleProvider
|
||||
FetchAllAssetsByOwner(chainID w_common.ChainID, owner common.Address, cursor string, limit int) (*FullCollectibleDataContainer, error)
|
||||
FetchAllAssetsByOwnerAndContractAddress(chainID w_common.ChainID, owner common.Address, contractAddresses []common.Address, cursor string, limit int) (*FullCollectibleDataContainer, error)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
|
@ -56,8 +57,7 @@ func (o *Client) ID() string {
|
|||
|
||||
func (o *Client) IsChainSupported(chainID walletCommon.ChainID) bool {
|
||||
switch uint64(chainID) {
|
||||
case walletCommon.EthereumMainnet, walletCommon.ArbitrumMainnet:
|
||||
case walletCommon.EthereumGoerli, walletCommon.EthereumSepolia:
|
||||
case walletCommon.EthereumMainnet, walletCommon.ArbitrumMainnet, walletCommon.EthereumGoerli, walletCommon.EthereumSepolia:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -105,3 +105,151 @@ func (o *Client) FetchCollectibleOwnersByContractAddress(chainID walletCommon.Ch
|
|||
|
||||
return infuraOwnershipToCommon(contractAddress, ownersMap)
|
||||
}
|
||||
|
||||
func (o *Client) FetchAllAssetsByOwner(chainID walletCommon.ChainID, owner common.Address, cursor string, limit int) (*thirdparty.FullCollectibleDataContainer, error) {
|
||||
queryParams := url.Values{}
|
||||
|
||||
if len(cursor) > 0 {
|
||||
queryParams["cursor"] = []string{cursor}
|
||||
}
|
||||
|
||||
return o.fetchOwnedAssets(chainID, owner, 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{}
|
||||
|
||||
if len(cursor) > 0 {
|
||||
queryParams["cursor"] = []string{cursor}
|
||||
}
|
||||
|
||||
for _, contractAddress := range contractAddresses {
|
||||
queryParams.Add("tokenAddress", contractAddress.String())
|
||||
}
|
||||
|
||||
return o.fetchOwnedAssets(chainID, owner, queryParams, limit)
|
||||
}
|
||||
|
||||
func (o *Client) fetchOwnedAssets(chainID walletCommon.ChainID, owner common.Address, queryParams url.Values, limit int) (*thirdparty.FullCollectibleDataContainer, error) {
|
||||
assets := new(thirdparty.FullCollectibleDataContainer)
|
||||
|
||||
if len(queryParams["cursor"]) > 0 {
|
||||
assets.PreviousCursor = queryParams["cursor"][0]
|
||||
}
|
||||
|
||||
for {
|
||||
url := fmt.Sprintf("%s/networks/%d/accounts/%s/assets/nfts?%s", baseURL, chainID, owner.String(), queryParams.Encode())
|
||||
|
||||
resp, err := o.doQuery(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// if Json is not returned there must be an error
|
||||
if !json.Valid(body) {
|
||||
return nil, fmt.Errorf("invalid json: %s", string(body))
|
||||
}
|
||||
|
||||
container := NFTList{}
|
||||
err = json.Unmarshal(body, &container)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
assets.Items = append(assets.Items, container.toCommon()...)
|
||||
assets.NextCursor = container.Cursor
|
||||
|
||||
if len(assets.NextCursor) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
queryParams["cursor"] = []string{assets.NextCursor}
|
||||
|
||||
if limit != thirdparty.FetchNoLimit && len(assets.Items) >= limit {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return assets, nil
|
||||
}
|
||||
|
||||
func (o *Client) FetchAssetsByCollectibleUniqueID(uniqueIDs []thirdparty.CollectibleUniqueID) ([]thirdparty.FullCollectibleData, error) {
|
||||
ret := make([]thirdparty.FullCollectibleData, 0, len(uniqueIDs))
|
||||
|
||||
for _, id := range uniqueIDs {
|
||||
url := fmt.Sprintf("%s/networks/%d/nfts/%s/tokens/%s", baseURL, id.ContractID.ChainID, id.ContractID.Address.String(), id.TokenID.String())
|
||||
|
||||
resp, err := o.doQuery(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// if Json is not returned there must be an error
|
||||
if !json.Valid(body) {
|
||||
return nil, fmt.Errorf("invalid json: %s", string(body))
|
||||
}
|
||||
|
||||
asset := Asset{}
|
||||
err = json.Unmarshal(body, &asset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
item := asset.toCommon(id)
|
||||
|
||||
ret = append(ret, item)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (o *Client) FetchCollectionDataByContractID(contractIDs []thirdparty.ContractID) ([]thirdparty.CollectionData, error) {
|
||||
ret := make([]thirdparty.CollectionData, 0, len(contractIDs))
|
||||
|
||||
for _, id := range contractIDs {
|
||||
url := fmt.Sprintf("%s/networks/%d/nfts/%s", baseURL, id.ChainID, id.Address.String())
|
||||
|
||||
resp, err := o.doQuery(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// if Json is not returned there must be an error
|
||||
if !json.Valid(body) {
|
||||
return nil, fmt.Errorf("invalid json: %s", string(body))
|
||||
}
|
||||
|
||||
contract := ContractMetadata{}
|
||||
err = json.Unmarshal(body, &contract)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
item := contract.toCommon(id)
|
||||
|
||||
ret = append(ret, item)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
|
|
@ -1,11 +1,35 @@
|
|||
package infura
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
func chainStringToChainID(chainString string) walletCommon.ChainID {
|
||||
chainID := walletCommon.UnknownChainID
|
||||
switch chainString {
|
||||
case "ETHEREUM":
|
||||
chainID = walletCommon.EthereumMainnet
|
||||
case "ARBITRUM":
|
||||
chainID = walletCommon.ArbitrumMainnet
|
||||
case "GOERLI":
|
||||
chainID = walletCommon.EthereumGoerli
|
||||
case "SEPOLIA":
|
||||
chainID = walletCommon.EthereumSepolia
|
||||
}
|
||||
return walletCommon.ChainID(chainID)
|
||||
}
|
||||
|
||||
type CollectibleOwner struct {
|
||||
ContractAddress common.Address `json:"tokenAddress"`
|
||||
TokenID *bigint.BigInt `json:"tokenId"`
|
||||
|
@ -45,3 +69,115 @@ func infuraOwnershipToCommon(contractAddress common.Address, ownersMap map[commo
|
|||
|
||||
return &ownership, nil
|
||||
}
|
||||
|
||||
type AttributeValue string
|
||||
|
||||
func (st *AttributeValue) UnmarshalJSON(b []byte) error {
|
||||
var item interface{}
|
||||
if err := json.Unmarshal(b, &item); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch v := item.(type) {
|
||||
case float64:
|
||||
*st = AttributeValue(strconv.FormatFloat(v, 'f', 2, 64))
|
||||
case int:
|
||||
*st = AttributeValue(strconv.Itoa(v))
|
||||
case string:
|
||||
*st = AttributeValue(v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Attribute struct {
|
||||
TraitType string `json:"trait_type"`
|
||||
Value AttributeValue `json:"value"`
|
||||
}
|
||||
|
||||
type AssetMetadata struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Permalink string `json:"permalink"`
|
||||
ImageURL string `json:"image"`
|
||||
AnimationURL string `json:"animation_url"`
|
||||
Attributes []Attribute `json:"attributes"`
|
||||
}
|
||||
|
||||
type ContractMetadata struct {
|
||||
ContractAddress string `json:"contract"`
|
||||
Name string `json:"name"`
|
||||
Symbol string `json:"symbol"`
|
||||
TokenType string `json:"tokenType"`
|
||||
}
|
||||
|
||||
type Asset struct {
|
||||
ContractAddress common.Address `json:"contract"`
|
||||
TokenID *bigint.BigInt `json:"tokenId"`
|
||||
Metadata AssetMetadata `json:"metadata"`
|
||||
}
|
||||
|
||||
type NFTList struct {
|
||||
Total *bigint.BigInt `json:"total"`
|
||||
PageNumber int `json:"pageNumber"`
|
||||
PageSize int `json:"pageSize"`
|
||||
Network string `json:"network"`
|
||||
Account string `json:"account"`
|
||||
Cursor string `json:"cursor"`
|
||||
Assets []Asset `json:"assets"`
|
||||
}
|
||||
|
||||
func (c *Asset) toCollectiblesData(id thirdparty.CollectibleUniqueID) thirdparty.CollectibleData {
|
||||
return thirdparty.CollectibleData{
|
||||
ID: id,
|
||||
Name: c.Metadata.Name,
|
||||
Description: c.Metadata.Description,
|
||||
Permalink: c.Metadata.Permalink,
|
||||
ImageURL: c.Metadata.ImageURL,
|
||||
AnimationURL: c.Metadata.AnimationURL,
|
||||
Traits: infuraToCollectibleTraits(c.Metadata.Attributes),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Asset) toCommon(id thirdparty.CollectibleUniqueID) thirdparty.FullCollectibleData {
|
||||
return thirdparty.FullCollectibleData{
|
||||
CollectibleData: c.toCollectiblesData(id),
|
||||
CollectionData: nil,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *NFTList) toCommon() []thirdparty.FullCollectibleData {
|
||||
ret := make([]thirdparty.FullCollectibleData, 0, len(l.Assets))
|
||||
for _, asset := range l.Assets {
|
||||
id := thirdparty.CollectibleUniqueID{
|
||||
ContractID: thirdparty.ContractID{
|
||||
ChainID: chainStringToChainID(l.Network),
|
||||
Address: asset.ContractAddress,
|
||||
},
|
||||
TokenID: asset.TokenID,
|
||||
}
|
||||
item := asset.toCommon(id)
|
||||
ret = append(ret, item)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func infuraToCollectibleTraits(attributes []Attribute) []thirdparty.CollectibleTrait {
|
||||
ret := make([]thirdparty.CollectibleTrait, 0, len(attributes))
|
||||
caser := cases.Title(language.Und, cases.NoLower)
|
||||
for _, orig := range attributes {
|
||||
dest := thirdparty.CollectibleTrait{
|
||||
TraitType: strings.Replace(orig.TraitType, "_", " ", 1),
|
||||
Value: caser.String(string(orig.Value)),
|
||||
}
|
||||
|
||||
ret = append(ret, dest)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *ContractMetadata) toCommon(id thirdparty.ContractID) thirdparty.CollectionData {
|
||||
return thirdparty.CollectionData{
|
||||
ID: id,
|
||||
Name: c.Name,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,9 +6,11 @@ import (
|
|||
"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"
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue