From ebfa1dc7adcff2d983783a3c162e2484423cb374 Mon Sep 17 00:00:00 2001 From: Will Smillie Date: Fri, 13 Oct 2023 17:47:51 -0400 Subject: [PATCH 1/6] Add support for support for `image/webp` in NFTAnimation --- components/nftDetail/NFTAnimation.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/nftDetail/NFTAnimation.tsx b/components/nftDetail/NFTAnimation.tsx index ff214e4..f9ab6c1 100644 --- a/components/nftDetail/NFTAnimation.tsx +++ b/components/nftDetail/NFTAnimation.tsx @@ -65,6 +65,8 @@ const NFTAnimation: React.FC<{ animationURL: string; animationType: string; imag /> ); + } else if (animationType?.startsWith('image/webp')) { + return ; } else { return ; } From f8ab733dbabdba33fbcebc001b13dbd7c3ecbab4 Mon Sep 17 00:00:00 2001 From: Will Smillie Date: Fri, 13 Oct 2023 18:27:55 -0400 Subject: [PATCH 2/6] prefer any animation_url prior to fallback src --- components/nftDetail/NFTAnimation.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/nftDetail/NFTAnimation.tsx b/components/nftDetail/NFTAnimation.tsx index f9ab6c1..5d0a918 100644 --- a/components/nftDetail/NFTAnimation.tsx +++ b/components/nftDetail/NFTAnimation.tsx @@ -65,7 +65,7 @@ const NFTAnimation: React.FC<{ animationURL: string; animationType: string; imag /> ); - } else if (animationType?.startsWith('image/webp')) { + } else if (animationType?.startsWith('image/')) { return ; } else { return ; From 0d0ffe93d2c437cb4712bf3848de7a7e643f4aa6 Mon Sep 17 00:00:00 2001 From: Will Smillie Date: Mon, 29 Jan 2024 15:47:56 -0500 Subject: [PATCH 3/6] ERC1155 - transform metadata uri id parameter --- hooks/useCachedNFT.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/hooks/useCachedNFT.ts b/hooks/useCachedNFT.ts index 158c94e..968fd0b 100644 --- a/hooks/useCachedNFT.ts +++ b/hooks/useCachedNFT.ts @@ -1,4 +1,5 @@ import React from 'react'; + import { ethers } from 'ethers'; import { INFURA_ENDPOINT } from '../utils/config'; @@ -59,8 +60,11 @@ const getERC1155URI = async (nft, isFailOver = false) => { const nftContract = new ethers.Contract(nft.token, contractABIERC1155, provider); - const uri = await nftContract.uri(nft.nftID); - return uri; + const nftIDDecimal = parseInt(nft.nftID, 16).toString(); // Convert hexadecimal to decimal and then to a string + + const uri = await nftContract.uri(nftIDDecimal); + + return uri.replace('{id}', nftIDDecimal); } catch (error) { console.error(error); if (!isFailOver) { @@ -90,7 +94,6 @@ const getNFTURI = async (nft) => { }; const getNFTMetadata = async (uri, nft, isErrorFallback = false) => { - const cacheKey = nft.id; let cacheResult = metadataCache.get(cacheKey); if (cacheResult) { @@ -104,17 +107,14 @@ const getNFTMetadata = async (uri, nft, isErrorFallback = false) => { }; } try { - const metadata = await fetch(uri.replace('ipfs://', IPFS_URL)) - .catch(() => { - - return fetch(uri.replace('ipfs://', FALLBACK_IPFS_URL)) - }) - .then((res) => res.json()); + .catch(() => { + return fetch(uri.replace('ipfs://', FALLBACK_IPFS_URL)); + }) + .then((res) => res.json()); metadataCache.set(cacheKey, metadata); return metadata; } catch (error) { - if (!isErrorFallback) { return getNFTMetadata(`${uri}/metadata.json`, nft, true); } From 1bf5b8c3bb00b3cb45fc80aa9728121cdc840408 Mon Sep 17 00:00:00 2001 From: Will Smillie Date: Mon, 29 Jan 2024 16:46:25 -0500 Subject: [PATCH 4/6] revert unrelated changes --- hooks/useCachedNFT.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/hooks/useCachedNFT.ts b/hooks/useCachedNFT.ts index 968fd0b..c0972da 100644 --- a/hooks/useCachedNFT.ts +++ b/hooks/useCachedNFT.ts @@ -1,5 +1,4 @@ import React from 'react'; - import { ethers } from 'ethers'; import { INFURA_ENDPOINT } from '../utils/config'; @@ -60,11 +59,8 @@ const getERC1155URI = async (nft, isFailOver = false) => { const nftContract = new ethers.Contract(nft.token, contractABIERC1155, provider); - const nftIDDecimal = parseInt(nft.nftID, 16).toString(); // Convert hexadecimal to decimal and then to a string - - const uri = await nftContract.uri(nftIDDecimal); - - return uri.replace('{id}', nftIDDecimal); + const uri = await nftContract.uri(nft.nftID); + return uri; } catch (error) { console.error(error); if (!isFailOver) { @@ -94,6 +90,7 @@ const getNFTURI = async (nft) => { }; const getNFTMetadata = async (uri, nft, isErrorFallback = false) => { + const cacheKey = nft.id; let cacheResult = metadataCache.get(cacheKey); if (cacheResult) { @@ -108,10 +105,11 @@ const getNFTMetadata = async (uri, nft, isErrorFallback = false) => { } try { const metadata = await fetch(uri.replace('ipfs://', IPFS_URL)) - .catch(() => { - return fetch(uri.replace('ipfs://', FALLBACK_IPFS_URL)); - }) - .then((res) => res.json()); + .catch(() => { + + return fetch(uri.replace('ipfs://', FALLBACK_IPFS_URL)) + }) + .then((res) => res.json()); metadataCache.set(cacheKey, metadata); return metadata; } catch (error) { From 9bebe46cb72df367e770331ba885290f8dcf4ca9 Mon Sep 17 00:00:00 2001 From: Will Smillie Date: Mon, 29 Jan 2024 16:52:00 -0500 Subject: [PATCH 5/6] revert whitespaces useCachedNFT.ts --- hooks/useCachedNFT.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hooks/useCachedNFT.ts b/hooks/useCachedNFT.ts index c0972da..158c94e 100644 --- a/hooks/useCachedNFT.ts +++ b/hooks/useCachedNFT.ts @@ -104,6 +104,7 @@ const getNFTMetadata = async (uri, nft, isErrorFallback = false) => { }; } try { + const metadata = await fetch(uri.replace('ipfs://', IPFS_URL)) .catch(() => { @@ -113,6 +114,7 @@ const getNFTMetadata = async (uri, nft, isErrorFallback = false) => { metadataCache.set(cacheKey, metadata); return metadata; } catch (error) { + if (!isErrorFallback) { return getNFTMetadata(`${uri}/metadata.json`, nft, true); } From 4a69edc3d296513cfc3bedf97e0b61cb1e51b9ee Mon Sep 17 00:00:00 2001 From: Will Smillie Date: Tue, 19 Mar 2024 19:24:09 -0400 Subject: [PATCH 6/6] Add fallback to nft collection name. - use first token of the collections collection_metadata name (from nft metadata) --- pages/collections/[address].tsx | 37 ++++++++++++++++++++++++++------- utils/config.ts | 3 ++- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/pages/collections/[address].tsx b/pages/collections/[address].tsx index 5f16669..2944a84 100644 --- a/pages/collections/[address].tsx +++ b/pages/collections/[address].tsx @@ -38,14 +38,37 @@ const getCollectionName = async (address)=> { try { const endpoint = `${LOOPRING_API}${loopringApiEndpoints.collection}?collectionAddress=${address}`; const res = await fetch(endpoint).then((res) => res.json()); - return { - name: res.name as string, - avatar: res.avatar as string, - banner: res.banner as string, - nftType: res.nftType as string, - description: res.description as string - } + if (!res.name) throw new Error('Contract has no name function'); + + return extractCollectionData(res); } catch (error) { + return getCollectionMetadataFromFirstToken(address); + } +}; + +const extractCollectionData = async (res) => { + return { + name: res.name as string, + avatar: res.avatar as string, + banner: res.banner as string, + nftType: res.nftType as string, + description: res.description as string, + }; +}; + +const getCollectionMetadataFromFirstToken = async (address) => { + try { + const endpoint = `${LOOPRING_API}${loopringApiEndpoints.collectionNFTs}?nftHash=${address}&id=0&limit=1&metadata=true`; + const { nftTokenInfos } = await fetch(endpoint).then((res) => res.json()); + const { + metadata: { uri }, + } = nftTokenInfos?.[0]; + + const { collection_metadata } = await fetch(uri).then((res) => res.json()); + const res = await fetch(collection_metadata).then((res) => res.json()); + + return extractCollectionData(res); + } catch { return {}; } }; diff --git a/utils/config.ts b/utils/config.ts index 89741bd..254727c 100644 --- a/utils/config.ts +++ b/utils/config.ts @@ -22,7 +22,8 @@ export const apiEndpointByTxType = { accountUpdate: 'user/transactions', }; export const loopringApiEndpoints = { - collection: 'nft/public/collection' + collection: 'nft/public/collection', + collectionNFTs: 'nft/public/collection/items', }; export const NFT_DISALLOW_LIST = [];