From 68d912cb105c4c796b252a4f89fffe3808fde1f9 Mon Sep 17 00:00:00 2001 From: sahar-fehri Date: Tue, 25 Jun 2024 16:06:24 +0200 Subject: [PATCH 01/41] feat: NFT detail new design --- ui/components/app/nft-details/index.scss | 119 ++ .../nft-detail-information-frame.js | 59 + .../nft-details/nft-detail-information-row.js | 56 + ui/components/app/nft-details/nft-details.js | 1123 ++++++++++++++++- ui/components/app/nft-options/nft-options.js | 2 +- ui/components/multichain/nft-item/index.scss | 3 + ui/pages/asset/components/asset-breadcrumb.js | 1 - 7 files changed, 1355 insertions(+), 8 deletions(-) create mode 100644 ui/components/app/nft-details/nft-detail-information-frame.js create mode 100644 ui/components/app/nft-details/nft-detail-information-row.js diff --git a/ui/components/app/nft-details/index.scss b/ui/components/app/nft-details/index.scss index 6f0a020bce4e..370139c3816b 100644 --- a/ui/components/app/nft-details/index.scss +++ b/ui/components/app/nft-details/index.scss @@ -5,6 +5,125 @@ $link-title-width: 160px; $spacer-break-large: 24px; $spacer-break-small: 16px; + +.nft-image { + + margin-bottom: $spacer-break-small; + + @include design-system.screen-sm-min { + //margin-right: $spacer-break-large; + //margin-bottom: 0; + max-width: 160px; + flex: 0 0 $card-width-break-large; + height: 160px; + } + +} + +.nft-container { + margin-top: 4px; + display: flex; + justify-content: space-between; + // margin-left: 16px; + // margin-right: 16px; +} + +.nft-item { + display: flex; +flex-direction: column; +align-items: flex-start; +align-self: stretch; +} + +.nft-test-image { + @include design-system.screen-sm-min { + height: 160px; + width: 160px; + } + +} + +.text-line { + line-height: 20px; +} + +.text-title-style { + //color: var(--text-alternative, #535A61); + text-align: center; + //font-feature-settings: 'clig' off, 'liga' off; + //font-family: "Euclid Circular B"; + font-size: 10px; + font-style: normal; + font-weight: 500; + line-height: 16px; /* 160% */ +} + +.text-value-style { + color: var(--text-default, #24272A); + text-align: center; + font-feature-settings: 'clig' off, 'liga' off; + text-overflow: ellipsis; + /* Heading-SM */ + font-family: "Euclid Circular B"; + font-size: 16px; + font-style: normal; + font-weight: 700; + line-height: 24px; /* 150% */ +} + +.box-test { +/* display: flex; + padding: 16px; + + flex-direction: column; + align-items: center; + gap: 16px; + + flex: 1 0 0; + width: 50%; */ + + flex: 1 0 33%; /* explanation below */ + //height: 100px; + padding: 16px; + + border-radius: var(--Spacing-sm, 8px); + border: 1px solid var(--border-muted, #D6D9DC); + +} + +.box-test2 { + /* display: flex; + padding: 16px; + + flex-direction: column; + align-items: center; + gap: 16px; + + flex: 1 0 0; + width: 50%; */ + + flex: 1 0 33%; /* explanation below */ + //height: 100px; + padding-left: 16px; + padding-right: 16px; + padding-top: 8px; + padding-bottom: 8px; + + + border-radius: var(--Spacing-sm, 8px); + border: 1px solid var(--border-muted, #D6D9DC); + + } +.nft-image-responsive { + @include design-system.screen-sm-max { + margin-right: $spacer-break-large; + margin-bottom: 0; + max-width: 160px; + flex: 0 0 160px; + height: 160px; + } +} + .nft-details { padding: 0 $spacer-break-small; diff --git a/ui/components/app/nft-details/nft-detail-information-frame.js b/ui/components/app/nft-details/nft-detail-information-frame.js new file mode 100644 index 000000000000..fcaf06fe27e2 --- /dev/null +++ b/ui/components/app/nft-details/nft-detail-information-frame.js @@ -0,0 +1,59 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +import { Box, Text } from '../../component-library'; +import { + AlignItems, + Display, + JustifyContent, +} from '../../../helpers/constants/design-system'; + +const NftDetailInformationFrame = ({ + title, + value, + frameClassname, + frameTextTitleProps, + frameTextTitleStyle, + frameTextValueStyle, + frameTextValueProps, + icon, +}) => { + return ( + /* TODO think about renaming properly the classes className={`account-list-item ${className}`} */ + + + {title} + + + {icon ? ( + + + {value} + + {icon} + + ) : ( + + {value} + + )} + + ); +}; + +NftDetailInformationFrame.propTypes = { + title: PropTypes.string, + value: PropTypes.string, + frameClassname: PropTypes.string, + frameTextTitleProps: PropTypes.object, + frameTextValueProps: PropTypes.object, + frameTextTitleStyle: PropTypes.object, + frameTextValueStyle: PropTypes.object, + icon: PropTypes.node, +}; + +export default NftDetailInformationFrame; diff --git a/ui/components/app/nft-details/nft-detail-information-row.js b/ui/components/app/nft-details/nft-detail-information-row.js new file mode 100644 index 000000000000..fcbd42bb53a0 --- /dev/null +++ b/ui/components/app/nft-details/nft-detail-information-row.js @@ -0,0 +1,56 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +import { Box, Text } from '../../component-library'; +import { + Display, + JustifyContent, + TextColor, + TextVariant, +} from '../../../helpers/constants/design-system'; + +const NftDetailInformationRow = ({ title, valueColor, value, icon }) => { + console.log('🚀 ~ NftDetailInformationRow ~ valueColor:', valueColor); + console.log('value color', valueColor || TextColor.textAlternative); + return ( + + + {title} + + {icon ? ( + + + {value} + + {icon} + + ) : ( + + {value} + + )} + + ); +}; + +NftDetailInformationRow.propTypes = { + title: PropTypes.string, + valueColor: TextColor, + value: PropTypes.string, + icon: PropTypes.node, +}; + +export default NftDetailInformationRow; diff --git a/ui/components/app/nft-details/nft-details.js b/ui/components/app/nft-details/nft-details.js index 55f5cdf32b75..d0aa21514bfc 100644 --- a/ui/components/app/nft-details/nft-details.js +++ b/ui/components/app/nft-details/nft-details.js @@ -3,7 +3,6 @@ import PropTypes from 'prop-types'; import { useDispatch, useSelector } from 'react-redux'; import { useHistory } from 'react-router-dom'; import { isEqual } from 'lodash'; -import Box from '../../ui/box'; import { TextColor, IconColor, @@ -13,6 +12,12 @@ import { OverflowWrap, FlexDirection, Display, + BorderRadius, + BorderStyle, + FlexWrap, + FontStyle, + TextAlign, + AlignItems, } from '../../../helpers/constants/design-system'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { @@ -50,7 +55,17 @@ import { AssetType, TokenStandard, } from '../../../../shared/constants/transaction'; -import { ButtonIcon, IconName, Text } from '../../component-library'; +import { + ButtonIcon, + IconName, + Text, + Box, + ButtonIconSize, + IconSize, + ButtonPrimarySize, + ButtonPrimary, + Icon, +} from '../../component-library'; import Tooltip from '../../ui/tooltip'; import { NftItem } from '../../multichain/nft-item'; import { @@ -58,6 +73,10 @@ import { MetaMetricsEventCategory, } from '../../../../shared/constants/metametrics'; import { MetaMetricsContext } from '../../../contexts/metametrics'; +import classnames from 'classnames'; +import { Content, Footer, Page } from '../../multichain/pages/page'; +import NftDetailInformationRow from './nft-detail-information-row'; +import NftDetailInformationFrame from './nft-detail-information-frame'; export default function NftDetails({ nft }) { const { @@ -199,10 +218,1102 @@ export default function NftDetails({ nft }) { }; return ( - <> + + + + history.push(DEFAULT_ROUTE)} + /> + + + + + global.platform.openTab({ url: openSeaLink }) + : null + } + onRemove={onRemove} + /> + + + + + {name} + + + + + + {description} + + + {/* + + Bought for + + + $550.00 + { + handleAddressCopy(address); + }} + iconName={IconName.Export} + /> + + */} + + { + handleAddressCopy(address); + }} + iconName={IconName.Export} + /> + } + /> + {/* + + Highest floor price + + + $450.00 + { + handleAddressCopy(address); + }} + iconName={IconName.Export} + /> + + */} + { + handleAddressCopy(address); + }} + iconName={IconName.Export} + /> + } + /> + {/* + + Rank + + #70 + */} + + {/* + + Contract address + + + + {shortenAddress(address)} + + { + handleAddressCopy(address); + }} + iconName={ + addressCopied ? IconName.CopySuccess : IconName.Copy + } + /> + + */} + { + handleAddressCopy(address); + }} + iconName={ + addressCopied ? IconName.CopySuccess : IconName.Copy + } + /> + } + /> + + {/* + + Token ID + + + 555 + + */} + + + {/* + + Token symbol + + + PPS + + */} + {/* + + Number of tokens + + + 555 + + */} + + {/* + + Token standard + + + ERC1155 + + */} + + {/* + + Date created + + + 23 Dec + + */} + + + + Price + + + {/* + + Last sold + + + + 23 Dec + + { + handleAddressCopy(address); + }} + iconName={IconName.Export} + /> + + */} + { + handleAddressCopy(address); + }} + iconName={IconName.Export} + justifyContent={JustifyContent.flexEnd} + /> + } + /> + {/* + + Highest current bid + + + + + 0.024ETH + + { + handleAddressCopy(address); + }} + iconName={IconName.Export} + /> + + */} + { + handleAddressCopy(address); + }} + iconName={IconName.Export} + justifyContent={JustifyContent.flexEnd} + /> + } + /> + + + Collection + + + {/* + + Collection name + + + Apes + + */} + + {/* + + Tokens in collection + + + 56667 + + */} + + {/* + + Creator address + + + + + {shortenAddress(address)} + + { + handleAddressCopy(address); + }} + iconName={addressCopied ? IconName.CopySuccess : IconName.Copy} + /> + + */} + { + handleAddressCopy(address); + }} + iconName={addressCopied ? IconName.CopySuccess : IconName.Copy} + justifyContent={JustifyContent.flexEnd} + /> + } + /> + + + Attributes + + + + {/* + + Background + + + + Purple + + */} + + {/* + + Teeth + + + + White + + */} + + + + + {t('nftDisclaimer')} + + + + +
+ console.log('ok')} + size={ButtonPrimarySize.Lg} + block + > + Send + +
+
+ + /* <> + + history.push(DEFAULT_ROUTE)} + /> + + + + + global.platform.openTab({ url: openSeaLink }) + : null + } + onRemove={onRemove} + /> + + + + {name} + + + + {description} + + + + Bought for + + $550.00 + { + handleAddressCopy(address); + }} + iconName={IconName.Export} + /> + + + + Highest floor price + + $450.00 + { + handleAddressCopy(address); + }} + iconName={IconName.Export} + /> + + + + + Rank + + #70 + + + + Contract address + + + + {shortenAddress(address)} + + { + handleAddressCopy(address); + }} + iconName={addressCopied ? IconName.CopySuccess : IconName.Copy} + /> + + + + + + Token ID + + + 555 + + + + + Token symbol + + + PPS + + + + + Number of tokens + + + 555 + + + + + Token standard + + + ERC1155 + + + + + Date created + + + 23 Dec + + + + + Price + + + + + Last sold + + + 23 Dec + + + + + Highest current bid + + + 0.024ETH + + + + + Collection + + + + + Collection name + + + Apes + + + + + Tokens in collection + + + 56667 + + + + + Creator address + + + {shortenAddress(address)} + + + + + Attributes + + + + + + Background + + + + Purple + + + + + Teeth + + + + White + + + + + + {t('nftDisclaimer')} + + + + + */ + + /* ======================== OLD code */ + + /* <> history.push(DEFAULT_ROUTE)} optionsButton={ - + */ ); } diff --git a/ui/components/app/nft-options/nft-options.js b/ui/components/app/nft-options/nft-options.js index 0343667d3ec2..7c976a8b8296 100644 --- a/ui/components/app/nft-options/nft-options.js +++ b/ui/components/app/nft-options/nft-options.js @@ -15,7 +15,7 @@ const NftOptions = ({ onRemove, onViewOnOpensea }) => {
setNftOptionsOpen(true)} color={Color.textDefault} diff --git a/ui/components/multichain/nft-item/index.scss b/ui/components/multichain/nft-item/index.scss index 0ca5fded8d09..3e7291290ba4 100644 --- a/ui/components/multichain/nft-item/index.scss +++ b/ui/components/multichain/nft-item/index.scss @@ -1,3 +1,4 @@ +@use "design-system"; .nft-item { &__container { width: 100%; @@ -23,5 +24,7 @@ padding: 0; width: 100%; height: 100%; + + } } diff --git a/ui/pages/asset/components/asset-breadcrumb.js b/ui/pages/asset/components/asset-breadcrumb.js index 42218ef43a9c..710842a2e5da 100644 --- a/ui/pages/asset/components/asset-breadcrumb.js +++ b/ui/pages/asset/components/asset-breadcrumb.js @@ -16,7 +16,6 @@ const AssetBreadcrumb = ({ accountName, assetName, onBack }) => { size={IconSize.Xs} /> {accountName} -  /  {assetName} ); From 2b3967d88f57564c98fabaf1d38285cdb50a8de5 Mon Sep 17 00:00:00 2001 From: sahar-fehri Date: Wed, 26 Jun 2024 13:44:08 +0200 Subject: [PATCH 02/41] fix: add real values --- app/_locales/en/messages.json | 42 + ui/components/app/nft-details/index.scss | 240 +-- .../nft-detail-information-frame.js | 1 - .../nft-details/nft-detail-information-row.js | 2 - ui/components/app/nft-details/nft-details.js | 1402 ++++------------- ui/helpers/utils/util.js | 24 + 6 files changed, 400 insertions(+), 1311 deletions(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 814a31bdca50..7a8c16dd7593 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -617,6 +617,9 @@ "attemptingConnect": { "message": "Attempting to connect to blockchain." }, + "attributes": { + "message": "Attributes" + }, "attributions": { "message": "Attributions" }, @@ -805,6 +808,9 @@ "blockies": { "message": "Blockies" }, + "boughtFor": { + "message": "Bought for" + }, "bridge": { "message": "Bridge" }, @@ -926,6 +932,9 @@ "coingecko": { "message": "CoinGecko" }, + "collectionName": { + "message": "Collection name" + }, "comboNoOptions": { "message": "No options found", "description": "Default text shown in the combo field dropdown if no options." @@ -1225,6 +1234,9 @@ "createSnapAccountTitle": { "message": "Create account" }, + "creatorAddress": { + "message": "Creator address" + }, "crossChainSwapsLink": { "message": "Swap across networks with MetaMask Portfolio" }, @@ -1412,6 +1424,12 @@ "dataHex": { "message": "Hex" }, + "dataUnavailable": { + "message": "data unavailable" + }, + "dateCreated": { + "message": "Date created" + }, "dcent": { "message": "D'Cent" }, @@ -2152,6 +2170,12 @@ "highLowercase": { "message": "high" }, + "highestCurrentBid": { + "message": "Highest current bid" + }, + "highestFloorPrice": { + "message": "Highest floor price" + }, "history": { "message": "History" }, @@ -3359,6 +3383,9 @@ "numberOfNewTokensDetectedSingular": { "message": "1 new token found in this account" }, + "numberOfTokens": { + "message": "Number of tokens" + }, "ofTextNofM": { "message": "of" }, @@ -3995,6 +4022,12 @@ "prev": { "message": "Prev" }, + "price": { + "message": "Price" + }, + "priceUnavailable": { + "message": "price unavailable" + }, "primaryCurrencySetting": { "message": "Primary currency" }, @@ -4147,6 +4180,9 @@ "quoteRate": { "message": "Quote rate" }, + "rank": { + "message": "Rank" + }, "reAddAccounts": { "message": "re-add any other accounts" }, @@ -5944,6 +5980,9 @@ "tokenShowUp": { "message": "Your tokens may not automatically show up in your wallet. " }, + "tokenStandard": { + "message": "Token standard" + }, "tokenSymbol": { "message": "Token symbol" }, @@ -5954,6 +5993,9 @@ "message": "$1 new tokens found", "description": "$1 is the number of new tokens detected" }, + "tokensInCollection": { + "message": "Tokens in collection" + }, "tooltipApproveButton": { "message": "I understand" }, diff --git a/ui/components/app/nft-details/index.scss b/ui/components/app/nft-details/index.scss index 370139c3816b..d027ac8792b7 100644 --- a/ui/components/app/nft-details/index.scss +++ b/ui/components/app/nft-details/index.scss @@ -5,238 +5,36 @@ $link-title-width: 160px; $spacer-break-large: 24px; $spacer-break-small: 16px; - -.nft-image { - - margin-bottom: $spacer-break-small; - - @include design-system.screen-sm-min { - //margin-right: $spacer-break-large; - //margin-bottom: 0; +.nft-details { + &__nft-image { + @include design-system.screen-sm-max { + margin-right: $spacer-break-large; + margin-bottom: 0; max-width: 160px; - flex: 0 0 $card-width-break-large; + flex: 0 0 160px; height: 160px; } - -} - -.nft-container { - margin-top: 4px; - display: flex; - justify-content: space-between; - // margin-left: 16px; - // margin-right: 16px; -} - -.nft-item { - display: flex; -flex-direction: column; -align-items: flex-start; -align-self: stretch; -} - -.nft-test-image { - @include design-system.screen-sm-min { - height: 160px; - width: 160px; } -} - -.text-line { - line-height: 20px; -} - -.text-title-style { - //color: var(--text-alternative, #535A61); - text-align: center; - //font-feature-settings: 'clig' off, 'liga' off; - //font-family: "Euclid Circular B"; - font-size: 10px; - font-style: normal; - font-weight: 500; - line-height: 16px; /* 160% */ -} - -.text-value-style { - color: var(--text-default, #24272A); - text-align: center; - font-feature-settings: 'clig' off, 'liga' off; - text-overflow: ellipsis; - /* Heading-SM */ - font-family: "Euclid Circular B"; - font-size: 16px; - font-style: normal; - font-weight: 700; - line-height: 24px; /* 150% */ -} - -.box-test { -/* display: flex; - padding: 16px; - - flex-direction: column; - align-items: center; - gap: 16px; - - flex: 1 0 0; - width: 50%; */ - - flex: 1 0 33%; /* explanation below */ - //height: 100px; - padding: 16px; - - border-radius: var(--Spacing-sm, 8px); - border: 1px solid var(--border-muted, #D6D9DC); - -} - -.box-test2 { - /* display: flex; + &__nft-frame { + flex: 1 0 33%; padding: 16px; + border-radius: var(--Spacing-sm, 8px); + border: 1px solid var(--border-muted, #D6D9DC); + } - flex-direction: column; - align-items: center; - gap: 16px; - - flex: 1 0 0; - width: 50%; */ - - flex: 1 0 33%; /* explanation below */ - //height: 100px; + &__nft-attribute-frame { + @include design-system.screen-sm-max { + width: 48.51%; + } + //flex: 1 0 33%; + display: inline-block; + width: 49%; padding-left: 16px; padding-right: 16px; padding-top: 8px; padding-bottom: 8px; - - border-radius: var(--Spacing-sm, 8px); border: 1px solid var(--border-muted, #D6D9DC); - - } -.nft-image-responsive { - @include design-system.screen-sm-max { - margin-right: $spacer-break-large; - margin-bottom: 0; - max-width: 160px; - flex: 0 0 160px; - height: 160px; - } -} - -.nft-details { - padding: 0 $spacer-break-small; - - @include design-system.screen-sm-min { - padding: 0 $spacer-break-large; - } - - &__tooltip-wrapper { - width: 100%; - } - - &__top-section { - display: flex; - flex-direction: column; - margin-bottom: $spacer-break-small; - box-shadow: var(--shadow-size-xs) var(--color-shadow-default); - padding: $spacer-break-large; - - @include design-system.screen-sm-min { - margin-bottom: $spacer-break-large; - flex-direction: row; - } - } - - &__info { - @include design-system.screen-sm-min { - max-width: - calc( - 100% - #{$card-width-break-large} - #{$spacer-break-large} - ); - flex: 0 0 calc(100% - #{$card-width-break-large} - #{$spacer-break-large}); - } - } - - &__card { - overflow: hidden; - margin-bottom: $spacer-break-small; - - @include design-system.screen-sm-min { - margin-right: $spacer-break-large; - margin-bottom: 0; - max-width: $card-width-break-large; - flex: 0 0 $card-width-break-large; - height: $card-width-break-large; - } - } - - &__nft-item { - margin-bottom: $spacer-break-small; - - @include design-system.screen-sm-min { - margin-right: $spacer-break-large; - margin-bottom: 0; - max-width: $card-width-break-large; - flex: 0 0 $card-width-break-large; - height: $card-width-break-large; - } - } - - &__image { - width: 100%; - object-fit: contain; - } - - &__address { - overflow-wrap: break-word; - } - - &__contract-wrapper { - max-width: calc(100% - #{$link-title-width}); - } - - &__contract-copy-button { - @include design-system.H6; - - width: 80px; - display: flex; - align-items: flex-start; - justify-content: center; - background-color: transparent; - cursor: pointer; - color: var(--color-text-alternative); - border: 0; - margin-top: -4px; - - &:active { - transform: scale(0.97); - } - } - - &__contract-link { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - &__image-source { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - width: 332px; - } - - &__link-title { - flex: 0 0 $link-title-width; - max-width: 0 0 $link-title-width; - } - - &__send-button { - margin-inline-end: 8px; - - @include design-system.screen-sm-min { - max-width: 160px; - } } -} +} \ No newline at end of file diff --git a/ui/components/app/nft-details/nft-detail-information-frame.js b/ui/components/app/nft-details/nft-detail-information-frame.js index fcaf06fe27e2..c51e20858d77 100644 --- a/ui/components/app/nft-details/nft-detail-information-frame.js +++ b/ui/components/app/nft-details/nft-detail-information-frame.js @@ -19,7 +19,6 @@ const NftDetailInformationFrame = ({ icon, }) => { return ( - /* TODO think about renaming properly the classes className={`account-list-item ${className}`} */ {title} diff --git a/ui/components/app/nft-details/nft-detail-information-row.js b/ui/components/app/nft-details/nft-detail-information-row.js index fcbd42bb53a0..5df1225e066d 100644 --- a/ui/components/app/nft-details/nft-detail-information-row.js +++ b/ui/components/app/nft-details/nft-detail-information-row.js @@ -10,8 +10,6 @@ import { } from '../../../helpers/constants/design-system'; const NftDetailInformationRow = ({ title, valueColor, value, icon }) => { - console.log('🚀 ~ NftDetailInformationRow ~ valueColor:', valueColor); - console.log('value color', valueColor || TextColor.textAlternative); return ( - isEqualCaseInsensitive(contractAddress, address), - )?.name; - const { - metadata: { name: selectedAccountName }, - } = useSelector(getSelectedInternalAccount); const nftImageAlt = getNftImageAlt(nft); const nftSrcUrl = imageOriginal ?? image; const nftImageURL = getAssetImageURL(imageOriginal ?? image, ipfsGateway); const isIpfsURL = nftSrcUrl?.startsWith('ipfs:'); const isImageHosted = image?.startsWith('https:'); - const formattedTimestamp = formatDate( - new Date(lastSale?.timestamp).getTime(), - 'M/d/y', - ); + const hasFloorAskPrice = Boolean(collection.floorAsk.price?.amount?.usd); + + const getFloorAskSource = () => { + if ( + hasFloorAskPrice && + (Boolean(collection.floorAsk.source.url) || + Boolean(collection.floorAsk.sourceDomain)) + ) { + return collection.floorAsk.source.url || collection.floorAsk.sourceDomain; + } + return undefined; + }; + + const getCurrentHighestBidValue = () => { + if (topBid.price && collection.topBid.price) { + // return the max between collection top Bid and token topBid + const topBidValue = Math.max( + topBid?.price?.amount?.native, + collection?.topBid?.price?.amount?.native, + ); + const currentChainSymbol = currentChain.ticker; + return `${topBidValue}${currentChainSymbol}`; + } + // return the one that is available + const topBidValue = + topBid?.price?.amount?.native || + collection?.topBid?.price?.amount?.native; + if (!topBidValue) { + return undefined; + } + const currentChainSymbol = currentChain.ticker; + return `${topBidValue}${currentChainSymbol}`; + }; + + const getTopBidSourceDomain = () => { + return ( + topBid?.source?.url || + (collection.topBid?.sourceDomain + ? `https://${collection.topBid?.sourceDomain}` + : undefined) + ); + }; const { chainId } = currentChain; useEffect(() => { @@ -182,7 +209,6 @@ export default function NftDetails({ nft }) { const openSeaLink = getOpenSeaLink(); const sendDisabled = standard !== TokenStandard.ERC721 && standard !== TokenStandard.ERC1155; - const inPopUp = getEnvironmentType() === ENVIRONMENT_TYPE_POPUP; const onSend = async () => { await dispatch( @@ -195,32 +221,19 @@ export default function NftDetails({ nft }) { history.push(SEND_ROUTE); }; - const renderSendButton = () => { - if (isCurrentlyOwned === false) { - return
; - } - return ( - - - {sendDisabled ? ( - - ) : null} - - ); + const getDateCreatedTimestamp = (dateString) => { + const date = new Date(dateString); + return Math.floor(date.getTime() / 1000); }; return ( - + history.push(DEFAULT_ROUTE)} /> - + - {/* - - Bought for - - - $550.00 - { - handleAddressCopy(address); - }} - iconName={IconName.Export} - /> - - */} - { - handleAddressCopy(address); - }} - iconName={IconName.Export} - /> + lastSale?.orderSource ? ( + { + global.platform.openTab({ + url: lastSale?.orderSource, + }); + }} + iconName={IconName.Export} + /> + ) : undefined } /> - {/* - - Highest floor price - - - $450.00 - { - handleAddressCopy(address); - }} - iconName={IconName.Export} - /> - - */} { - handleAddressCopy(address); - }} - iconName={IconName.Export} - /> + getFloorAskSource() ? ( + { + global.platform.openTab({ + url: getFloorAskSource(), + }); + }} + iconName={IconName.Export} + /> + ) : undefined } /> - {/* - - Rank - - #70 - */} - {/* - - Contract address - - - - {shortenAddress(address)} - - { - handleAddressCopy(address); - }} - iconName={ - addressCopied ? IconName.CopySuccess : IconName.Copy - } - /> - - */} - {/* - - Token ID - - - 555 - - */} - - - {/* - - Token symbol - - - PPS - - */} - {/* - - Number of tokens - - - 555 - - */} - - {/* - - Token standard - - - ERC1155 - - */} - - {/* - - Date created - - - 23 Dec - - */} - + + {/* TODO check if collection.symbol is nullremove the whole row? */} + + + + - Price + {t('price')} - {/* - - Last sold - - - - 23 Dec - - { - handleAddressCopy(address); - }} - iconName={IconName.Export} - /> - - */} + {/* TODO check if lastSale is not available remove the whole row? */} { - handleAddressCopy(address); - }} - iconName={IconName.Export} - justifyContent={JustifyContent.flexEnd} - /> + lastSale?.orderSource ? ( + { + global.platform.openTab({ + url: lastSale?.orderSource, + }); + }} + iconName={IconName.Export} + justifyContent={JustifyContent.flexEnd} + /> + ) : undefined } /> - {/* - - Highest current bid - - - - - 0.024ETH - - { - handleAddressCopy(address); - }} - iconName={IconName.Export} - /> - - */} + {/* TODO check if highest current bid is not available remove the whole row? */} { - handleAddressCopy(address); - }} - iconName={IconName.Export} - justifyContent={JustifyContent.flexEnd} - /> + getTopBidSourceDomain() ? ( + { + global.platform.openTab({ + url: getTopBidSourceDomain(), + }); + }} + iconName={IconName.Export} + justifyContent={JustifyContent.flexEnd} + /> + ) : undefined } /> - Collection + {t('notificationItemCollection')} - {/* - - Collection name - - - Apes - - */} - - {/* - - Tokens in collection - - - 56667 - - */} - - {/* - - Creator address - - - - - {shortenAddress(address)} - - { - handleAddressCopy(address); - }} - iconName={addressCopied ? IconName.CopySuccess : IconName.Copy} - /> - - */} + + { - handleAddressCopy(address); + handleAddressCopy(collection.creator); }} iconName={addressCopied ? IconName.CopySuccess : IconName.Copy} justifyContent={JustifyContent.flexEnd} @@ -805,7 +567,7 @@ export default function NftDetails({ nft }) { marginTop={4} > - Attributes + {t('attributes')} - {/* - - Background - - - - Purple - - */} - { + const { key, value } = elm; + return ( + + ); + })} + {/* - {/* - - Teeth - - - - White - - */} + /> */} -
- console.log('ok')} - size={ButtonPrimarySize.Lg} - block - > - Send - -
+ {isCurrentlyOwned === true ? ( +
+ + {t('send')} + + {sendDisabled ? ( + + ) : null} +
+ ) : null}
- - /* <> - - history.push(DEFAULT_ROUTE)} - /> - - - - - global.platform.openTab({ url: openSeaLink }) - : null - } - onRemove={onRemove} - /> - - - - {name} - - - - {description} - - - - Bought for - - $550.00 - { - handleAddressCopy(address); - }} - iconName={IconName.Export} - /> - - - - Highest floor price - - $450.00 - { - handleAddressCopy(address); - }} - iconName={IconName.Export} - /> - - - - - Rank - - #70 - - - - Contract address - - - - {shortenAddress(address)} - - { - handleAddressCopy(address); - }} - iconName={addressCopied ? IconName.CopySuccess : IconName.Copy} - /> - - - - - - Token ID - - - 555 - - - - - Token symbol - - - PPS - - - - - Number of tokens - - - 555 - - - - - Token standard - - - ERC1155 - - - - - Date created - - - 23 Dec - - - - - Price - - - - - Last sold - - - 23 Dec - - - - - Highest current bid - - - 0.024ETH - - - - - Collection - - - - - Collection name - - - Apes - - - - - Tokens in collection - - - 56667 - - - - - Creator address - - - {shortenAddress(address)} - - - - - Attributes - - - - - - Background - - - - Purple - - - - - Teeth - - - - White - - - - - - {t('nftDisclaimer')} - - - -
- console.log('ok')} - size={ButtonPrimarySize.Lg} - block - > - Send - -
- */ - - /* ======================== OLD code */ - - /* <> - history.push(DEFAULT_ROUTE)} - optionsButton={ - global.platform.openTab({ url: openSeaLink }) - : null - } - onRemove={onRemove} - /> - } - /> - - - - - - -
- - {name} - - - #{tokenId} - -
- {description ? ( -
- - {t('description')} - - - {description} - -
- ) : null} - {inPopUp ? null : renderSendButton()} -
-
- - {lastSale ? ( - <> - - - {t('lastSold')} - - - - {formattedTimestamp} - - - - - - {t('lastPriceSold')} - - - - {lastSale?.price?.amount?.decimal}{' '} - {lastSale?.price?.currency?.symbol} - - - - - ) : null} - - - {t('contractAddress')} - - - - {shortenAddress(address)} - - - { - handleAddressCopy(address); - }} - iconName={ - addressCopied ? IconName.CopySuccess : IconName.Copy - } - /> - - - - {inPopUp ? renderSendButton() : null} - - {t('nftDisclaimer')} - - -
- */ - ); -} + ); +} NftDetails.propTypes = { nft: PropTypes.shape({ @@ -1529,22 +687,92 @@ NftDetails.propTypes = { imageThumbnail: PropTypes.string, imagePreview: PropTypes.string, imageOriginal: PropTypes.string, + rarityRank: PropTypes.string, + creator: PropTypes.shape({ address: PropTypes.string, config: PropTypes.string, profile_img_url: PropTypes.string, }), + attributes: PropTypes.arrayOf( + PropTypes.shape({ + key: PropTypes.string, + value: PropTypes.string, + }), + ), lastSale: PropTypes.shape({ timestamp: PropTypes.string, + orderSource: PropTypes.string, + price: PropTypes.shape({ + amount: PropTypes.shape({ + native: PropTypes.string, + decimal: PropTypes.string, + usd: PropTypes.string, + }), + currency: PropTypes.shape({ + symbol: PropTypes.string, + }), + }), + }), + topBid: PropTypes.shape({ + source: PropTypes.shape({ + id: PropTypes.string, + domain: PropTypes.string, + name: PropTypes.string, + icon: PropTypes.string, + url: PropTypes.string, + }), price: PropTypes.shape({ amount: PropTypes.shape({ native: PropTypes.string, decimal: PropTypes.string, + usd: PropTypes.string, }), currency: PropTypes.shape({ symbol: PropTypes.string, }), }), }), + collection: PropTypes.shape({ + tokenCount: PropTypes.string, + name: PropTypes.string, + ownerCount: PropTypes.string, + creator: PropTypes.string, + symbol: PropTypes.string, + contractDeployedAt: PropTypes.string, + floorAsk: PropTypes.shape({ + sourceDomain: PropTypes.string, + source: PropTypes.shape({ + id: PropTypes.string, + domain: PropTypes.string, + name: PropTypes.string, + icon: PropTypes.string, + url: PropTypes.string, + }), + price: PropTypes.shape({ + amount: PropTypes.shape({ + native: PropTypes.string, + decimal: PropTypes.string, + usd: PropTypes.string, + }), + currency: PropTypes.shape({ + symbol: PropTypes.string, + }), + }), + }), + topBid: PropTypes.shape({ + sourceDomain: PropTypes.string, + price: PropTypes.shape({ + amount: PropTypes.shape({ + native: PropTypes.string, + decimal: PropTypes.string, + usd: PropTypes.string, + }), + currency: PropTypes.shape({ + symbol: PropTypes.string, + }), + }), + }), + }), }), }; diff --git a/ui/helpers/utils/util.js b/ui/helpers/utils/util.js index 909c7c2c2d8a..f8e50e438607 100644 --- a/ui/helpers/utils/util.js +++ b/ui/helpers/utils/util.js @@ -57,6 +57,30 @@ export function formatDateWithYearContext( now.year === dateTime.year ? formatThisYear : fallback, ); } + +export function formatDateWithSuffix(timestamp) { + const date = DateTime.fromMillis(timestamp * 1000); // Convert to milliseconds + const { day } = date; + const suffix = getOrdinalSuffix(day); + + return date.toFormat(`MMM d'${suffix}', yyyy`); +} + +function getOrdinalSuffix(day) { + if (day > 3 && day < 21) { + return 'th'; + } // because 11th, 12th, 13th + switch (day % 10) { + case 1: + return 'st'; + case 2: + return 'nd'; + case 3: + return 'rd'; + default: + return 'th'; + } +} /** * Determines if the provided chainId is a default MetaMask chain * From 26201a8eb8776e2eb795ccadbadcc2d2757ed6ce Mon Sep 17 00:00:00 2001 From: sahar-fehri Date: Wed, 26 Jun 2024 14:32:18 +0200 Subject: [PATCH 03/41] fix: add storybooks --- .../nft-detail-information-frame.stories.js | 64 +++++++++++++++++++ .../nft-detail-information-row.stories.js | 22 +++++++ 2 files changed, 86 insertions(+) create mode 100644 ui/components/app/nft-details/nft-detail-information-frame.stories.js create mode 100644 ui/components/app/nft-details/nft-detail-information-row.stories.js diff --git a/ui/components/app/nft-details/nft-detail-information-frame.stories.js b/ui/components/app/nft-details/nft-detail-information-frame.stories.js new file mode 100644 index 000000000000..241cf98ef9e1 --- /dev/null +++ b/ui/components/app/nft-details/nft-detail-information-frame.stories.js @@ -0,0 +1,64 @@ +import React from 'react'; +import { + IconColor, + TextAlign, + TextColor, + TextVariant, +} from '../../../helpers/constants/design-system'; +import { ButtonIcon, IconName, IconSize } from '../../component-library'; +import NftDetailInformationFrame from './nft-detail-information-frame'; + +export default { + title: 'Components/App/NftDetailInformationFrame', + + argTypes: { + nft: { + control: 'object', + }, + }, + args: { + title: 'Bought for', + value: '$500', + frameClassname: 'nft-details__nft-frame', + frameTextTitleProps: { + textAlign: TextAlign.Center, + color: TextColor.textAlternative, + variant: TextVariant.bodyMdMedium, + }, + frameTextTitleStyle: { + fontSize: '10px', + lineHeight: '16px', + }, + frameTextValueProps: { + color: TextColor.textDefault, + variant: TextVariant.headingSm, + }, + frameTextValueStyle: { + fontSize: '16px', + lineHeight: '24px', + }, + }, +}; + +export const DefaultStory = (args) => { + return ( + { + global.platform.openTab({ + url: 'test', + }); + }} + iconName={IconName.Export} + /> + } + /> + ); +}; + +DefaultStory.storyName = 'Default'; diff --git a/ui/components/app/nft-details/nft-detail-information-row.stories.js b/ui/components/app/nft-details/nft-detail-information-row.stories.js new file mode 100644 index 000000000000..e5001cecce2d --- /dev/null +++ b/ui/components/app/nft-details/nft-detail-information-row.stories.js @@ -0,0 +1,22 @@ +import React from 'react'; +import NftDetailInformationRow from './nft-detail-information-row'; + +export default { + title: 'Components/App/NftDetailInformationRow', + + argTypes: { + nft: { + control: 'object', + }, + }, + args: { + title: 'Token ID', + value: '345', + }, +}; + +export const DefaultStory = (args) => { + return ; +}; + +DefaultStory.storyName = 'Default'; From 9ed2b98b6be37867722e9a9ec001a372bc713242 Mon Sep 17 00:00:00 2001 From: sahar-fehri Date: Thu, 27 Jun 2024 16:23:33 +0200 Subject: [PATCH 04/41] fix: design updates --- ui/components/app/nft-details/index.scss | 24 +- .../nft-details/nft-detail-information-row.js | 3 + ui/components/app/nft-details/nft-details.js | 401 +++++++++--------- 3 files changed, 215 insertions(+), 213 deletions(-) diff --git a/ui/components/app/nft-details/index.scss b/ui/components/app/nft-details/index.scss index d027ac8792b7..6c2068833be1 100644 --- a/ui/components/app/nft-details/index.scss +++ b/ui/components/app/nft-details/index.scss @@ -6,19 +6,30 @@ $spacer-break-large: 24px; $spacer-break-small: 16px; .nft-details { + &__content { + @include design-system.screen-lg-min { + padding-left: 128px ; + padding-right: 128px ; + width: auto !important; + } + } &__nft-image { @include design-system.screen-sm-max { - margin-right: $spacer-break-large; - margin-bottom: 0; - max-width: 160px; - flex: 0 0 160px; - height: 160px; + max-width: 144px; + flex: 0 0 144px; + height: 144px; } + max-width: 144px; + flex: 0 0 144px; + height: 144px; } &__nft-frame { flex: 1 0 33%; - padding: 16px; + padding-top: 12px; + padding-bottom: 12px; + padding-left: 16px; + padding-right: 16px; border-radius: var(--Spacing-sm, 8px); border: 1px solid var(--border-muted, #D6D9DC); } @@ -27,7 +38,6 @@ $spacer-break-small: 16px; @include design-system.screen-sm-max { width: 48.51%; } - //flex: 1 0 33%; display: inline-block; width: 49%; padding-left: 16px; diff --git a/ui/components/app/nft-details/nft-detail-information-row.js b/ui/components/app/nft-details/nft-detail-information-row.js index 5df1225e066d..33777b2d4319 100644 --- a/ui/components/app/nft-details/nft-detail-information-row.js +++ b/ui/components/app/nft-details/nft-detail-information-row.js @@ -10,6 +10,9 @@ import { } from '../../../helpers/constants/design-system'; const NftDetailInformationRow = ({ title, valueColor, value, icon }) => { + if (!value) { + return null; + } return ( { if ( hasFloorAskPrice && - (Boolean(collection.floorAsk.source.url) || - Boolean(collection.floorAsk.sourceDomain)) + (Boolean(collection?.floorAsk?.source?.url) || + Boolean(collection?.floorAsk?.sourceDomain)) ) { - return collection.floorAsk.source.url || collection.floorAsk.sourceDomain; + return ( + collection?.floorAsk?.source?.url || collection?.floorAsk?.sourceDomain + ); } return undefined; }; const getCurrentHighestBidValue = () => { - if (topBid.price && collection.topBid.price) { + if (topBid?.price && collection?.topBid?.price) { // return the max between collection top Bid and token topBid const topBidValue = Math.max( topBid?.price?.amount?.native, @@ -139,7 +143,7 @@ export default function NftDetails({ nft }) { const getTopBidSourceDomain = () => { return ( topBid?.source?.url || - (collection.topBid?.sourceDomain + (collection?.topBid?.sourceDomain ? `https://${collection.topBid?.sourceDomain}` : undefined) ); @@ -228,9 +232,8 @@ export default function NftDetails({ nft }) { return ( - + @@ -241,6 +244,21 @@ export default function NftDetails({ nft }) { iconName={IconName.ArrowLeft} onClick={() => history.push(DEFAULT_ROUTE)} /> + global.platform.openTab({ url: openSeaLink }) + : null + } + onRemove={onRemove} + /> + + - - global.platform.openTab({ url: openSeaLink }) - : null - } - onRemove={onRemove} - /> - + - - - {description} - + + + {description} + + - { - global.platform.openTab({ - url: lastSale?.orderSource, - }); - }} - iconName={IconName.Export} - /> - ) : undefined - } - /> - { - global.platform.openTab({ - url: getFloorAskSource(), - }); - }} - iconName={IconName.Export} - /> - ) : undefined - } - /> - + {hasLastSalePrice || hasFloorAskPrice ? ( + <> + { + global.platform.openTab({ + url: lastSale?.orderSource, + }); + }} + iconName={IconName.Export} + /> + ) : undefined + } + /> + { + global.platform.openTab({ + url: getFloorAskSource(), + }); + }} + iconName={IconName.Export} + /> + ) : undefined + } + /> + + ) : null} + + {rarityRank ? ( + + ) : null} + - {/* TODO check if collection.symbol is nullremove the whole row? */} - {/* TODO check if lastSale is not available remove the whole row? */} - {/* TODO check if highest current bid is not available remove the whole row? */} { - handleAddressCopy(collection.creator); + handleAddressCopy(collection?.creator); }} iconName={addressCopied ? IconName.CopySuccess : IconName.Copy} justifyContent={JustifyContent.flexEnd} @@ -577,7 +606,7 @@ export default function NftDetails({ nft }) { flexWrap={FlexWrap.Wrap} > {' '} - {attributes.map((elm, idx) => { + {attributes?.map((elm, idx) => { const { key, value } = elm; return ( ); })} - {/* - */} Date: Thu, 27 Jun 2024 16:28:25 +0200 Subject: [PATCH 05/41] fix: lint --- ui/components/app/nft-details/index.scss | 13 ++++++++----- ui/components/multichain/nft-item/index.scss | 3 +-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/ui/components/app/nft-details/index.scss b/ui/components/app/nft-details/index.scss index 6c2068833be1..fa5664abb14d 100644 --- a/ui/components/app/nft-details/index.scss +++ b/ui/components/app/nft-details/index.scss @@ -8,17 +8,19 @@ $spacer-break-small: 16px; .nft-details { &__content { @include design-system.screen-lg-min { - padding-left: 128px ; - padding-right: 128px ; + padding-left: 128px; + padding-right: 128px; width: auto !important; } } + &__nft-image { @include design-system.screen-sm-max { max-width: 144px; flex: 0 0 144px; height: 144px; } + max-width: 144px; flex: 0 0 144px; height: 144px; @@ -31,13 +33,14 @@ $spacer-break-small: 16px; padding-left: 16px; padding-right: 16px; border-radius: var(--Spacing-sm, 8px); - border: 1px solid var(--border-muted, #D6D9DC); + border: 1px solid var(--border-muted, #d6d9dc); } &__nft-attribute-frame { @include design-system.screen-sm-max { width: 48.51%; } + display: inline-block; width: 49%; padding-left: 16px; @@ -45,6 +48,6 @@ $spacer-break-small: 16px; padding-top: 8px; padding-bottom: 8px; border-radius: var(--Spacing-sm, 8px); - border: 1px solid var(--border-muted, #D6D9DC); + border: 1px solid var(--border-muted, #d6d9dc); } -} \ No newline at end of file +} diff --git a/ui/components/multichain/nft-item/index.scss b/ui/components/multichain/nft-item/index.scss index 3e7291290ba4..e76ca904549a 100644 --- a/ui/components/multichain/nft-item/index.scss +++ b/ui/components/multichain/nft-item/index.scss @@ -1,4 +1,5 @@ @use "design-system"; + .nft-item { &__container { width: 100%; @@ -24,7 +25,5 @@ padding: 0; width: 100%; height: 100%; - - } } From b88b12483cec5709e76398d03481f1d4bfa203c1 Mon Sep 17 00:00:00 2001 From: sahar-fehri Date: Thu, 27 Jun 2024 18:28:53 +0200 Subject: [PATCH 06/41] fix: fix --- ui/components/app/nft-details/nft-details.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/components/app/nft-details/nft-details.js b/ui/components/app/nft-details/nft-details.js index 92d1137c44b5..ea7c34cdaed3 100644 --- a/ui/components/app/nft-details/nft-details.js +++ b/ui/components/app/nft-details/nft-details.js @@ -282,7 +282,7 @@ export default function NftDetails({ nft }) { fontStyle={FontStyle.Normal} style={{ fontSize: '24px' }} > - {name} + {name || collection.name} Date: Thu, 27 Jun 2024 20:29:12 +0200 Subject: [PATCH 07/41] fix: fix design --- ui/components/app/nft-details/index.scss | 4 ++-- .../app/nft-details/nft-detail-information-row.js | 2 +- ui/components/app/nft-details/nft-details.js | 11 ++++++----- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/ui/components/app/nft-details/index.scss b/ui/components/app/nft-details/index.scss index fa5664abb14d..eb57dd13b0fb 100644 --- a/ui/components/app/nft-details/index.scss +++ b/ui/components/app/nft-details/index.scss @@ -8,8 +8,8 @@ $spacer-break-small: 16px; .nft-details { &__content { @include design-system.screen-lg-min { - padding-left: 128px; - padding-right: 128px; + padding-left: 192px; + padding-right: 192px; width: auto !important; } } diff --git a/ui/components/app/nft-details/nft-detail-information-row.js b/ui/components/app/nft-details/nft-detail-information-row.js index 33777b2d4319..1ca1fbe2a4f9 100644 --- a/ui/components/app/nft-details/nft-detail-information-row.js +++ b/ui/components/app/nft-details/nft-detail-information-row.js @@ -17,7 +17,7 @@ const NftDetailInformationRow = ({ title, valueColor, value, icon }) => { @@ -292,7 +292,7 @@ export default function NftDetails({ nft }) { height="20" /> - + {t('price')} @@ -558,7 +559,7 @@ export default function NftDetails({ nft }) { {t('notificationItemCollection')} @@ -593,7 +594,7 @@ export default function NftDetails({ nft }) { {t('attributes')} From cd1c81eb84f2f7c28bf1d0f009b2968d25ef5a47 Mon Sep 17 00:00:00 2001 From: sahar-fehri Date: Thu, 27 Jun 2024 22:03:09 +0200 Subject: [PATCH 08/41] fix: fix design --- ui/components/app/nft-details/nft-details.js | 76 ++++++++++++-------- 1 file changed, 48 insertions(+), 28 deletions(-) diff --git a/ui/components/app/nft-details/nft-details.js b/ui/components/app/nft-details/nft-details.js index b321613114a6..ed1e9d66043b 100644 --- a/ui/components/app/nft-details/nft-details.js +++ b/ui/components/app/nft-details/nft-details.js @@ -230,6 +230,11 @@ export default function NftDetails({ nft }) { return Math.floor(date.getTime() / 1000); }; + const hasPriceSection = getCurrentHighestBidValue() || lastSale?.timestamp; + const hasCollectionSection = + collection?.name || collection?.tokenCount || collection?.creator; + const hasAttributesSection = attributes.length !== 0; + return ( @@ -257,7 +262,7 @@ export default function NftDetails({ nft }) { display={Display.Flex} justifyContent={JustifyContent.center} marginBottom={8} - marginTop={3} + marginTop={1} > - - - {t('price')} - - + {hasPriceSection ? ( + + + {t('price')} + + + ) : null} - - - {t('notificationItemCollection')} - - + {hasCollectionSection ? ( + + + {t('notificationItemCollection')} + + + ) : null} } /> - - - {t('attributes')} - - + {hasAttributesSection ? ( + + + {t('attributes')} + + + ) : null} Date: Fri, 28 Jun 2024 00:32:17 +0200 Subject: [PATCH 09/41] fix: add patch --- ...ts-controllers-npm-33.0.0-3e7448c4cd.patch | 149 ++++++++++++++++++ package.json | 2 +- yarn.lock | 46 +++++- 3 files changed, 194 insertions(+), 3 deletions(-) create mode 100644 .yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch diff --git a/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch b/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch new file mode 100644 index 000000000000..d3d9261770e9 --- /dev/null +++ b/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch @@ -0,0 +1,149 @@ +diff --git a/dist/chunk-354SINOH.js b/dist/chunk-354SINOH.js +index 7f87776370b755bf04765b8a0ae0145bf3a0b5e6..3882dc6679b4479489e01162ccb17af13dbf8a9a 100644 +--- a/dist/chunk-354SINOH.js ++++ b/dist/chunk-354SINOH.js +@@ -2,14 +2,13 @@ + + + +- + var _chunkZ4BLTVTBjs = require('./chunk-Z4BLTVTB.js'); + + // src/NftDetectionController.ts + var _basecontroller = require('@metamask/base-controller'); + + +- ++var _chunkNYVA7ZTQjs = require('./chunk-NYVA7ZTQ.js'); + + + +@@ -25,6 +24,7 @@ var BlockaidResultType = /* @__PURE__ */ ((BlockaidResultType2) => { + BlockaidResultType2["Malicious"] = "Malicious"; + return BlockaidResultType2; + })(BlockaidResultType || {}); ++var MAX_GET_COLLECTION_BATCH_SIZE = 20; + var _disabled, _addNft, _getNftState, _inProcessNftFetchingUpdates, _onPreferencesControllerStateChange, onPreferencesControllerStateChange_fn, _getOwnerNftApi, getOwnerNftApi_fn, _getOwnerNfts, getOwnerNfts_fn; + var NftDetectionController = class extends _basecontroller.BaseController { + /** +@@ -134,6 +134,56 @@ 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)) { ++ acc.push(currValue.token.contract); ++ } ++ return acc; ++ }, []); ++ 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: '1' ++ } ++ }, ++ 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..a82d8f01f004ed876edf1f34fcb1de5f05cbbcef 100644 +--- a/dist/chunk-7JWDWDXT.js ++++ b/dist/chunk-7JWDWDXT.js +@@ -873,14 +873,33 @@ getNftInformationFromApi_fn = async function(contractAddress, tokenId) { + includeAttributes: "true", + includeLastSale: "true" + }).toString(); +- const nftInformation = await _controllerutils.fetchWithErrorHandling.call(void 0, { +- url: `${this.getNftApi()}?${urlParams}`, +- options: { +- headers: { +- Version: "1" +- } +- } +- }); ++ const getCollectionParams = new URLSearchParams({ ++ chainIds: "1", ++ contract: `${contractAddress}` ++ }).toString(); ++ const [nftInformation, collectionInformation] = await Promise.all([ ++ _controllerutils.safelyExecute.call(void 0, ++ () => _controllerutils.fetchWithErrorHandling.call(void 0, { ++ url: `${this.getNftApi()}?${urlParams}`, ++ options: { ++ headers: { ++ Version: "1" ++ } ++ } ++ }) ++ ), ++ _controllerutils.safelyExecute.call(void 0, ++ () => _controllerutils.fetchWithErrorHandling.call(void 0, { ++ url: `${_controllerutils.NFT_API_BASE_URL}/collections?${getCollectionParams}`, ++ options: { ++ headers: { ++ Version: "1" ++ } ++ } ++ }) ++ ) ++ ]); ++ + if (!nftInformation?.tokens?.[0]?.token) { + return { + name: null, +@@ -918,7 +937,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; + }; diff --git a/package.json b/package.json index f1c90da5fc8a..d423917f0eab 100644 --- a/package.json +++ b/package.json @@ -288,7 +288,7 @@ "@metamask/address-book-controller": "^4.0.1", "@metamask/announcement-controller": "^6.1.0", "@metamask/approval-controller": "^7.0.0", - "@metamask/assets-controllers": "^33.0.0", + "@metamask/assets-controllers": "patch:@metamask/assets-controllers@npm%3A33.0.0#~/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch", "@metamask/base-controller": "^5.0.1", "@metamask/browser-passworder": "^4.3.0", "@metamask/contract-metadata": "^2.5.0", diff --git a/yarn.lock b/yarn.lock index 9ef60d6f70e3..c3b267288ce0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4824,7 +4824,7 @@ __metadata: languageName: node linkType: hard -"@metamask/assets-controllers@npm:^33.0.0": +"@metamask/assets-controllers@npm:33.0.0": version: 33.0.0 resolution: "@metamask/assets-controllers@npm:33.0.0" dependencies: @@ -4866,6 +4866,48 @@ __metadata: languageName: node linkType: hard +"@metamask/assets-controllers@patch:@metamask/assets-controllers@npm%3A33.0.0#~/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch": + version: 33.0.0 + resolution: "@metamask/assets-controllers@patch:@metamask/assets-controllers@npm%3A33.0.0#~/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch::version=33.0.0&hash=58fb82" + dependencies: + "@ethereumjs/util": "npm:^8.1.0" + "@ethersproject/address": "npm:^5.7.0" + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/contracts": "npm:^5.7.0" + "@ethersproject/providers": "npm:^5.7.0" + "@metamask/abi-utils": "npm:^2.0.2" + "@metamask/accounts-controller": "npm:^17.0.0" + "@metamask/approval-controller": "npm:^7.0.0" + "@metamask/base-controller": "npm:^6.0.0" + "@metamask/contract-metadata": "npm:^2.4.0" + "@metamask/controller-utils": "npm:^11.0.0" + "@metamask/eth-query": "npm:^4.0.0" + "@metamask/keyring-controller": "npm:^17.1.0" + "@metamask/metamask-eth-abis": "npm:^3.1.1" + "@metamask/network-controller": "npm:^19.0.0" + "@metamask/polling-controller": "npm:^8.0.0" + "@metamask/preferences-controller": "npm:^13.0.0" + "@metamask/rpc-errors": "npm:^6.2.1" + "@metamask/utils": "npm:^8.3.0" + "@types/bn.js": "npm:^5.1.5" + "@types/uuid": "npm:^8.3.0" + async-mutex: "npm:^0.5.0" + bn.js: "npm:^5.2.1" + cockatiel: "npm:^3.1.2" + lodash: "npm:^4.17.21" + multiformats: "npm:^9.5.2" + single-call-balance-checker-abi: "npm:^1.0.0" + uuid: "npm:^8.3.2" + peerDependencies: + "@metamask/accounts-controller": ^17.0.0 + "@metamask/approval-controller": ^7.0.0 + "@metamask/keyring-controller": ^17.0.0 + "@metamask/network-controller": ^19.0.0 + "@metamask/preferences-controller": ^13.0.0 + checksum: 10/c0f86025ff564274946ce616f615cee5ba77771df4d88dddb02f18a538462b5bae8ef0fb224a034565195dde691d2e6870a68aef9fb24eb36bc7fa835952675e + languageName: node + linkType: hard + "@metamask/auto-changelog@npm:^2.1.0": version: 2.6.1 resolution: "@metamask/auto-changelog@npm:2.6.1" @@ -25337,7 +25379,7 @@ __metadata: "@metamask/announcement-controller": "npm:^6.1.0" "@metamask/api-specs": "npm:^0.9.3" "@metamask/approval-controller": "npm:^7.0.0" - "@metamask/assets-controllers": "npm:^33.0.0" + "@metamask/assets-controllers": "patch:@metamask/assets-controllers@npm%3A33.0.0#~/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch" "@metamask/auto-changelog": "npm:^2.1.0" "@metamask/base-controller": "npm:^5.0.1" "@metamask/browser-passworder": "npm:^4.3.0" From a1417c7a918f9b7bf0af453fbdfe55c8ff1c4eb5 Mon Sep 17 00:00:00 2001 From: sahar-fehri Date: Fri, 28 Jun 2024 01:19:41 +0200 Subject: [PATCH 10/41] fix: fix tests --- .../__snapshots__/nft-details.test.js.snap | 294 +++++++++--------- ui/components/app/nft-details/nft-details.js | 5 +- .../app/nft-details/nft-details.test.js | 9 +- 3 files changed, 152 insertions(+), 156 deletions(-) diff --git a/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap b/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap index 037f736f6829..025f8accec3e 100644 --- a/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap +++ b/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap @@ -3,186 +3,176 @@ exports[`NFT Details should match minimal props and state snapshot 1`] = `
- -
- -
-
-
-
+ +
- -
-
-
-

- MUNK #1 -

-
- # - 1 -
- -
-
-
-
-
- -
-
+ +
-
-
-
-
- -
-
-
-
- -
-
+ MUNK #1 +
+ +
+
- 0xDc738...06414 - +

+

- + Contract address +

+
+

+ 0xDc738...06414 +

+ +
+
+

+ Token ID +

+

+ 1 +

+
+
+

+ Token standard +

+

+ ERC721 +

+
+
+ +
+
+
+ Disclaimer: MetaMask pulls the media file from the source url. This url sometimes gets changed by the marketplace on which the NFT was minted. +
+
-
- Disclaimer: MetaMask pulls the media file from the source url. This url sometimes gets changed by the marketplace on which the NFT was minted. -
diff --git a/ui/components/app/nft-details/nft-details.js b/ui/components/app/nft-details/nft-details.js index ed1e9d66043b..3bd87b26b7d4 100644 --- a/ui/components/app/nft-details/nft-details.js +++ b/ui/components/app/nft-details/nft-details.js @@ -85,7 +85,7 @@ export default function NftDetails({ nft }) { topBid, attributes, } = nft; - console.log('🚀 ~ NftDetails ~ nft:', nft); + const t = useI18nContext(); const history = useHistory(); const dispatch = useDispatch(); @@ -233,7 +233,7 @@ export default function NftDetails({ nft }) { const hasPriceSection = getCurrentHighestBidValue() || lastSale?.timestamp; const hasCollectionSection = collection?.name || collection?.tokenCount || collection?.creator; - const hasAttributesSection = attributes.length !== 0; + const hasAttributesSection = attributes && attributes?.length !== 0; return ( @@ -248,6 +248,7 @@ export default function NftDetails({ nft }) { ariaLabel={t('back')} iconName={IconName.ArrowLeft} onClick={() => history.push(DEFAULT_ROUTE)} + data-testid="nft__back" /> { mockStore, ); - const backButton = queryByTestId('asset__back'); + const backButton = queryByTestId('nft__back'); fireEvent.click(backButton); @@ -141,8 +141,12 @@ describe('NFT Details', () => { }); it('should navigate to draft transaction send route with ERC721 data', async () => { + const nftProps = { + nft: nfts[5], + }; + nfts[5].isCurrentlyOwned = true; const { queryByTestId } = renderWithProvider( - , + , mockStore, ); @@ -178,6 +182,7 @@ describe('NFT Details', () => { const nftProps = { nft: nfts[1], }; + nfts[1].isCurrentlyOwned = true; const { queryByTestId } = renderWithProvider( , mockStore, From c2a56cd7eca06f1727a8392658c97f225f941e08 Mon Sep 17 00:00:00 2001 From: sahar-fehri Date: Fri, 28 Jun 2024 01:32:19 +0200 Subject: [PATCH 11/41] fix: fix locales --- app/_locales/de/messages.json | 3 --- app/_locales/el/messages.json | 3 --- app/_locales/en/messages.json | 6 ------ app/_locales/es/messages.json | 3 --- app/_locales/fr/messages.json | 3 --- app/_locales/hi/messages.json | 3 --- app/_locales/id/messages.json | 3 --- app/_locales/ja/messages.json | 3 --- app/_locales/ko/messages.json | 3 --- app/_locales/pt/messages.json | 3 --- app/_locales/ru/messages.json | 3 --- app/_locales/tl/messages.json | 3 --- app/_locales/tr/messages.json | 3 --- app/_locales/vi/messages.json | 3 --- app/_locales/zh_CN/messages.json | 3 --- 15 files changed, 48 deletions(-) diff --git a/app/_locales/de/messages.json b/app/_locales/de/messages.json index 0160c032ed88..7c82a9f32368 100644 --- a/app/_locales/de/messages.json +++ b/app/_locales/de/messages.json @@ -2324,9 +2324,6 @@ "lastConnected": { "message": "Zuletzt verbunden" }, - "lastPriceSold": { - "message": "Letzter Verkaufspreis" - }, "lastSold": { "message": "Zuletzt verkauft" }, diff --git a/app/_locales/el/messages.json b/app/_locales/el/messages.json index a53b48a7be40..8c8bd1675ee8 100644 --- a/app/_locales/el/messages.json +++ b/app/_locales/el/messages.json @@ -2324,9 +2324,6 @@ "lastConnected": { "message": "Τελευταία σύνδεση" }, - "lastPriceSold": { - "message": "Τελευταία τιμή πώλησης" - }, "lastSold": { "message": "Τελευταία πώληση" }, diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index e2785e73962b..8cdc4d6e8616 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -620,9 +620,6 @@ "attemptToCancelSwapForFree": { "message": "Attempt to cancel swap for free" }, - "attemptingConnect": { - "message": "Attempting to connect to blockchain." - }, "attributes": { "message": "Attributes" }, @@ -2530,9 +2527,6 @@ "lastConnected": { "message": "Last connected" }, - "lastPriceSold": { - "message": "Last price sold" - }, "lastSold": { "message": "Last sold" }, diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json index 244c70313634..6a379962fe07 100644 --- a/app/_locales/es/messages.json +++ b/app/_locales/es/messages.json @@ -2321,9 +2321,6 @@ "lastConnected": { "message": "Última conexión" }, - "lastPriceSold": { - "message": "Precio de la última venta" - }, "lastSold": { "message": "Última venta" }, diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json index 1b2a54f3c4c1..4b147e046772 100644 --- a/app/_locales/fr/messages.json +++ b/app/_locales/fr/messages.json @@ -2324,9 +2324,6 @@ "lastConnected": { "message": "Dernière connexion" }, - "lastPriceSold": { - "message": "Prix de la dernière vente" - }, "lastSold": { "message": "Dernière vente" }, diff --git a/app/_locales/hi/messages.json b/app/_locales/hi/messages.json index dc6318004958..95876c08a8d1 100644 --- a/app/_locales/hi/messages.json +++ b/app/_locales/hi/messages.json @@ -2321,9 +2321,6 @@ "lastConnected": { "message": "अंतिम बार जुड़ा" }, - "lastPriceSold": { - "message": "पिछली बार की बिक्री दर" - }, "lastSold": { "message": "पिछली बार बेचा गया" }, diff --git a/app/_locales/id/messages.json b/app/_locales/id/messages.json index 0faef246fd39..cfd3c64b6bff 100644 --- a/app/_locales/id/messages.json +++ b/app/_locales/id/messages.json @@ -2324,9 +2324,6 @@ "lastConnected": { "message": "Terakhir terhubung" }, - "lastPriceSold": { - "message": "Harga terakhir terjual" - }, "lastSold": { "message": "Terakhir terjual" }, diff --git a/app/_locales/ja/messages.json b/app/_locales/ja/messages.json index 4308665d7bcb..5db58d4dde3e 100644 --- a/app/_locales/ja/messages.json +++ b/app/_locales/ja/messages.json @@ -2321,9 +2321,6 @@ "lastConnected": { "message": "前回の接続" }, - "lastPriceSold": { - "message": "前回の売値" - }, "lastSold": { "message": "前回の売却" }, diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json index 464c3bf9e250..4f572fe6bf7c 100644 --- a/app/_locales/ko/messages.json +++ b/app/_locales/ko/messages.json @@ -2321,9 +2321,6 @@ "lastConnected": { "message": "마지막 연결" }, - "lastPriceSold": { - "message": "최근 판매 가격" - }, "lastSold": { "message": "최근 판매" }, diff --git a/app/_locales/pt/messages.json b/app/_locales/pt/messages.json index f201f475a4ec..018b4018e069 100644 --- a/app/_locales/pt/messages.json +++ b/app/_locales/pt/messages.json @@ -2324,9 +2324,6 @@ "lastConnected": { "message": "Última conexão" }, - "lastPriceSold": { - "message": "Último preço de venda" - }, "lastSold": { "message": "Última venda" }, diff --git a/app/_locales/ru/messages.json b/app/_locales/ru/messages.json index 3c419a274034..acbb8d7f1b30 100644 --- a/app/_locales/ru/messages.json +++ b/app/_locales/ru/messages.json @@ -2324,9 +2324,6 @@ "lastConnected": { "message": "Последнее подключение" }, - "lastPriceSold": { - "message": "Последняя цена продажи" - }, "lastSold": { "message": "Последняя продажа" }, diff --git a/app/_locales/tl/messages.json b/app/_locales/tl/messages.json index b6d454c012af..0cc3f147f74c 100644 --- a/app/_locales/tl/messages.json +++ b/app/_locales/tl/messages.json @@ -2321,9 +2321,6 @@ "lastConnected": { "message": "Huling Kumonekta" }, - "lastPriceSold": { - "message": "Huling presyong naibenta" - }, "lastSold": { "message": "Huling naibenta" }, diff --git a/app/_locales/tr/messages.json b/app/_locales/tr/messages.json index cd6508892738..f566c4be9714 100644 --- a/app/_locales/tr/messages.json +++ b/app/_locales/tr/messages.json @@ -2324,9 +2324,6 @@ "lastConnected": { "message": "Son bağlanma" }, - "lastPriceSold": { - "message": "Son satış fiyatı" - }, "lastSold": { "message": "Son satış" }, diff --git a/app/_locales/vi/messages.json b/app/_locales/vi/messages.json index ffc867cf6e76..b2f5496c3e35 100644 --- a/app/_locales/vi/messages.json +++ b/app/_locales/vi/messages.json @@ -2321,9 +2321,6 @@ "lastConnected": { "message": "Đã kết nối lần cuối" }, - "lastPriceSold": { - "message": "Giá bán gần nhất" - }, "lastSold": { "message": "Đã bán gần nhất" }, diff --git a/app/_locales/zh_CN/messages.json b/app/_locales/zh_CN/messages.json index 14c8e355be1f..862c0faa47c7 100644 --- a/app/_locales/zh_CN/messages.json +++ b/app/_locales/zh_CN/messages.json @@ -2321,9 +2321,6 @@ "lastConnected": { "message": "最后连接" }, - "lastPriceSold": { - "message": "最后售价" - }, "lastSold": { "message": "最后售出" }, From 6faee86b8be31fa8e6a10cb2f69183c9f990cd11 Mon Sep 17 00:00:00 2001 From: sahar-fehri Date: Fri, 28 Jun 2024 09:39:42 +0200 Subject: [PATCH 12/41] fix: fix tests --- .../tests/tokens/nft/view-erc1155-details.spec.js | 13 +++++-------- ui/components/app/nft-details/nft-details.js | 2 ++ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/test/e2e/tests/tokens/nft/view-erc1155-details.spec.js b/test/e2e/tests/tokens/nft/view-erc1155-details.spec.js index 1bf8d6adf286..fd06b4f36b27 100644 --- a/test/e2e/tests/tokens/nft/view-erc1155-details.spec.js +++ b/test/e2e/tests/tokens/nft/view-erc1155-details.spec.js @@ -3,6 +3,7 @@ const { withFixtures, unlockWallet, } = require('../../../helpers'); + const { SMART_CONTRACTS } = require('../../../seeder/smart-contracts'); const FixtureBuilder = require('../../../fixture-builder'); @@ -37,26 +38,22 @@ describe('View ERC1155 NFT details', function () { await driver.clickElement('.nft-item__container'); - await driver.findElement({ - css: '.asset-breadcrumb span:nth-of-type(2)', - text: 'Account 1', - }); + await driver.findElement('[data-testid="nft__back"]'); - // Check the displayed ERC1155 NFT details await driver.findElement({ - css: '.nft-details__info h4', + css: '[data-testid="nft-details__name"]', text: 'Rocks', }); await driver.findElement({ - css: '.nft-details__info h6:nth-of-type(2)', + css: '[data-testid="nft-details__description"]', text: 'This is a collection of Rock NFTs.', }); await driver.findVisibleElement('.nft-item__container'); await driver.findElement({ - css: '.nft-details__contract-wrapper', + css: '.nft-details__nft-frame', text: '0x581c3...45947', }); }, diff --git a/ui/components/app/nft-details/nft-details.js b/ui/components/app/nft-details/nft-details.js index 3bd87b26b7d4..089806e6b826 100644 --- a/ui/components/app/nft-details/nft-details.js +++ b/ui/components/app/nft-details/nft-details.js @@ -287,6 +287,7 @@ export default function NftDetails({ nft }) { color={TextColor.textDefault} fontStyle={FontStyle.Normal} style={{ fontSize: '24px' }} + data-testid="nft-details__name" > {name || collection.name} @@ -303,6 +304,7 @@ export default function NftDetails({ nft }) { variant={TextVariant.bodySm} fontWeight={FontWeight.Medium} color={TextColor.textAlternative} + data-testid="nft-details__description" > {description} From 3e3c749e4ca5b011c2ee047b33bf1c4fd202322e Mon Sep 17 00:00:00 2001 From: sahar-fehri Date: Fri, 28 Jun 2024 09:52:37 +0200 Subject: [PATCH 13/41] fix: fix tests --- .../app/nft-details/__snapshots__/nft-details.test.js.snap | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap b/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap index 025f8accec3e..25f58a8ba71c 100644 --- a/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap +++ b/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap @@ -79,6 +79,7 @@ exports[`NFT Details should match minimal props and state snapshot 1`] = ` >

MUNK #1 @@ -94,6 +95,7 @@ exports[`NFT Details should match minimal props and state snapshot 1`] = ` >

Date: Fri, 28 Jun 2024 10:29:36 +0200 Subject: [PATCH 14/41] fix: fix tests --- .../tests/tokens/nft/view-nft-details.spec.js | 32 ++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/test/e2e/tests/tokens/nft/view-nft-details.spec.js b/test/e2e/tests/tokens/nft/view-nft-details.spec.js index ef8aba0cd9b3..410bed887ab4 100644 --- a/test/e2e/tests/tokens/nft/view-nft-details.spec.js +++ b/test/e2e/tests/tokens/nft/view-nft-details.spec.js @@ -26,31 +26,27 @@ describe('View NFT details', function () { await driver.clickElement('[data-testid="account-overview__nfts-tab"]'); await driver.clickElement('.nft-item__container'); - const detailsPageTitle = await driver.findElement('.asset-breadcrumb'); - assert.equal( - await detailsPageTitle.getText(), - 'Account 1 / TestDappNFTs', - ); + await driver.findElement('[data-testid="nft__back"]'); // Check the displayed NFT details - const nftName = await driver.findElement('.nft-details__info h4'); - assert.equal(await nftName.getText(), 'Test Dapp NFTs #1'); - const nftDescription = await driver.findElement( - '.nft-details__info h6:nth-of-type(2)', - ); - assert.equal( - await nftDescription.getText(), - 'Test Dapp NFTs for testing.', - ); + await driver.findElement({ + css: '[data-testid="nft-details__name"]', + text: 'Test Dapp NFTs #1', + }); + + await driver.findElement({ + css: '[data-testid="nft-details__description"]', + text: 'Test Dapp NFTs for testing.', + }); const nftImage = await driver.findElement('.nft-item__container'); assert.equal(await nftImage.isDisplayed(), true); - const nftContract = await driver.findElement( - '.nft-details__contract-wrapper', - ); - assert.equal(await nftContract.getText(), '0x581c3...45947'); + await driver.findElement({ + css: '.nft-details__nft-frame', + text: '0x581c3...45947', + }); }, ); }); From 44800b3a92b067f074018411aa387c954a5ad539 Mon Sep 17 00:00:00 2001 From: sahar-fehri Date: Fri, 28 Jun 2024 13:49:45 +0200 Subject: [PATCH 15/41] Revert "fix: add patch" This reverts commit 588985c524016c5947fa33298c94ef8188d8bd10. --- ...ts-controllers-npm-33.0.0-3e7448c4cd.patch | 149 ------------------ package.json | 2 +- yarn.lock | 46 +----- 3 files changed, 3 insertions(+), 194 deletions(-) delete mode 100644 .yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch diff --git a/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch b/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch deleted file mode 100644 index d3d9261770e9..000000000000 --- a/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch +++ /dev/null @@ -1,149 +0,0 @@ -diff --git a/dist/chunk-354SINOH.js b/dist/chunk-354SINOH.js -index 7f87776370b755bf04765b8a0ae0145bf3a0b5e6..3882dc6679b4479489e01162ccb17af13dbf8a9a 100644 ---- a/dist/chunk-354SINOH.js -+++ b/dist/chunk-354SINOH.js -@@ -2,14 +2,13 @@ - - - -- - var _chunkZ4BLTVTBjs = require('./chunk-Z4BLTVTB.js'); - - // src/NftDetectionController.ts - var _basecontroller = require('@metamask/base-controller'); - - -- -+var _chunkNYVA7ZTQjs = require('./chunk-NYVA7ZTQ.js'); - - - -@@ -25,6 +24,7 @@ var BlockaidResultType = /* @__PURE__ */ ((BlockaidResultType2) => { - BlockaidResultType2["Malicious"] = "Malicious"; - return BlockaidResultType2; - })(BlockaidResultType || {}); -+var MAX_GET_COLLECTION_BATCH_SIZE = 20; - var _disabled, _addNft, _getNftState, _inProcessNftFetchingUpdates, _onPreferencesControllerStateChange, onPreferencesControllerStateChange_fn, _getOwnerNftApi, getOwnerNftApi_fn, _getOwnerNfts, getOwnerNfts_fn; - var NftDetectionController = class extends _basecontroller.BaseController { - /** -@@ -134,6 +134,56 @@ 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)) { -+ acc.push(currValue.token.contract); -+ } -+ return acc; -+ }, []); -+ 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: '1' -+ } -+ }, -+ 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..a82d8f01f004ed876edf1f34fcb1de5f05cbbcef 100644 ---- a/dist/chunk-7JWDWDXT.js -+++ b/dist/chunk-7JWDWDXT.js -@@ -873,14 +873,33 @@ getNftInformationFromApi_fn = async function(contractAddress, tokenId) { - includeAttributes: "true", - includeLastSale: "true" - }).toString(); -- const nftInformation = await _controllerutils.fetchWithErrorHandling.call(void 0, { -- url: `${this.getNftApi()}?${urlParams}`, -- options: { -- headers: { -- Version: "1" -- } -- } -- }); -+ const getCollectionParams = new URLSearchParams({ -+ chainIds: "1", -+ contract: `${contractAddress}` -+ }).toString(); -+ const [nftInformation, collectionInformation] = await Promise.all([ -+ _controllerutils.safelyExecute.call(void 0, -+ () => _controllerutils.fetchWithErrorHandling.call(void 0, { -+ url: `${this.getNftApi()}?${urlParams}`, -+ options: { -+ headers: { -+ Version: "1" -+ } -+ } -+ }) -+ ), -+ _controllerutils.safelyExecute.call(void 0, -+ () => _controllerutils.fetchWithErrorHandling.call(void 0, { -+ url: `${_controllerutils.NFT_API_BASE_URL}/collections?${getCollectionParams}`, -+ options: { -+ headers: { -+ Version: "1" -+ } -+ } -+ }) -+ ) -+ ]); -+ - if (!nftInformation?.tokens?.[0]?.token) { - return { - name: null, -@@ -918,7 +937,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; - }; diff --git a/package.json b/package.json index d423917f0eab..f1c90da5fc8a 100644 --- a/package.json +++ b/package.json @@ -288,7 +288,7 @@ "@metamask/address-book-controller": "^4.0.1", "@metamask/announcement-controller": "^6.1.0", "@metamask/approval-controller": "^7.0.0", - "@metamask/assets-controllers": "patch:@metamask/assets-controllers@npm%3A33.0.0#~/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch", + "@metamask/assets-controllers": "^33.0.0", "@metamask/base-controller": "^5.0.1", "@metamask/browser-passworder": "^4.3.0", "@metamask/contract-metadata": "^2.5.0", diff --git a/yarn.lock b/yarn.lock index c3b267288ce0..9ef60d6f70e3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4824,7 +4824,7 @@ __metadata: languageName: node linkType: hard -"@metamask/assets-controllers@npm:33.0.0": +"@metamask/assets-controllers@npm:^33.0.0": version: 33.0.0 resolution: "@metamask/assets-controllers@npm:33.0.0" dependencies: @@ -4866,48 +4866,6 @@ __metadata: languageName: node linkType: hard -"@metamask/assets-controllers@patch:@metamask/assets-controllers@npm%3A33.0.0#~/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch": - version: 33.0.0 - resolution: "@metamask/assets-controllers@patch:@metamask/assets-controllers@npm%3A33.0.0#~/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch::version=33.0.0&hash=58fb82" - dependencies: - "@ethereumjs/util": "npm:^8.1.0" - "@ethersproject/address": "npm:^5.7.0" - "@ethersproject/bignumber": "npm:^5.7.0" - "@ethersproject/contracts": "npm:^5.7.0" - "@ethersproject/providers": "npm:^5.7.0" - "@metamask/abi-utils": "npm:^2.0.2" - "@metamask/accounts-controller": "npm:^17.0.0" - "@metamask/approval-controller": "npm:^7.0.0" - "@metamask/base-controller": "npm:^6.0.0" - "@metamask/contract-metadata": "npm:^2.4.0" - "@metamask/controller-utils": "npm:^11.0.0" - "@metamask/eth-query": "npm:^4.0.0" - "@metamask/keyring-controller": "npm:^17.1.0" - "@metamask/metamask-eth-abis": "npm:^3.1.1" - "@metamask/network-controller": "npm:^19.0.0" - "@metamask/polling-controller": "npm:^8.0.0" - "@metamask/preferences-controller": "npm:^13.0.0" - "@metamask/rpc-errors": "npm:^6.2.1" - "@metamask/utils": "npm:^8.3.0" - "@types/bn.js": "npm:^5.1.5" - "@types/uuid": "npm:^8.3.0" - async-mutex: "npm:^0.5.0" - bn.js: "npm:^5.2.1" - cockatiel: "npm:^3.1.2" - lodash: "npm:^4.17.21" - multiformats: "npm:^9.5.2" - single-call-balance-checker-abi: "npm:^1.0.0" - uuid: "npm:^8.3.2" - peerDependencies: - "@metamask/accounts-controller": ^17.0.0 - "@metamask/approval-controller": ^7.0.0 - "@metamask/keyring-controller": ^17.0.0 - "@metamask/network-controller": ^19.0.0 - "@metamask/preferences-controller": ^13.0.0 - checksum: 10/c0f86025ff564274946ce616f615cee5ba77771df4d88dddb02f18a538462b5bae8ef0fb224a034565195dde691d2e6870a68aef9fb24eb36bc7fa835952675e - languageName: node - linkType: hard - "@metamask/auto-changelog@npm:^2.1.0": version: 2.6.1 resolution: "@metamask/auto-changelog@npm:2.6.1" @@ -25379,7 +25337,7 @@ __metadata: "@metamask/announcement-controller": "npm:^6.1.0" "@metamask/api-specs": "npm:^0.9.3" "@metamask/approval-controller": "npm:^7.0.0" - "@metamask/assets-controllers": "patch:@metamask/assets-controllers@npm%3A33.0.0#~/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch" + "@metamask/assets-controllers": "npm:^33.0.0" "@metamask/auto-changelog": "npm:^2.1.0" "@metamask/base-controller": "npm:^5.0.1" "@metamask/browser-passworder": "npm:^4.3.0" From 676f670ec354ea99322621b5c1e15bf66184d6b5 Mon Sep 17 00:00:00 2001 From: sahar-fehri Date: Fri, 28 Jun 2024 14:05:47 +0200 Subject: [PATCH 16/41] fix: update patch --- ...ts-controllers-npm-33.0.0-3e7448c4cd.patch | 175 ++++++++++++++++++ package.json | 2 +- yarn.lock | 46 ++++- 3 files changed, 220 insertions(+), 3 deletions(-) create mode 100644 .yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch diff --git a/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch b/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch new file mode 100644 index 000000000000..2acf99542cf4 --- /dev/null +++ b/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch @@ -0,0 +1,175 @@ +diff --git a/dist/chunk-354SINOH.js b/dist/chunk-354SINOH.js +index 7f87776370b755bf04765b8a0ae0145bf3a0b5e6..3b6d011fd5953abea392f0723dfedd52bf061a44 100644 +--- a/dist/chunk-354SINOH.js ++++ b/dist/chunk-354SINOH.js +@@ -10,7 +10,7 @@ var _basecontroller = require('@metamask/base-controller'); + + + +- ++var _chunkNYVA7ZTQjs = require('./chunk-NYVA7ZTQ.js'); + + + +@@ -25,6 +25,7 @@ var BlockaidResultType = /* @__PURE__ */ ((BlockaidResultType2) => { + BlockaidResultType2["Malicious"] = "Malicious"; + return BlockaidResultType2; + })(BlockaidResultType || {}); ++var MAX_GET_COLLECTION_BATCH_SIZE = 20; + var _disabled, _addNft, _getNftState, _inProcessNftFetchingUpdates, _onPreferencesControllerStateChange, onPreferencesControllerStateChange_fn, _getOwnerNftApi, getOwnerNftApi_fn, _getOwnerNfts, getOwnerNfts_fn; + var NftDetectionController = class extends _basecontroller.BaseController { + /** +@@ -134,6 +135,56 @@ 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)) { ++ acc.push(currValue.token.contract); ++ } ++ return acc; ++ }, []); ++ 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: '1' ++ } ++ }, ++ 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..d4d13c8488844a7c419bf0ae16a0c7f31800216a 100644 +--- a/dist/chunk-7JWDWDXT.js ++++ b/dist/chunk-7JWDWDXT.js +@@ -873,14 +873,32 @@ getNftInformationFromApi_fn = async function(contractAddress, tokenId) { + includeAttributes: "true", + includeLastSale: "true" + }).toString(); +- const nftInformation = await _controllerutils.fetchWithErrorHandling.call(void 0, { +- url: `${this.getNftApi()}?${urlParams}`, +- options: { +- headers: { +- Version: "1" +- } +- } +- }); ++ const getCollectionParams = new URLSearchParams({ ++ chainIds: "1", ++ contract: `${contractAddress}` ++ }).toString(); ++ const [nftInformation, collectionInformation] = await Promise.all([ ++ _controllerutils.safelyExecute.call(void 0, ++ () => _controllerutils.fetchWithErrorHandling.call(void 0, { ++ url: `${this.getNftApi()}?${urlParams}`, ++ options: { ++ headers: { ++ Version: "1" ++ } ++ } ++ }) ++ ), ++ _controllerutils.safelyExecute.call(void 0, ++ () => _controllerutils.fetchWithErrorHandling.call(void 0, { ++ url: `${_controllerutils.NFT_API_BASE_URL}/collections?${getCollectionParams}`, ++ options: { ++ headers: { ++ Version: "1" ++ } ++ } ++ }) ++ ) ++ ]); + if (!nftInformation?.tokens?.[0]?.token) { + return { + name: null, +@@ -918,7 +936,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 +1122,8 @@ addIndividualNft_fn = async function(tokenAddress, tokenId, nftMetadata, nftCont + nftMetadata, + existingEntry + ); +- if (!differentMetadata && existingEntry.isCurrentlyOwned) { ++ const hasNewFields = _chunkNYVA7ZTQjs.hasNewCollectionFields.call(void 0, 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/package.json b/package.json index f1c90da5fc8a..d423917f0eab 100644 --- a/package.json +++ b/package.json @@ -288,7 +288,7 @@ "@metamask/address-book-controller": "^4.0.1", "@metamask/announcement-controller": "^6.1.0", "@metamask/approval-controller": "^7.0.0", - "@metamask/assets-controllers": "^33.0.0", + "@metamask/assets-controllers": "patch:@metamask/assets-controllers@npm%3A33.0.0#~/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch", "@metamask/base-controller": "^5.0.1", "@metamask/browser-passworder": "^4.3.0", "@metamask/contract-metadata": "^2.5.0", diff --git a/yarn.lock b/yarn.lock index 9ef60d6f70e3..f7c6de9fcd41 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4824,7 +4824,7 @@ __metadata: languageName: node linkType: hard -"@metamask/assets-controllers@npm:^33.0.0": +"@metamask/assets-controllers@npm:33.0.0": version: 33.0.0 resolution: "@metamask/assets-controllers@npm:33.0.0" dependencies: @@ -4866,6 +4866,48 @@ __metadata: languageName: node linkType: hard +"@metamask/assets-controllers@patch:@metamask/assets-controllers@npm%3A33.0.0#~/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch": + version: 33.0.0 + resolution: "@metamask/assets-controllers@patch:@metamask/assets-controllers@npm%3A33.0.0#~/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch::version=33.0.0&hash=f4b08f" + dependencies: + "@ethereumjs/util": "npm:^8.1.0" + "@ethersproject/address": "npm:^5.7.0" + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/contracts": "npm:^5.7.0" + "@ethersproject/providers": "npm:^5.7.0" + "@metamask/abi-utils": "npm:^2.0.2" + "@metamask/accounts-controller": "npm:^17.0.0" + "@metamask/approval-controller": "npm:^7.0.0" + "@metamask/base-controller": "npm:^6.0.0" + "@metamask/contract-metadata": "npm:^2.4.0" + "@metamask/controller-utils": "npm:^11.0.0" + "@metamask/eth-query": "npm:^4.0.0" + "@metamask/keyring-controller": "npm:^17.1.0" + "@metamask/metamask-eth-abis": "npm:^3.1.1" + "@metamask/network-controller": "npm:^19.0.0" + "@metamask/polling-controller": "npm:^8.0.0" + "@metamask/preferences-controller": "npm:^13.0.0" + "@metamask/rpc-errors": "npm:^6.2.1" + "@metamask/utils": "npm:^8.3.0" + "@types/bn.js": "npm:^5.1.5" + "@types/uuid": "npm:^8.3.0" + async-mutex: "npm:^0.5.0" + bn.js: "npm:^5.2.1" + cockatiel: "npm:^3.1.2" + lodash: "npm:^4.17.21" + multiformats: "npm:^9.5.2" + single-call-balance-checker-abi: "npm:^1.0.0" + uuid: "npm:^8.3.2" + peerDependencies: + "@metamask/accounts-controller": ^17.0.0 + "@metamask/approval-controller": ^7.0.0 + "@metamask/keyring-controller": ^17.0.0 + "@metamask/network-controller": ^19.0.0 + "@metamask/preferences-controller": ^13.0.0 + checksum: 10/a66fca82393083b3bf49c43519386113f52f2579d0ba08f52785f7ffe86d763a46d898fc857f282e5352e38128c8cf1120a2b7417f2643576793143c1de3fe01 + languageName: node + linkType: hard + "@metamask/auto-changelog@npm:^2.1.0": version: 2.6.1 resolution: "@metamask/auto-changelog@npm:2.6.1" @@ -25337,7 +25379,7 @@ __metadata: "@metamask/announcement-controller": "npm:^6.1.0" "@metamask/api-specs": "npm:^0.9.3" "@metamask/approval-controller": "npm:^7.0.0" - "@metamask/assets-controllers": "npm:^33.0.0" + "@metamask/assets-controllers": "patch:@metamask/assets-controllers@npm%3A33.0.0#~/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch" "@metamask/auto-changelog": "npm:^2.1.0" "@metamask/base-controller": "npm:^5.0.1" "@metamask/browser-passworder": "npm:^4.3.0" From 1fb5fb435c94d03d23d48e6454773b4dff73047c Mon Sep 17 00:00:00 2001 From: sahar-fehri Date: Sun, 30 Jun 2024 23:07:22 +0200 Subject: [PATCH 17/41] fix: make contract and creator address clickable --- ui/components/app/nft-details/index.scss | 5 + .../nft-detail-information-frame.js | 13 ++- .../nft-details/nft-detail-information-row.js | 27 +++-- ui/components/app/nft-details/nft-details.js | 104 +++++++++++++----- ui/components/multichain/nft-item/index.scss | 2 + 5 files changed, 114 insertions(+), 37 deletions(-) diff --git a/ui/components/app/nft-details/index.scss b/ui/components/app/nft-details/index.scss index eb57dd13b0fb..f402bb93d60b 100644 --- a/ui/components/app/nft-details/index.scss +++ b/ui/components/app/nft-details/index.scss @@ -14,6 +14,11 @@ $spacer-break-small: 16px; } } + &__addressButton{ + background-color: transparent; + padding-right: 0px; + } + &__nft-image { @include design-system.screen-sm-max { max-width: 144px; diff --git a/ui/components/app/nft-details/nft-detail-information-frame.js b/ui/components/app/nft-details/nft-detail-information-frame.js index c51e20858d77..50890460b5a5 100644 --- a/ui/components/app/nft-details/nft-detail-information-frame.js +++ b/ui/components/app/nft-details/nft-detail-information-frame.js @@ -11,6 +11,7 @@ import { const NftDetailInformationFrame = ({ title, value, + buttonAddressValue, frameClassname, frameTextTitleProps, frameTextTitleStyle, @@ -30,9 +31,14 @@ const NftDetailInformationFrame = ({ justifyContent={JustifyContent.center} alignItems={AlignItems.center} > - - {value} - + {' '} + {buttonAddressValue ? ( + { ...buttonAddressValue } + ) : ( + + {value} + + )} {icon} ) : ( @@ -53,6 +59,7 @@ NftDetailInformationFrame.propTypes = { frameTextTitleStyle: PropTypes.object, frameTextValueStyle: PropTypes.object, icon: PropTypes.node, + buttonAddressValue: PropTypes.node, }; export default NftDetailInformationFrame; diff --git a/ui/components/app/nft-details/nft-detail-information-row.js b/ui/components/app/nft-details/nft-detail-information-row.js index 1ca1fbe2a4f9..a4a3dd526398 100644 --- a/ui/components/app/nft-details/nft-detail-information-row.js +++ b/ui/components/app/nft-details/nft-detail-information-row.js @@ -9,8 +9,14 @@ import { TextVariant, } from '../../../helpers/constants/design-system'; -const NftDetailInformationRow = ({ title, valueColor, value, icon }) => { - if (!value) { +const NftDetailInformationRow = ({ + title, + valueColor, + value, + icon, + buttonAddressValue, +}) => { + if (!value && !buttonAddressValue) { return null; } return ( @@ -27,12 +33,16 @@ const NftDetailInformationRow = ({ title, valueColor, value, icon }) => { {icon ? ( - - {value} - + {buttonAddressValue ? ( + { ...buttonAddressValue } + ) : ( + + {value} + + )} {icon} ) : ( @@ -52,6 +62,7 @@ NftDetailInformationRow.propTypes = { valueColor: TextColor, value: PropTypes.string, icon: PropTypes.node, + buttonAddressValue: PropTypes.node, }; export default NftDetailInformationRow; diff --git a/ui/components/app/nft-details/nft-details.js b/ui/components/app/nft-details/nft-details.js index 089806e6b826..777240406b2a 100644 --- a/ui/components/app/nft-details/nft-details.js +++ b/ui/components/app/nft-details/nft-details.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import { useDispatch, useSelector } from 'react-redux'; import { useHistory } from 'react-router-dom'; import { isEqual } from 'lodash'; +import { getTokenTrackerLink, getAccountLink } from '@metamask/etherscan-link'; import { TextColor, IconColor, @@ -66,6 +67,7 @@ import { Content, Footer, Page } from '../../multichain/pages/page'; import { formatCurrency } from '../../../helpers/utils/confirm-tx.util'; import { getPricePrecision } from '../../../pages/asset/util'; import { ShowMore } from '../snaps/show-more'; +import { SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../shared/constants/swaps'; import NftDetailInformationRow from './nft-detail-information-row'; import NftDetailInformationFrame from './nft-detail-information-frame'; @@ -235,6 +237,19 @@ export default function NftDetails({ nft }) { collection?.name || collection?.tokenCount || collection?.creator; const hasAttributesSection = attributes && attributes?.length !== 0; + const blockExplorerTokenLink = (tokenAddress) => { + return getTokenTrackerLink( + tokenAddress, + chainId, + null, // no networkId + null, // no holderAddress + { + blockExplorerUrl: + SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId] ?? null, + }, + ); + }; + return ( @@ -280,25 +295,30 @@ export default function NftDetails({ nft }) { - - - {name || collection.name} - - - + {name || collection.name ? ( + + + {name || collection.name} + + {collection.openseaVerificationStatus === 'verified' ? ( + + ) : null} + + ) : null} + { + global.platform.openTab({ + url: blockExplorerTokenLink(address), + }); + }} + > + + {shortenAddress(address)} + + + } icon={ { + global.platform.openTab({ + url: getAccountLink(collection?.creator, chainId), + }); + }} + > + + {shortenAddress(collection?.creator)} + + + ) : null + } valueColor={TextColor.primaryDefault} icon={ Date: Mon, 1 Jul 2024 17:22:49 +0200 Subject: [PATCH 18/41] fix: fix --- ui/components/app/nft-details/index.scss | 2 -- 1 file changed, 2 deletions(-) diff --git a/ui/components/app/nft-details/index.scss b/ui/components/app/nft-details/index.scss index f402bb93d60b..3a93254bf3b5 100644 --- a/ui/components/app/nft-details/index.scss +++ b/ui/components/app/nft-details/index.scss @@ -23,12 +23,10 @@ $spacer-break-small: 16px; @include design-system.screen-sm-max { max-width: 144px; flex: 0 0 144px; - height: 144px; } max-width: 144px; flex: 0 0 144px; - height: 144px; } &__nft-frame { From b5827ab6a4f9fd9dca302216342e9412982afa46 Mon Sep 17 00:00:00 2001 From: sahar-fehri Date: Mon, 1 Jul 2024 18:43:07 +0200 Subject: [PATCH 19/41] fix: fix showMore css --- ui/components/app/nft-details/index.scss | 37 ++++++++++- .../app/nft-details/nft-detail-description.js | 63 +++++++++++++++++++ ui/components/app/nft-details/nft-details.js | 14 +---- .../app/snaps/show-more/show-more.js | 6 +- ui/components/multichain/nft-item/index.scss | 2 - 5 files changed, 105 insertions(+), 17 deletions(-) create mode 100644 ui/components/app/nft-details/nft-detail-description.js diff --git a/ui/components/app/nft-details/index.scss b/ui/components/app/nft-details/index.scss index 3a93254bf3b5..0032e9a1fa0c 100644 --- a/ui/components/app/nft-details/index.scss +++ b/ui/components/app/nft-details/index.scss @@ -5,6 +5,18 @@ $link-title-width: 160px; $spacer-break-large: 24px; $spacer-break-small: 16px; +.buttonDescriptionContainer { + position: absolute; + bottom: 0; + right: 0; + // Avoids see-through with muted colors + background: linear-gradient(90deg, transparent 0%, var(--color-background-default) 33%); + + @include design-system.screen-md-min { + bottom: 3px; + } +} + .nft-details { &__content { @include design-system.screen-lg-min { @@ -14,9 +26,9 @@ $spacer-break-small: 16px; } } - &__addressButton{ + &__addressButton { background-color: transparent; - padding-right: 0px; + padding-right: 0; } &__nft-image { @@ -29,6 +41,27 @@ $spacer-break-small: 16px; flex: 0 0 144px; } + &__show-more { + max-height: 2.5rem; + + &__buttonContainer { + position: 'absolute'; + bottom: 0; + right: 0; + // Avoids see-through with muted colors + background: linear-gradient(90deg, transparent 0%, var(--color-background-default) 33%); + } + + @include design-system.screen-md-min { + max-height: 3rem; + } + + &__button { + background: linear-gradient(90deg, transparent 0%, var(--color-background-default) 33%); + vertical-align: baseline; + } + } + &__nft-frame { flex: 1 0 33%; padding-top: 12px; diff --git a/ui/components/app/nft-details/nft-detail-description.js b/ui/components/app/nft-details/nft-detail-description.js new file mode 100644 index 000000000000..c510574910fc --- /dev/null +++ b/ui/components/app/nft-details/nft-detail-description.js @@ -0,0 +1,63 @@ +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; + +import useIsOverflowing from '../../../hooks/snaps/useIsOverflowing'; +import { Box, Button, ButtonVariant, Text } from '../../component-library'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import { + FontWeight, + TextColor, + TextVariant, +} from '../../../helpers/constants/design-system'; + +const NftDetailDescription = ({ value }) => { + const t = useI18nContext(); + const { contentRef, isOverflowing } = useIsOverflowing(); + const [isOpen, setIsOpen] = useState(false); + + const shouldDisplayButton = !isOpen && isOverflowing; + + const handleClick = (e) => { + e.stopPropagation(); + setIsOpen(true); + }; + + return ( + + + {value} + + {shouldDisplayButton && ( + + + + )} + + ); +}; + +NftDetailDescription.propTypes = { + value: PropTypes.string, +}; +export default NftDetailDescription; diff --git a/ui/components/app/nft-details/nft-details.js b/ui/components/app/nft-details/nft-details.js index 777240406b2a..28fd7f05b619 100644 --- a/ui/components/app/nft-details/nft-details.js +++ b/ui/components/app/nft-details/nft-details.js @@ -66,10 +66,10 @@ import { MetaMetricsContext } from '../../../contexts/metametrics'; import { Content, Footer, Page } from '../../multichain/pages/page'; import { formatCurrency } from '../../../helpers/utils/confirm-tx.util'; import { getPricePrecision } from '../../../pages/asset/util'; -import { ShowMore } from '../snaps/show-more'; import { SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../shared/constants/swaps'; import NftDetailInformationRow from './nft-detail-information-row'; import NftDetailInformationFrame from './nft-detail-information-frame'; +import NftDetailDescription from './nft-detail-description'; export default function NftDetails({ nft }) { const { @@ -319,16 +319,8 @@ export default function NftDetails({ nft }) { ) : null} - - - {description} - - + + { +export const ShowMore = ({ children, className = '', ...props }) => { const t = useI18nContext(); const { contentRef, isOverflowing } = useIsOverflowing(); const [isOpen, setIsOpen] = useState(false); @@ -23,7 +24,7 @@ export const ShowMore = ({ children, ...props }) => { return ( { ShowMore.propTypes = { children: PropTypes.node, buttonBackground: PropTypes.string, + className: PropTypes.string, }; diff --git a/ui/components/multichain/nft-item/index.scss b/ui/components/multichain/nft-item/index.scss index 24f8f0a8ffb0..24fe75b0238a 100644 --- a/ui/components/multichain/nft-item/index.scss +++ b/ui/components/multichain/nft-item/index.scss @@ -3,7 +3,6 @@ .nft-item { &__container { width: 100%; - height: 100%; padding: 0; border-radius: 8px; cursor: unset; @@ -26,6 +25,5 @@ padding: 0; width: 100%; height: 100%; - } } From a7c45cf38e08b40b348227405cc1503c3138c496 Mon Sep 17 00:00:00 2001 From: sahar-fehri Date: Tue, 2 Jul 2024 12:23:59 +0200 Subject: [PATCH 20/41] fix: update patch --- ...ts-controllers-npm-34.0.0-ea790e90a1.patch | 123 ++++++++++++++++++ package.json | 2 +- yarn.lock | 14 +- 3 files changed, 131 insertions(+), 8 deletions(-) create mode 100644 .yarn/patches/@metamask-assets-controllers-npm-34.0.0-ea790e90a1.patch diff --git a/.yarn/patches/@metamask-assets-controllers-npm-34.0.0-ea790e90a1.patch b/.yarn/patches/@metamask-assets-controllers-npm-34.0.0-ea790e90a1.patch new file mode 100644 index 000000000000..90d312479247 --- /dev/null +++ b/.yarn/patches/@metamask-assets-controllers-npm-34.0.0-ea790e90a1.patch @@ -0,0 +1,123 @@ +diff --git a/dist/chunk-354SINOH.js b/dist/chunk-354SINOH.js +index 7f87776370b755bf04765b8a0ae0145bf3a0b5e6..e79edab438840d5cceb06a23097eacee126c8e26 100644 +--- a/dist/chunk-354SINOH.js ++++ b/dist/chunk-354SINOH.js +@@ -8,7 +8,7 @@ var _chunkZ4BLTVTBjs = require('./chunk-Z4BLTVTB.js'); + // src/NftDetectionController.ts + var _basecontroller = require('@metamask/base-controller'); + +- ++var _chunkNYVA7ZTQjs = require('./chunk-NYVA7ZTQ.js'); + + + +@@ -25,6 +25,7 @@ var BlockaidResultType = /* @__PURE__ */ ((BlockaidResultType2) => { + BlockaidResultType2["Malicious"] = "Malicious"; + return BlockaidResultType2; + })(BlockaidResultType || {}); ++var MAX_GET_COLLECTION_BATCH_SIZE = 20; + var _disabled, _addNft, _getNftState, _inProcessNftFetchingUpdates, _onPreferencesControllerStateChange, onPreferencesControllerStateChange_fn, _getOwnerNftApi, getOwnerNftApi_fn, _getOwnerNfts, getOwnerNfts_fn; + var NftDetectionController = class extends _basecontroller.BaseController { + /** +@@ -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..a354e4563d4307ff1e176337aeb8ffd614834c27 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; + }; diff --git a/package.json b/package.json index f9dbb8dbeb77..2c8d01646bc4 100644 --- a/package.json +++ b/package.json @@ -289,7 +289,7 @@ "@metamask/address-book-controller": "^4.0.1", "@metamask/announcement-controller": "^6.1.0", "@metamask/approval-controller": "^7.0.0", - "@metamask/assets-controllers": "^34.0.0", + "@metamask/assets-controllers": "patch:@metamask/assets-controllers@npm%3A34.0.0#~/.yarn/patches/@metamask-assets-controllers-npm-34.0.0-ea790e90a1.patch", "@metamask/base-controller": "^5.0.1", "@metamask/browser-passworder": "^4.3.0", "@metamask/contract-metadata": "^2.5.0", diff --git a/yarn.lock b/yarn.lock index e908172af74a..a07332caf7d5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4825,7 +4825,7 @@ __metadata: languageName: node linkType: hard -"@metamask/assets-controllers@npm:^34.0.0": +"@metamask/assets-controllers@npm:34.0.0": version: 34.0.0 resolution: "@metamask/assets-controllers@npm:34.0.0" dependencies: @@ -4867,9 +4867,9 @@ __metadata: languageName: node linkType: hard -"@metamask/assets-controllers@patch:@metamask/assets-controllers@npm%3A33.0.0#~/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch": - version: 33.0.0 - resolution: "@metamask/assets-controllers@patch:@metamask/assets-controllers@npm%3A33.0.0#~/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch::version=33.0.0&hash=f4b08f" +"@metamask/assets-controllers@patch:@metamask/assets-controllers@npm%3A34.0.0#~/.yarn/patches/@metamask-assets-controllers-npm-34.0.0-ea790e90a1.patch": + version: 34.0.0 + resolution: "@metamask/assets-controllers@patch:@metamask/assets-controllers@npm%3A34.0.0#~/.yarn/patches/@metamask-assets-controllers-npm-34.0.0-ea790e90a1.patch::version=34.0.0&hash=b927d9" dependencies: "@ethereumjs/util": "npm:^8.1.0" "@ethersproject/address": "npm:^5.7.0" @@ -4877,7 +4877,7 @@ __metadata: "@ethersproject/contracts": "npm:^5.7.0" "@ethersproject/providers": "npm:^5.7.0" "@metamask/abi-utils": "npm:^2.0.2" - "@metamask/accounts-controller": "npm:^17.0.0" + "@metamask/accounts-controller": "npm:^17.1.0" "@metamask/approval-controller": "npm:^7.0.0" "@metamask/base-controller": "npm:^6.0.0" "@metamask/contract-metadata": "npm:^2.4.0" @@ -4905,7 +4905,7 @@ __metadata: "@metamask/keyring-controller": ^17.0.0 "@metamask/network-controller": ^19.0.0 "@metamask/preferences-controller": ^13.0.0 - checksum: 10/a66fca82393083b3bf49c43519386113f52f2579d0ba08f52785f7ffe86d763a46d898fc857f282e5352e38128c8cf1120a2b7417f2643576793143c1de3fe01 + checksum: 10/9e6a829032e00d2072409137c55dce54c74fab7559cfa9e3e45627298262be2f68faa0f9d15a0c25549fc016edf2c849722359824255183b5343b1bcbee36c96 languageName: node linkType: hard @@ -25213,7 +25213,7 @@ __metadata: "@metamask/announcement-controller": "npm:^6.1.0" "@metamask/api-specs": "npm:^0.9.3" "@metamask/approval-controller": "npm:^7.0.0" - "@metamask/assets-controllers": "npm:^34.0.0" + "@metamask/assets-controllers": "patch:@metamask/assets-controllers@npm%3A34.0.0#~/.yarn/patches/@metamask-assets-controllers-npm-34.0.0-ea790e90a1.patch" "@metamask/auto-changelog": "npm:^2.1.0" "@metamask/base-controller": "npm:^5.0.1" "@metamask/browser-passworder": "npm:^4.3.0" From 0bc7eddf6467f8dde228a1eca06449375881aecc Mon Sep 17 00:00:00 2001 From: sahar-fehri Date: Tue, 2 Jul 2024 12:25:05 +0200 Subject: [PATCH 21/41] fix: delete unused patch --- ...ts-controllers-npm-33.0.0-3e7448c4cd.patch | 175 ------------------ 1 file changed, 175 deletions(-) delete mode 100644 .yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch diff --git a/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch b/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch deleted file mode 100644 index 2acf99542cf4..000000000000 --- a/.yarn/patches/@metamask-assets-controllers-npm-33.0.0-3e7448c4cd.patch +++ /dev/null @@ -1,175 +0,0 @@ -diff --git a/dist/chunk-354SINOH.js b/dist/chunk-354SINOH.js -index 7f87776370b755bf04765b8a0ae0145bf3a0b5e6..3b6d011fd5953abea392f0723dfedd52bf061a44 100644 ---- a/dist/chunk-354SINOH.js -+++ b/dist/chunk-354SINOH.js -@@ -10,7 +10,7 @@ var _basecontroller = require('@metamask/base-controller'); - - - -- -+var _chunkNYVA7ZTQjs = require('./chunk-NYVA7ZTQ.js'); - - - -@@ -25,6 +25,7 @@ var BlockaidResultType = /* @__PURE__ */ ((BlockaidResultType2) => { - BlockaidResultType2["Malicious"] = "Malicious"; - return BlockaidResultType2; - })(BlockaidResultType || {}); -+var MAX_GET_COLLECTION_BATCH_SIZE = 20; - var _disabled, _addNft, _getNftState, _inProcessNftFetchingUpdates, _onPreferencesControllerStateChange, onPreferencesControllerStateChange_fn, _getOwnerNftApi, getOwnerNftApi_fn, _getOwnerNfts, getOwnerNfts_fn; - var NftDetectionController = class extends _basecontroller.BaseController { - /** -@@ -134,6 +135,56 @@ 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)) { -+ acc.push(currValue.token.contract); -+ } -+ return acc; -+ }, []); -+ 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: '1' -+ } -+ }, -+ 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..d4d13c8488844a7c419bf0ae16a0c7f31800216a 100644 ---- a/dist/chunk-7JWDWDXT.js -+++ b/dist/chunk-7JWDWDXT.js -@@ -873,14 +873,32 @@ getNftInformationFromApi_fn = async function(contractAddress, tokenId) { - includeAttributes: "true", - includeLastSale: "true" - }).toString(); -- const nftInformation = await _controllerutils.fetchWithErrorHandling.call(void 0, { -- url: `${this.getNftApi()}?${urlParams}`, -- options: { -- headers: { -- Version: "1" -- } -- } -- }); -+ const getCollectionParams = new URLSearchParams({ -+ chainIds: "1", -+ contract: `${contractAddress}` -+ }).toString(); -+ const [nftInformation, collectionInformation] = await Promise.all([ -+ _controllerutils.safelyExecute.call(void 0, -+ () => _controllerutils.fetchWithErrorHandling.call(void 0, { -+ url: `${this.getNftApi()}?${urlParams}`, -+ options: { -+ headers: { -+ Version: "1" -+ } -+ } -+ }) -+ ), -+ _controllerutils.safelyExecute.call(void 0, -+ () => _controllerutils.fetchWithErrorHandling.call(void 0, { -+ url: `${_controllerutils.NFT_API_BASE_URL}/collections?${getCollectionParams}`, -+ options: { -+ headers: { -+ Version: "1" -+ } -+ } -+ }) -+ ) -+ ]); - if (!nftInformation?.tokens?.[0]?.token) { - return { - name: null, -@@ -918,7 +936,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 +1122,8 @@ addIndividualNft_fn = async function(tokenAddress, tokenId, nftMetadata, nftCont - nftMetadata, - existingEntry - ); -- if (!differentMetadata && existingEntry.isCurrentlyOwned) { -+ const hasNewFields = _chunkNYVA7ZTQjs.hasNewCollectionFields.call(void 0, 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 From fb9922a525e0d55776e96334d5d9bc864cc630d8 Mon Sep 17 00:00:00 2001 From: sahar-fehri Date: Tue, 2 Jul 2024 15:05:28 +0200 Subject: [PATCH 22/41] fix: add showLess button --- app/_locales/en/messages.json | 3 + .../app/nft-details/nft-detail-description.js | 59 +++++++++++-------- 2 files changed, 39 insertions(+), 23 deletions(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index b08018f8a101..f8813bb8a91d 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -4711,6 +4711,9 @@ "showIncomingTransactionsExplainer": { "message": "This relies on different third-party APIs for each network, which expose your Ethereum address and your IP address." }, + "showLess": { + "message": "Show less" + }, "showMore": { "message": "Show more" }, diff --git a/ui/components/app/nft-details/nft-detail-description.js b/ui/components/app/nft-details/nft-detail-description.js index c510574910fc..2d03e76cb1c9 100644 --- a/ui/components/app/nft-details/nft-detail-description.js +++ b/ui/components/app/nft-details/nft-detail-description.js @@ -19,41 +19,54 @@ const NftDetailDescription = ({ value }) => { const handleClick = (e) => { e.stopPropagation(); - setIsOpen(true); + setIsOpen(!isOpen); }; return ( - - + - {value} - - {shouldDisplayButton && ( - + + {value} + + {shouldDisplayButton && ( + + + + )} + + {isOpen && ( + )} - + ); }; From ab336d4f49615cc3ea62bb413c39dcea7e6db6cd Mon Sep 17 00:00:00 2001 From: sahar-fehri Date: Tue, 2 Jul 2024 15:12:49 +0200 Subject: [PATCH 23/41] fix: add storybook for nft detail description --- .../nft-detail-description.stories.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 ui/components/app/nft-details/nft-detail-description.stories.js diff --git a/ui/components/app/nft-details/nft-detail-description.stories.js b/ui/components/app/nft-details/nft-detail-description.stories.js new file mode 100644 index 000000000000..10c3482d1c17 --- /dev/null +++ b/ui/components/app/nft-details/nft-detail-description.stories.js @@ -0,0 +1,16 @@ +import React from 'react'; +import NftDetailDescription from './nft-detail-description'; + +export default { + title: 'Components/App/NftDetailDescription', + args: { + value: + 'At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.', + }, +}; + +export const DefaultStory = (args) => { + return ; +}; + +DefaultStory.storyName = 'Default'; From baae0255bfdebff66f6c433f27c65e20a925e470 Mon Sep 17 00:00:00 2001 From: sahar-fehri Date: Tue, 2 Jul 2024 15:18:57 +0200 Subject: [PATCH 24/41] fix: fix --- ui/components/app/nft-details/nft-details.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/components/app/nft-details/nft-details.js b/ui/components/app/nft-details/nft-details.js index 28fd7f05b619..7f42386882e0 100644 --- a/ui/components/app/nft-details/nft-details.js +++ b/ui/components/app/nft-details/nft-details.js @@ -307,7 +307,7 @@ export default function NftDetails({ nft }) { > {name || collection.name} - {collection.openseaVerificationStatus === 'verified' ? ( + {collection?.openseaVerificationStatus === 'verified' ? ( Date: Tue, 2 Jul 2024 16:18:54 +0200 Subject: [PATCH 25/41] fix: fix css --- ui/components/app/nft-details/index.scss | 22 +++++++++++--------- ui/components/app/nft-details/nft-details.js | 2 +- ui/components/multichain/nft-item/index.scss | 3 --- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/ui/components/app/nft-details/index.scss b/ui/components/app/nft-details/index.scss index 0032e9a1fa0c..f68de89c78f5 100644 --- a/ui/components/app/nft-details/index.scss +++ b/ui/components/app/nft-details/index.scss @@ -1,6 +1,6 @@ @use "design-system"; -$card-width-break-large: 224px; +$card-width-break-large: 144px; $link-title-width: 160px; $spacer-break-large: 24px; $spacer-break-small: 16px; @@ -18,6 +18,17 @@ $spacer-break-small: 16px; } .nft-details { + &__nft-item { + margin-bottom: $spacer-break-small; + + @include design-system.screen-sm-min { + margin-bottom: 0; + max-width: $card-width-break-large; + flex: 0 0 $card-width-break-large; + height: calc(100% - 8px); + } + } + &__content { @include design-system.screen-lg-min { padding-left: 192px; @@ -31,15 +42,6 @@ $spacer-break-small: 16px; padding-right: 0; } - &__nft-image { - @include design-system.screen-sm-max { - max-width: 144px; - flex: 0 0 144px; - } - - max-width: 144px; - flex: 0 0 144px; - } &__show-more { max-height: 2.5rem; diff --git a/ui/components/app/nft-details/nft-details.js b/ui/components/app/nft-details/nft-details.js index 7f42386882e0..0bfe144fa1d4 100644 --- a/ui/components/app/nft-details/nft-details.js +++ b/ui/components/app/nft-details/nft-details.js @@ -280,7 +280,7 @@ export default function NftDetails({ nft }) { marginBottom={8} marginTop={1} > - + Date: Tue, 2 Jul 2024 16:20:29 +0200 Subject: [PATCH 26/41] fix: fix snapshot --- .../__snapshots__/nft-details.test.js.snap | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap b/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap index 25f58a8ba71c..94082e2cd2b9 100644 --- a/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap +++ b/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap @@ -41,7 +41,7 @@ exports[`NFT Details should match minimal props and state snapshot 1`] = ` class="mm-box mm-box--margin-top-1 mm-box--margin-bottom-8 mm-box--display-flex mm-box--justify-content-center" >

-

-

- 0xDc738...06414 -

+

+ 0xDc738...06414 +

+