Skip to content

Commit

Permalink
feat: NFT details new design (#25524)
Browse files Browse the repository at this point in the history
## **Description**

PR that updates the design for the NFT page.
Designs are here:
https://www.figma.com/design/TfVzSMJA8KwpWX8TTWQ2iO/Asset-list-and-details?node-id=3717-47944&m=dev

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25524?quickstart=1)

## **Related issues**

Fixes:
Related: MetaMask/core#4443

## **Manual testing steps**

1. Go to NFT tab
2. Click on any NFT you have
3. You should be able to see the new NFT page with no errors even if
some data is not available.


## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**



https://github.com/MetaMask/metamask-extension/assets/10994169/dc6ca128-5f2a-45e2-9289-d84f5403d772


### **After**



https://github.com/MetaMask/metamask-extension/assets/10994169/58fd8cd4-24d9-42e9-931a-c33f8ae812d6



## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

---------

Co-authored-by: MetaMask Bot <[email protected]>
  • Loading branch information
sahar-fehri and metamaskbot authored Jul 16, 2024
1 parent 7b3450a commit b9de828
Show file tree
Hide file tree
Showing 47 changed files with 1,907 additions and 764 deletions.
236 changes: 236 additions & 0 deletions .yarn/patches/@metamask-assets-controllers-npm-34.0.0-ea790e90a1.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
diff --git a/dist/chunk-354SINOH.js b/dist/chunk-354SINOH.js
index 7f87776370b755bf04765b8a0ae0145bf3a0b5e6..e0b47123b31b3c7779e903180afc6c692953b6c2 100644
--- a/dist/chunk-354SINOH.js
+++ b/dist/chunk-354SINOH.js
@@ -12,7 +12,8 @@ var _basecontroller = require('@metamask/base-controller');



-
+var MAX_GET_COLLECTION_BATCH_SIZE = 20;
+var _chunkNYVA7ZTQjs = require('./chunk-NYVA7ZTQ.js');

