) => setAnchorEl(event.currentTarget)
+ const onClose = () => setAnchorEl(null)
+ const onSelect = (option: AddressName) => {
+ setSelectedAddress(option)
+ onClose()
+ }
+
+ if (!selectedAddress) return null
return (
-
-
-
- {t('plugin_wallet_nft_wall_current_display')}
-
- {formatEthereumAddress(addressName.resolvedAddress ?? '', 4)}
-
-
-
-
-
+
+ {uniqBy(addressNames ?? [], (x) => x.resolvedAddress.toLowerCase()).map((x) => {
+ return (
+
+ )
+ })}
+
+
)
}
diff --git a/packages/mask/src/plugins/Collectible/SNSAdaptor/index.tsx b/packages/mask/src/plugins/Collectible/SNSAdaptor/index.tsx
index 171a280e2fa5..5fc6612f35c9 100644
--- a/packages/mask/src/plugins/Collectible/SNSAdaptor/index.tsx
+++ b/packages/mask/src/plugins/Collectible/SNSAdaptor/index.tsx
@@ -1,4 +1,4 @@
-import { uniq, first } from 'lodash-unified'
+import { uniq } from 'lodash-unified'
import { Plugin, usePostInfoDetails, usePluginWrapper } from '@masknet/plugin-infra'
import { PostInspector } from './PostInspector'
import { base } from '../base'
@@ -30,9 +30,7 @@ const sns: Plugin.SNSAdaptor.Definition = {
label: 'NFTs',
priority: 1,
UI: {
- TabContent: ({ addressNames = [] }) => (
-
- ),
+ TabContent: ({ addressNames = [] }) => ,
},
Utils: {
addressNameSorter: (a, z) => {
diff --git a/packages/provider-proxy/src/index.ts b/packages/provider-proxy/src/index.ts
index b02c896bc350..ad76efa9d6a6 100644
--- a/packages/provider-proxy/src/index.ts
+++ b/packages/provider-proxy/src/index.ts
@@ -2,9 +2,11 @@ import type { RPCMethodRegistrationValue } from './types'
import fungibleTokenProducer from './producers/fungibleTokenAsset'
import nonFungibleCollectionAsset from './producers/nonFungibleCollectionAsset'
import nonFungibleCollectibleAsset from './producers/nonFungibleCollectibleAsset'
+import nonFungibleCollectibleAssetV2 from './producers/nonFungibleCollectibleAssetV2'
export const producers: RPCMethodRegistrationValue[] = [
fungibleTokenProducer,
nonFungibleCollectibleAsset,
+ nonFungibleCollectibleAssetV2,
nonFungibleCollectionAsset,
]
diff --git a/packages/provider-proxy/src/producers/nonFungibleCollectibleAssetV2.ts b/packages/provider-proxy/src/producers/nonFungibleCollectibleAssetV2.ts
new file mode 100644
index 000000000000..a47fb30b34a5
--- /dev/null
+++ b/packages/provider-proxy/src/producers/nonFungibleCollectibleAssetV2.ts
@@ -0,0 +1,55 @@
+import { getOpenSeaNFTList, getRaribleNFTList, getNFTScanNFTs } from '@masknet/web3-providers'
+import type { ERC721TokenDetailed } from '@masknet/web3-shared-evm'
+import type { ProducerArgBase, ProducerKeyFunction, ProducerPushFunction, RPCMethodRegistrationValue } from '../types'
+import { collectAllPageDate } from '../helper/request'
+
+export interface NonFungibleTokenAssetArgs extends ProducerArgBase {
+ address: string
+}
+
+const nonFungibleCollectibleAsset = async (
+ push: ProducerPushFunction,
+ getKeys: ProducerKeyFunction,
+ args: NonFungibleTokenAssetArgs,
+): Promise => {
+ const { address } = args
+ const size = 50
+ const openSeaApiKey = await getKeys('opensea')
+
+ try {
+ await collectAllPageDate(
+ (page) => getOpenSeaNFTList(openSeaApiKey, address, page, size),
+ size,
+ push,
+ )
+ } finally {
+ const fromRarible = collectAllPageDate(
+ (page, pageInfo) => getRaribleNFTList(openSeaApiKey, address, page, size, pageInfo),
+ size,
+ push,
+ )
+
+ const formNFTScanERC721 = collectAllPageDate(
+ (page) => getNFTScanNFTs(address, 'erc721', page, size),
+ size,
+ push,
+ )
+
+ const fromNFTScanERC1155 = collectAllPageDate(
+ (page) => getNFTScanNFTs(address, 'erc1155', page, size),
+ size,
+ push,
+ )
+
+ await Promise.allSettled([fromRarible, formNFTScanERC721, fromNFTScanERC1155])
+ }
+}
+
+const producer: RPCMethodRegistrationValue = {
+ method: 'mask.fetchNonFungibleCollectibleAssetV2',
+ producer: nonFungibleCollectibleAsset,
+ distinctBy: (item) =>
+ `${item.tokenId.toLowerCase()}_${item.contractDetailed.address.toLowerCase()}_${item.contractDetailed.chainId}`,
+}
+
+export default producer
diff --git a/packages/web3-providers/src/NFTScan/index.ts b/packages/web3-providers/src/NFTScan/index.ts
index a5710a6138b7..ca59e1b4b571 100644
--- a/packages/web3-providers/src/NFTScan/index.ts
+++ b/packages/web3-providers/src/NFTScan/index.ts
@@ -1,4 +1,4 @@
-import { ChainId, createERC721ContractDetailed, createERC721Token } from '@masknet/web3-shared-evm'
+import { ChainId, createERC721ContractDetailed, createERC721Token, resolveResourceLink } from '@masknet/web3-shared-evm'
import addSeconds from 'date-fns/addSeconds'
import isBefore from 'date-fns/isBefore'
import urlcat from 'urlcat'
@@ -58,7 +58,7 @@ function createERC721TokenAsset(asset: NFTScanAsset) {
{
name: payload?.name ?? asset.nft_name ?? asset.nft_platform_name ?? '',
description: payload?.description ?? '',
- mediaUrl: payload?.image ?? '',
+ mediaUrl: resolveResourceLink(asset.nft_cover ?? asset.nft_content_uri ?? payload.image ?? ''),
owner: asset.nft_holder ?? '',
},
asset.token_id,
@@ -117,7 +117,8 @@ export class NFTScanAPI implements NonFungibleTokenAPI.Provider {
data: [],
hasNextPage: false,
}
- const data = response.data.content.map(createERC721TokenAsset)
+ const data =
+ response.data.content.map(createERC721TokenAsset).map((x) => ({ ...x, provideBy: 'NFTScan' })) ?? []
const total = response.data.total
return {
data,
diff --git a/packages/web3-providers/src/opensea/index.ts b/packages/web3-providers/src/opensea/index.ts
index 86cbd320f630..0b708c25c2a2 100644
--- a/packages/web3-providers/src/opensea/index.ts
+++ b/packages/web3-providers/src/opensea/index.ts
@@ -63,7 +63,7 @@ function createERC721TokenFromAsset(
chainId: ChainId,
asset: OpenSeaResponse,
): ERC721TokenDetailed {
- const imageURL = asset?.image_url ?? asset?.image_preview_url ?? ''
+ const imageURL = asset?.image_preview_url ?? asset?.image_url ?? ''
return createERC721Token(
createERC721ContractFromAssetContract(asset?.asset_contract?.address, chainId, asset?.asset_contract),
{
@@ -284,7 +284,8 @@ export class OpenSeaAPI implements NonFungibleTokenAPI.Provider {
['non-fungible', 'semi-fungible'].includes(x.asset_contract.asset_contract_type) ||
['ERC721', 'ERC1155'].includes(x.asset_contract.schema_name),
)
- .map((asset: OpenSeaResponse) => createERC721TokenFromAsset(from, asset.token_id, chainId, asset)) ?? []
+ .map((asset: OpenSeaResponse) => createERC721TokenFromAsset(from, asset.token_id, chainId, asset))
+ .map((x) => ({ ...x, provideBy: 'OpenSea' })) ?? []
return {
data: assets,
hasNextPage: assets.length === size,
diff --git a/packages/web3-providers/src/rarible/index.ts b/packages/web3-providers/src/rarible/index.ts
index 2b7119c04d38..257a50fe1fe7 100644
--- a/packages/web3-providers/src/rarible/index.ts
+++ b/packages/web3-providers/src/rarible/index.ts
@@ -6,6 +6,7 @@ import {
ERC721TokenDetailed,
EthereumTokenType,
FungibleTokenDetailed,
+ resolveResourceLink,
} from '@masknet/web3-shared-evm'
import {
Ownership,
@@ -16,7 +17,6 @@ import {
RaribleProfileResponse,
} from './types'
import { RaribleUserURL, RaribleRopstenUserURL, RaribleMainnetURL, RaribleChainURL, RaribleURL } from './constants'
-import { toRaribleImage } from './utils'
import { NonFungibleTokenAPI } from '..'
import { isProxyENV } from '../helpers'
@@ -51,7 +51,7 @@ function createERC721TokenFromAsset(
tokenId: string,
asset?: RaribleNFTItemMapResponse,
): ERC721TokenDetailed {
- const imageURL = toRaribleImage(asset?.meta.image?.url.ORIGINAL ?? asset?.meta.image?.url.PREVIEW ?? '')
+ const imageURL = resolveResourceLink(asset?.meta.image?.url.ORIGINAL ?? asset?.meta.image?.url.PREVIEW ?? '')
return {
contractDetailed: {
type: EthereumTokenType.ERC721,
@@ -64,7 +64,7 @@ function createERC721TokenFromAsset(
name: asset?.meta.name ?? '',
description: asset?.meta.description ?? '',
mediaUrl:
- toRaribleImage(asset?.meta.animation?.url.ORIGINAL ?? asset?.meta.animation?.url.PREVIEW ?? '') ||
+ resolveResourceLink(asset?.meta.animation?.url.ORIGINAL ?? asset?.meta.animation?.url.PREVIEW ?? '') ||
imageURL,
imageURL,
owner: asset?.owners[0],
@@ -80,7 +80,7 @@ function createNFTAsset(asset: RaribleNFTItemMapResponse, chainId: ChainId): Non
is_verified: false,
is_auction: false,
token_address: asset.contract,
- image_url: toRaribleImage(asset?.meta.image?.url.ORIGINAL),
+ image_url: resolveResourceLink(asset?.meta.image?.url.ORIGINAL ?? ''),
asset_contract: null,
owner: owner
? {
@@ -171,9 +171,11 @@ export class RaribleAPI implements NonFungibleTokenAPI.Provider {
hasNextPage: false,
}
- const data = asset.items
- .map((asset) => createERC721TokenFromAsset(asset.contract, asset.tokenId, asset))
- .filter((x) => x.info?.owner?.toLowerCase() === from.toLowerCase())
+ const data =
+ asset.items
+ .map((asset) => createERC721TokenFromAsset(asset.contract, asset.tokenId, asset))
+ .filter((x) => x.info?.owner?.toLowerCase() === from.toLowerCase())
+ .map((x) => ({ ...x, provideBy: 'Rarible' })) ?? []
return {
data,
hasNextPage: !!asset.continuation,
@@ -211,7 +213,7 @@ export class RaribleAPI implements NonFungibleTokenAPI.Provider {
maker_account: {
user: { username: ownerInfo?.name ?? '' },
address: ownerInfo?.id ?? '',
- profile_img_url: toRaribleImage(ownerInfo?.image),
+ profile_img_url: resolveResourceLink(ownerInfo?.image ?? ''),
link: `${resolveRaribleUserNetwork(chainId as number)}${ownerInfo?.id ?? ''}`,
},
}
@@ -242,7 +244,7 @@ export class RaribleAPI implements NonFungibleTokenAPI.Provider {
maker_account: {
user: { username: ownerInfo?.name ?? '' },
address: ownerInfo?.id ?? '',
- profile_img_url: toRaribleImage(ownerInfo?.image),
+ profile_img_url: resolveResourceLink(ownerInfo?.image ?? ''),
link: `${resolveRaribleUserNetwork(chainId as number)}${ownerInfo?.id ?? ''}`,
},
}
diff --git a/packages/web3-providers/src/rarible/utils.ts b/packages/web3-providers/src/rarible/utils.ts
deleted file mode 100644
index 70f4b7d55166..000000000000
--- a/packages/web3-providers/src/rarible/utils.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { resolveIPFSLink } from '@masknet/web3-shared-evm'
-export function toRaribleImage(url?: string) {
- if (!url) return ''
- if (url.startsWith('ipfs://ipfs/')) return resolveIPFSLink(url.replace(/^ipfs:\/\/ipfs\//, ''))
- return url
-}
diff --git a/packages/web3-shared/evm/hooks/useCollectibles.ts b/packages/web3-shared/evm/hooks/useCollectibles.ts
index a7f302e9dc19..bbd9f29b9a3b 100644
--- a/packages/web3-shared/evm/hooks/useCollectibles.ts
+++ b/packages/web3-shared/evm/hooks/useCollectibles.ts
@@ -22,7 +22,7 @@ export function useCollectibles(address: string, chainId: ChainId | null, depend
const id = `mask.fetchNonFungibleCollectibleAsset_${address}_${chainId}`
const message = {
id: dependReady === undefined ? id : dependReady ? id : '',
- method: 'mask.fetchNonFungibleCollectibleAsset',
+ method: 'mask.fetchNonFungibleCollectibleAssetV2',
params: {
address: address,
pageSize: 30,
@@ -33,7 +33,11 @@ export function useCollectibles(address: string, chainId: ChainId | null, depend
const all = uniqWith(
[
...(data ?? []),
- ...erc721Tokens.getCurrentValue().filter((x) => !chainId || x.contractDetailed.chainId === chainId),
+ ...erc721Tokens
+ .getCurrentValue()
+ .filter(
+ (x) => (!chainId || x.contractDetailed.chainId === chainId) && isSameAddress(x.info.owner, address),
+ ),
],
(a, b) => isSameAddress(a.contractDetailed.address, b.contractDetailed.address) && a.tokenId === b.tokenId,
)
diff --git a/packages/web3-shared/evm/pipes/index.ts b/packages/web3-shared/evm/pipes/index.ts
index 220c857a797e..070d3a080d36 100644
--- a/packages/web3-shared/evm/pipes/index.ts
+++ b/packages/web3-shared/evm/pipes/index.ts
@@ -172,7 +172,15 @@ export function resolveBlockLinkOnExplorer(chainId: ChainId, block: string): str
}
export function resolveIPFSLink(ipfs: string): string {
- return urlcat('https://coldcdn.com/api/cdn/mipfsygtms/ipfs/:ipfs', { ipfs })
+ return urlcat('https://ipfs.fleek.co/ipfs/:ipfs', { ipfs })
+}
+
+export function resolveResourceLink(originLink: string): string {
+ if (!originLink) return ''
+ if (originLink.startsWith('http') || originLink.startsWith('data')) return originLink
+ if (originLink.startsWith('ipfs://ipfs/')) return resolveIPFSLink(originLink.replace(/^ipfs:\/\/ipfs\//, ''))
+ if (originLink.startsWith('ipfs://')) return resolveIPFSLink(decodeURIComponent(originLink).replace('ipfs://', ''))
+ return resolveIPFSLink(originLink)
}
export function resolveDomainLink(domain?: string) {