var _controllerutils = require('@metamask/controller-utils');
var _utils = require('@metamask/utils');
@@ -134,6 +135,60 @@ var NftDetectionController = class extends _basecontroller.BaseController {
apiNfts = resultNftApi.tokens.filter(
(elm) => elm.token.isSpam === false && (elm.blockaidResult?.result_type ? elm.blockaidResult?.result_type === "Benign" /* Benign */ : true)
);
+ const collections = apiNfts.reduce((acc, currValue) => {
+ if (!acc.includes(currValue.token.contract) && currValue.token.contract === currValue?.token?.collection?.id) {
+ acc.push(currValue.token.contract);
+ }
+ return acc;
+ }, []);
+ if (collections.length !== 0) {
+ const collectionResponse = await _chunkNYVA7ZTQjs.reduceInBatchesSerially.call(void 0, {
+ values: collections,
+ batchSize: MAX_GET_COLLECTION_BATCH_SIZE,
+ eachBatch: async (allResponses, batch) => {
+ const params = new URLSearchParams(
+ batch.map((s) => ["contract", s])
+ );
+ params.append("chainId", "1");
+ const collectionResponseForBatch = await _controllerutils.fetchWithErrorHandling.call(void 0,
+ {
+ url: `${_controllerutils.NFT_API_BASE_URL}/collections?${params.toString()}`,
+ options: {
+ headers: {
+ Version: _controllerutils.NFT_API_VERSION
+ }
+ },
+ timeout: _controllerutils.NFT_API_TIMEOUT
+ }
+ );
+ return {
+ ...allResponses,
+ ...collectionResponseForBatch
+ };
+ },
+ initialResult: {}
+ });
+ if (collectionResponse.collections?.length) {
+ apiNfts.forEach((singleNFT) => {
+ const found = collectionResponse.collections.find(
+ (elm) => elm.id?.toLowerCase() === singleNFT.token.contract.toLowerCase()
+ );
+ if (found) {
+ singleNFT.token = {
+ ...singleNFT.token,
+ collection: {
+ ...singleNFT.token.collection ? singleNFT.token.collection : {},
+ creator: found?.creator,
+ openseaVerificationStatus: found?.openseaVerificationStatus,
+ contractDeployedAt: found.contractDeployedAt,
+ ownerCount: found.ownerCount,
+ topBid: found.topBid
+ }
+ };
+ }
+ });
+ }
+ }
const addNftPromises = apiNfts.map(async (nft) => {
const {
tokenId,
diff --git a/dist/chunk-7JWDWDXT.js b/dist/chunk-7JWDWDXT.js
index af5d78416658763da52305f9e08b286733310898..5f1d7268ed8b102e0aab9f09c3896ea6fba6a0a8 100644
--- a/dist/chunk-7JWDWDXT.js
+++ b/dist/chunk-7JWDWDXT.js
@@ -881,6 +881,18 @@ getNftInformationFromApi_fn = async function(contractAddress, tokenId) {
}
}
});
+ const getCollectionParams = new URLSearchParams({
+ chainId: "1",
+ id: `${nftInformation?.tokens[0]?.token?.collection?.id}`
+ }).toString();
+ const collectionInformation = await _controllerutils.fetchWithErrorHandling.call(void 0, {
+ url: `${_controllerutils.NFT_API_BASE_URL}/collections?${getCollectionParams}`,
+ options: {
+ headers: {
+ Version: _controllerutils.NFT_API_VERSION
+ }
+ }
+ });
if (!nftInformation?.tokens?.[0]?.token) {
return {
name: null,
@@ -918,7 +930,16 @@ getNftInformationFromApi_fn = async function(contractAddress, tokenId) {
},
rarityRank && { rarityRank },
rarity && { rarity },
- collection && { collection }
+ (collection || collectionInformation) && {
+ collection: {
+ ...collection || {},
+ creator: collection?.creator || collectionInformation?.collections[0].creator,
+ openseaVerificationStatus: collectionInformation?.collections[0].openseaVerificationStatus,
+ contractDeployedAt: collectionInformation?.collections[0].contractDeployedAt,
+ ownerCount: collectionInformation?.collections[0].ownerCount,
+ topBid: collectionInformation?.collections[0].topBid
+ }
+ }
);
return nftMetadata;
};
@@ -1095,7 +1116,8 @@ addIndividualNft_fn = async function(tokenAddress, tokenId, nftMetadata, nftCont
nftMetadata,
existingEntry
);
- if (!differentMetadata && existingEntry.isCurrentlyOwned) {
+ const hasNewFields = hasNewCollectionFields(nftMetadata, existingEntry);
+ if (!differentMetadata && existingEntry.isCurrentlyOwned && !hasNewFields) {
return;
}
const indexToUpdate = nfts.findIndex(
diff --git a/dist/chunk-NYVA7ZTQ.js b/dist/chunk-NYVA7ZTQ.js
index f31fdabedc067227407a6320e57a670f86b972f4..c0ff7ece56dc5f3e68149d114ff16f7d10eb1741 100644
--- a/dist/chunk-NYVA7ZTQ.js
+++ b/dist/chunk-NYVA7ZTQ.js
@@ -27,6 +27,11 @@ function compareNftMetadata(newNftMetadata, nft) {
}, 0);
return differentValues > 0;
}
+function hasNewCollectionFields(newNftMetadata, nft) {
+ const keysNewNftMetadata = Object.keys(newNftMetadata.collection || {});
+ const keysExistingNft = new Set(Object.keys(nft.collection || {}));
+ return keysNewNftMetadata.some((key) => !keysExistingNft.has(key));
+}
var aggregatorNameByKey = {
aave: "Aave",
bancor: "Bancor",
@@ -205,5 +210,5 @@ async function fetchTokenContractExchangeRates({



-exports.TOKEN_PRICES_BATCH_SIZE = TOKEN_PRICES_BATCH_SIZE; exports.compareNftMetadata = compareNftMetadata; exports.formatAggregatorNames = formatAggregatorNames; exports.formatIconUrlWithProxy = formatIconUrlWithProxy; exports.SupportedTokenDetectionNetworks = SupportedTokenDetectionNetworks; exports.isTokenDetectionSupportedForNetwork = isTokenDetectionSupportedForNetwork; exports.isTokenListSupportedForNetwork = isTokenListSupportedForNetwork; exports.removeIpfsProtocolPrefix = removeIpfsProtocolPrefix; exports.getIpfsCIDv1AndPath = getIpfsCIDv1AndPath; exports.getFormattedIpfsUrl = getFormattedIpfsUrl; exports.addUrlProtocolPrefix = addUrlProtocolPrefix; exports.ethersBigNumberToBN = ethersBigNumberToBN; exports.divideIntoBatches = divideIntoBatches; exports.reduceInBatchesSerially = reduceInBatchesSerially; exports.fetchTokenContractExchangeRates = fetchTokenContractExchangeRates;
+exports.TOKEN_PRICES_BATCH_SIZE = TOKEN_PRICES_BATCH_SIZE; exports.compareNftMetadata = compareNftMetadata; exports.hasNewCollectionFields = hasNewCollectionFields; exports.formatAggregatorNames = formatAggregatorNames; exports.formatIconUrlWithProxy = formatIconUrlWithProxy; exports.SupportedTokenDetectionNetworks = SupportedTokenDetectionNetworks; exports.isTokenDetectionSupportedForNetwork = isTokenDetectionSupportedForNetwork; exports.isTokenListSupportedForNetwork = isTokenListSupportedForNetwork; exports.removeIpfsProtocolPrefix = removeIpfsProtocolPrefix; exports.getIpfsCIDv1AndPath = getIpfsCIDv1AndPath; exports.getFormattedIpfsUrl = getFormattedIpfsUrl; exports.addUrlProtocolPrefix = addUrlProtocolPrefix; exports.ethersBigNumberToBN = ethersBigNumberToBN; exports.divideIntoBatches = divideIntoBatches; exports.reduceInBatchesSerially = reduceInBatchesSerially; exports.fetchTokenContractExchangeRates = fetchTokenContractExchangeRates;
//# sourceMappingURL=chunk-NYVA7ZTQ.js.map
\ No newline at end of file
diff --git a/dist/types/NftController.d.ts b/dist/types/NftController.d.ts
index b663e265475fee486f1e570736a08f2c06ce5479..0252b138bb4f1cbcbfab7c6eadc8ba28fe5af674 100644
--- a/dist/types/NftController.d.ts
+++ b/dist/types/NftController.d.ts
@@ -7,7 +7,7 @@ import type { PreferencesControllerStateChangeEvent } from '@metamask/preference
import type { Hex } from '@metamask/utils';
import type { AssetsContractController } from './AssetsContractController';
import { Source } from './constants';
-import type { Collection, Attributes, LastSale } from './NftDetectionController';
+import type { Collection, Attributes, LastSale, TopBid } from './NftDetectionController';
type NFTStandardType = 'ERC721' | 'ERC1155';
type SuggestedNftMeta = {
asset: {
@@ -110,9 +110,10 @@ export type NftMetadata = {
tokenURI?: string | null;
collection?: Collection;
address?: string;
- attributes?: Attributes;
+ attributes?: Attributes[];
lastSale?: LastSale;
rarityRank?: string;
+ topBid?: TopBid;
};
/**
* @type NftControllerState
diff --git a/dist/types/NftDetectionController.d.ts b/dist/types/NftDetectionController.d.ts
index c645b3ada1ad9dd862428e94adb788f7892c99ad..ad2df53b8225c105b67245f6498702920f882f95 100644
--- a/dist/types/NftDetectionController.d.ts
+++ b/dist/types/NftDetectionController.d.ts
@@ -227,7 +227,43 @@ export type Attributes = {
topBidValue?: number | null;
createdAt?: string;
};
-export type Collection = {
+
+export type GetCollectionsResponse = {
+ collections: CollectionResponse[];
+ };
+
+export type CollectionResponse = {
+ id?: string;
+ openseaVerificationStatus?: string;
+ contractDeployedAt?: string;
+ creator?: string;
+ ownerCount?: string;
+ topBid?: TopBid & {
+ sourceDomain?: string;
+ };
+};
+
+export type FloorAskCollection = {
+ id?: string;
+ price?: Price;
+ maker?: string;
+ kind?: string;
+ validFrom?: number;
+ validUntil?: number;
+ source?: SourceCollection;
+ rawData?: Metadata;
+ isNativeOffChainCancellable?: boolean;
+};
+
+export type SourceCollection = {
+ id: string;
+ domain: string;
+ name: string;
+ icon: string;
+ url: string;
+};
+
+export type TokenCollection = {
id?: string;
name?: string;
slug?: string;
@@ -243,7 +279,10 @@ export type Collection = {
floorAskPrice?: Price;
royaltiesBps?: number;
royalties?: Royalties[];
-};
+ floorAsk?: FloorAskCollection;
+ };
+
+export type Collection = TokenCollection & CollectionResponse;
export type Royalties = {
bps?: number;
recipient?: string;
3 changes: 0 additions & 3 deletions app/_locales/de/messages.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions app/_locales/el/messages.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 45 additions & 3 deletions app/_locales/en/messages.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit b9de828

Please sign in to comment.