From 023a70f9c58dcd476e60277d064aaae814b28742 Mon Sep 17 00:00:00 2001 From: vikinatora Date: Wed, 16 Mar 2022 17:41:23 +0200 Subject: [PATCH 1/8] listings tab, empty lists (events) reused --- .../nft-page/components/nft-info/NFTInfo.tsx | 489 ++++++++++-------- .../shared/empty-events/EmptyEvents.tsx | 21 + .../components/shared/empty-events/index.ts | 1 + .../history-listings-event/HistoryEvent.tsx | 120 +++++ .../history-listings-event}/index.ts | 0 .../nft-info/components/shared/index.tsx | 2 + .../components/tab-history/TabHistory.tsx | 12 +- .../components/history-event/HistoryEvent.tsx | 98 ---- .../tab-history/components/index.ts | 1 - .../components/tab-listings/TabListings.tsx | 64 +++ .../components/tab-listings/index.tsx | 1 + .../components/tab-offers/TabOffers.tsx | 140 ++--- .../components/empty-offers/EmptyOffers.tsx | 11 - .../components/empty-offers/index.ts | 1 - .../components/tab-offers/components/index.ts | 1 - .../tab-properties/TabProperties.tsx | 38 +- 16 files changed, 582 insertions(+), 418 deletions(-) create mode 100644 src/app/modules/nft/pages/nft-page/components/nft-info/components/shared/empty-events/EmptyEvents.tsx create mode 100644 src/app/modules/nft/pages/nft-page/components/nft-info/components/shared/empty-events/index.ts create mode 100644 src/app/modules/nft/pages/nft-page/components/nft-info/components/shared/history-listings-event/HistoryEvent.tsx rename src/app/modules/nft/pages/nft-page/components/nft-info/components/{tab-history/components/history-event => shared/history-listings-event}/index.ts (100%) create mode 100644 src/app/modules/nft/pages/nft-page/components/nft-info/components/shared/index.tsx delete mode 100644 src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-history/components/history-event/HistoryEvent.tsx delete mode 100644 src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-history/components/index.ts create mode 100644 src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-listings/TabListings.tsx create mode 100644 src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-listings/index.tsx delete mode 100644 src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-offers/components/empty-offers/EmptyOffers.tsx delete mode 100644 src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-offers/components/empty-offers/index.ts diff --git a/src/app/modules/nft/pages/nft-page/components/nft-info/NFTInfo.tsx b/src/app/modules/nft/pages/nft-page/components/nft-info/NFTInfo.tsx index ea65c2e5b..a1b5bd206 100644 --- a/src/app/modules/nft/pages/nft-page/components/nft-info/NFTInfo.tsx +++ b/src/app/modules/nft/pages/nft-page/components/nft-info/NFTInfo.tsx @@ -1,5 +1,6 @@ import { - Box, BoxProps, + Box, + BoxProps, Button, Container, Flex, @@ -34,7 +35,7 @@ import * as styles from '../../styles'; import * as styles2 from './styles'; import { NFTItemContentWithPrice, NFTLike } from '../../../../components/nft-item/components'; import { NFTTransferPopup } from '../nft-transfer-popup'; -import {BigNumber as EthersBigNumber, utils} from "ethers" +import { BigNumber as EthersBigNumber, utils } from 'ethers'; import BigNumber from 'bignumber.js'; import { sendRefreshMetadataRequest } from '../../../../../../../utils/api/marketplace'; import BGImage from '../../../../../../../assets/images/v2/stone_bg.jpg'; @@ -51,12 +52,15 @@ import { ReportStatusPopup } from './components/tab-offers/components/report-sta import { NFTAcceptOfferPopup } from './components/tab-offers/components'; import { useQueryClient } from 'react-query'; import { userKeys } from '../../../../../../utils/query-keys'; +import { TabListings } from './components/tab-listings'; // TODO: hide metadata tab for not Polymorph NFT type export const NFTInfo = () => { const router = useHistory(); - const { getTokenPriceByTicker, ethUsdPrice, daiUsdPrice, usdcUsdPrice, xyzUsdPrice, wethUsdPrice } = useAuthContext() as any - const { NFT, isLoading, order, creator, owner, collection, collectionAddress, history, offers, moreFromCollection } = useNFTPageData(); + const { getTokenPriceByTicker, ethUsdPrice, daiUsdPrice, usdcUsdPrice, xyzUsdPrice, wethUsdPrice, address } = + useAuthContext() as any; + const { NFT, isLoading, order, creator, owner, collection, collectionAddress, history, offers, moreFromCollection } = + useNFTPageData(); const [buySectionMeasure, setBuySectionMeasure] = useState(); const [isTransferOpened, setIsTransferOpened] = useState(false); @@ -84,253 +88,302 @@ export const NFTInfo = () => { const showMetadata = [ process.env.REACT_APP_POLYMORPHS_CONTRACT_ADDRESS, - process.env.REACT_APP_LOBSTERS_CONTRACT_ADDRESS + process.env.REACT_APP_LOBSTERS_CONTRACT_ADDRESS, ].includes(NFT?.collection?.address ?? ''); - + const handleRefresh = async () => { try { setRefreshMetadataStatus(Status.PROCESSING); - const request = await sendRefreshMetadataRequest(NFT?.collection?.address || "", NFT.tokenId); - + const request = await sendRefreshMetadataRequest(NFT?.collection?.address || '', NFT.tokenId); + if (request.status === 204) { setRefreshMetadataStatus(Status.SUCCESS); return; } - } catch(err) { - console.log(err) + } catch (err) { + console.log(err); } setRefreshMetadataStatus(Status.HIDDEN); - } + }; const getOrderOffers = async () => { - try { - const orders = offers?.orders || []; + try { + const orders = offers?.orders || []; + + const userRequests: Array = []; + const uniqueUsers = [...Array.from(new Set(orders.map((order) => order.maker)))]; + for (const user of uniqueUsers) { + userRequests.push(GetUserApi(user)); + } + + orders?.sort((a, b) => { + // Order by USD value of orders DESC + const tokenContractA = (a.make.assetType as IERC721AssetType).contract; + const tokenA = getTokenByAddress(tokenContractA); + const tokenPriceA = getTokenPriceByTicker(tokenA.ticker); + const orderPriceA = utils.formatUnits(a.make.value, tokenA.decimals ?? 18); + const orderUsdPriceA = new BigNumber(orderPriceA).multipliedBy(tokenPriceA); + + let tokenB = null; + let tokenPriceB = null; + + const tokenContractB = (b.make.assetType as IERC721AssetType).contract; + + if (tokenContractA.toLowerCase() === tokenContractB.toLowerCase()) { + tokenB = tokenA; + tokenPriceB = tokenPriceA; + } else { + tokenB = getTokenByAddress(tokenContractB); + tokenPriceB = getTokenPriceByTicker(tokenB.ticker); + } + + const orderPriceB = utils.formatUnits(b.make.value, tokenB.decimals ?? 18); + const orderUsdPriceB = new BigNumber(orderPriceB).multipliedBy(tokenPriceB); - const userRequests: Array = []; - const uniqueUsers = [...Array.from(new Set(orders.map(order => order.maker)))]; - for (const user of uniqueUsers) { - userRequests.push(GetUserApi(user)) + if (orderUsdPriceB.eq(orderUsdPriceA)) { + return 0; } - orders?.sort((a,b) => { - // Order by USD value of orders DESC - const tokenContractA = (a.make.assetType as IERC721AssetType).contract; - const tokenA = getTokenByAddress(tokenContractA) - const tokenPriceA = getTokenPriceByTicker(tokenA.ticker) - const orderPriceA = utils.formatUnits(a.make.value, tokenA.decimals ?? 18); - const orderUsdPriceA = new BigNumber(orderPriceA).multipliedBy(tokenPriceA); - - let tokenB = null; - let tokenPriceB = null; - - const tokenContractB = (b.make.assetType as IERC721AssetType).contract; - - if (tokenContractA.toLowerCase() === tokenContractB.toLowerCase()) { - tokenB = tokenA; - tokenPriceB = tokenPriceA; - } else { - tokenB = getTokenByAddress(tokenContractB); - tokenPriceB = getTokenPriceByTicker(tokenB.ticker) - } - - const orderPriceB = utils.formatUnits(b.make.value, tokenB.decimals ?? 18); - const orderUsdPriceB = new BigNumber(orderPriceB).multipliedBy(tokenPriceB); - - if (orderUsdPriceB.eq(orderUsdPriceA)) { - return 0; - } - - if (orderUsdPriceB.lt(orderUsdPriceA)) { - return -1; - } - - return 1; - }) - - const usersMap = (await (Promise.allSettled(userRequests))).reduce>((acc, response) => { - if(response.status !== 'fulfilled') { - return acc; - } - const user: IUser = response.value; - - queryClient.setQueryData(userKeys.info(user.address), user); - - acc[user.address] = user; + if (orderUsdPriceB.lt(orderUsdPriceA)) { + return -1; + } + + return 1; + }); + + const usersMap = (await Promise.allSettled(userRequests)).reduce>((acc, response) => { + if (response.status !== 'fulfilled') { return acc; - }, {}); + } - setUsersMap(usersMap) - setHighestOffer(orders[0]); - setHighestOfferCreator(usersMap[orders[0]?.maker]); - }catch(err) { - console.error(err); - } - } + const user: IUser = response.value; + acc[user.address] = user; + return acc; + }, {}); + + setUsersMap(usersMap); + setHighestOffer(orders[0]); + setHighestOfferCreator(usersMap[orders[0]?.maker]); + } catch (err) { + console.error(err); + } + }; useEffect(() => { if (ethUsdPrice && daiUsdPrice && usdcUsdPrice && xyzUsdPrice && wethUsdPrice) { getOrderOffers(); } - }, [offers, ethUsdPrice, daiUsdPrice, usdcUsdPrice, xyzUsdPrice, wethUsdPrice]) + }, [offers, ethUsdPrice, daiUsdPrice, usdcUsdPrice, xyzUsdPrice, wethUsdPrice]); + + const isOwner = owner?.address === address; return ( <> - {isLoading - ? ( -
- -
- ) - : NFT ? ( - <> - - - {!NFT.artworkType && } - {isNFTAssetImage(NFT.artworkType) && - - } - {isNFTAssetVideo(NFT.artworkType) && - - } - {isNFTAssetAudio(NFT.artworkType) && - - } - - - - + + + ) : NFT ? ( + <> + + + {!NFT.artworkType && } + {isNFTAssetImage(NFT.artworkType) && } + {isNFTAssetVideo(NFT.artworkType) && ( + + )} + {isNFTAssetAudio(NFT.artworkType) && } + + + + - {NFT.name} - - {/**/} - - setIsTransferOpened(true)} - onRefresh={handleRefresh} - /> - - - - - Edition  - {`${editionNumber}/${NFT.numberOfEditions || editions.length}`} - - - - {creator && } - {collection && } - {owner && } - - - - - {NFT.description || ''} - + justifyContent: 'space-between', + }} + > + + {NFT.name} + + + {/**/} + + setIsTransferOpened(true)} + onRefresh={handleRefresh} + /> + + + + Edition  + {`${editionNumber}/${NFT.numberOfEditions || editions.length}`} + + + + {creator && } + {collection && } + {owner && } + - - - Properties - {showMetadata && Metadata} - {/* TODO: Add implementation after release */} - {/* Owners */} - {/* Bids */} - Offers - History - - - div' : { px: 0, pb: 0, pt: '30px', }}}> - - {showMetadata && } - {/* TODO: Add implementation after release */} - {/* */} - {/* */} - - - - + + + {NFT.description || ''} + - setBuySectionMeasure(measure)} - /> + + + + Properties + {showMetadata && Metadata} + {/* TODO: Add implementation after release */} + {/* Owners */} + {/* Bids */} + Offers + History + Listings + + + div': { px: 0, pb: 0, pt: '30px' } }}> + + + + {showMetadata && ( + + + + )} + {/* TODO: Add implementation after release */} + {/* */} + {/* */} + + + + + + + + + + + - - {showOfferPopup && ( - setShowOfferPopup(false)} + owner={owner} + order={order} + highestOffer={{ offer: highestOffer || ({} as IOrder), creator: highestOfferCreator || ({} as IUser) }} + onMeasureChange={(measure) => setBuySectionMeasure(measure)} /> - )} - - {moreFromCollection && ( - - More from this collection - + + + {showOfferPopup && ( + setShowOfferPopup(false)} + /> + )} + {moreFromCollection && ( + + More from this collection + + - - {moreFromCollection.map((NFT) => !!NFT.id && ( - ( - + !!NFT.id && ( + ( + + )} /> - )} - /> - - ))} - - - - - )} - setIsTransferOpened(false)} /> - setRefreshMetadataStatus(Status.HIDDEN)} /> - - ) - : ()} + ) + )} + + + + + )} + setIsTransferOpened(false)} /> + setRefreshMetadataStatus(Status.HIDDEN)} + /> + + ) : ( + + )} - ) + ); }; diff --git a/src/app/modules/nft/pages/nft-page/components/nft-info/components/shared/empty-events/EmptyEvents.tsx b/src/app/modules/nft/pages/nft-page/components/nft-info/components/shared/empty-events/EmptyEvents.tsx new file mode 100644 index 000000000..20860adf6 --- /dev/null +++ b/src/app/modules/nft/pages/nft-page/components/nft-info/components/shared/empty-events/EmptyEvents.tsx @@ -0,0 +1,21 @@ +import { Flex, Image, Text } from '@chakra-ui/react'; + +import TextBubbleImage from '../../../../../../../../../../assets/images/text-bubble.png'; + +interface IOffersEmpty { + title: string; + subtitle?: string; +} + +export const EventsEmpty = (props: IOffersEmpty) => { + const { title, subtitle } = props; + return ( + + + + {title} + + {subtitle && {subtitle}} + + ); +}; diff --git a/src/app/modules/nft/pages/nft-page/components/nft-info/components/shared/empty-events/index.ts b/src/app/modules/nft/pages/nft-page/components/nft-info/components/shared/empty-events/index.ts new file mode 100644 index 000000000..79af9ab3c --- /dev/null +++ b/src/app/modules/nft/pages/nft-page/components/nft-info/components/shared/empty-events/index.ts @@ -0,0 +1 @@ +export * from './EmptyEvents'; diff --git a/src/app/modules/nft/pages/nft-page/components/nft-info/components/shared/history-listings-event/HistoryEvent.tsx b/src/app/modules/nft/pages/nft-page/components/nft-info/components/shared/history-listings-event/HistoryEvent.tsx new file mode 100644 index 000000000..a3881cc1c --- /dev/null +++ b/src/app/modules/nft/pages/nft-page/components/nft-info/components/shared/history-listings-event/HistoryEvent.tsx @@ -0,0 +1,120 @@ +import { Box, Flex, Text, Link, Image, Tooltip, Button } from '@chakra-ui/react'; +import BigNumber from 'bignumber.js'; +import dayjs from 'dayjs'; +import { utils } from 'ethers'; +import React from 'react'; +import { NFTTabItemWrapper } from '../..'; +import { getEtherscanTxUrl } from '../../../../../../../../../../utils/helpers'; +import { shortenEthereumAddress } from '../../../../../../../../../../utils/helpers/format'; +import { getTokenByAddress, TOKENS_MAP, ZERO_ADDRESS } from '../../../../../../../../../constants'; +import { TokenTicker } from '../../../../../../../../../enums'; +import { useTokenPrice } from '../../../../../../../../../hooks'; +import { IToken } from '../../../../../../../../../types'; +import { IERC20AssetType, IERC721AssetType, IOrder } from '../../../../../../../types'; +import { HistoryType } from '../../../../../enums'; +import { actionIcon, nameLabels } from '../../tab-history/constants'; +import { getAddedAtLabel } from '../../tab-history/helpers'; +import * as styles from '../../tab-history/styles'; +import EtherScanIcon from './../../../../../../../../../../assets/images/etherscan.svg'; + +interface IHistoryEventProps { + event: IOrder; + onlyListings?: boolean; + cancelListing?: React.Dispatch>; +} + +const HistoryEvent: React.FC = ({ event, onlyListings, cancelListing }) => { + let type: HistoryType = HistoryType.MINTED; + let price = ''; + let token: IToken = null as any; + + if (event.from !== ZERO_ADDRESS) { + const side = event.side; + const status = event.status; + + if (side === 1 && status === 2) { + type = HistoryType.BOUGHT; + } else if (side === 1 && status === 0) { + type = HistoryType.LISTED; + } else if (onlyListings) { + type = HistoryType.LISTED; + } else { + type = HistoryType.OFFER; + } + + if (side === 0) { + token = getTokenByAddress((event.make.assetType as IERC721AssetType).contract); + const tokenDecimals = TOKENS_MAP[token.ticker]?.decimals ?? 18; + + price = new BigNumber(utils.formatUnits(event.make.value, tokenDecimals)).toFixed(2); + } else { + token = getTokenByAddress((event.take.assetType as IERC20AssetType).contract); + const tokenDecimals = token?.decimals ?? 18; + + price = new BigNumber(utils.formatUnits(event.take.value, tokenDecimals)).toFixed(2); + } + } + + const usdPrice = useTokenPrice(token?.ticker); + + const usd = new BigNumber(price).multipliedBy(usdPrice).toFixed(2); + + const endDate = new Date(event.end * 1000); + const expired = type === HistoryType.OFFER ? dayjs().diff(endDate) > 0 : false; + + return ( + + + {!onlyListings && } + + + {nameLabels[type]} + {event.makerData && + (event.makerData.displayName + ? event.makerData.displayName + : shortenEthereumAddress(event.makerData.address))} + + + {getAddedAtLabel(event.createdAt)} + {!onlyListings && expired && ( + + {' '} + (expired) + + )} + + + + + {!!price && ( + + + {price} {token?.ticker ?? ''} + + ${usd} + + )} + {onlyListings && cancelListing && ( + + )} + {(type === HistoryType.BOUGHT || type === HistoryType.MINTED) && event.matchedTxHash && ( + + + + + + )} + + + ); +}; + +export default HistoryEvent; diff --git a/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-history/components/history-event/index.ts b/src/app/modules/nft/pages/nft-page/components/nft-info/components/shared/history-listings-event/index.ts similarity index 100% rename from src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-history/components/history-event/index.ts rename to src/app/modules/nft/pages/nft-page/components/nft-info/components/shared/history-listings-event/index.ts diff --git a/src/app/modules/nft/pages/nft-page/components/nft-info/components/shared/index.tsx b/src/app/modules/nft/pages/nft-page/components/nft-info/components/shared/index.tsx new file mode 100644 index 000000000..b0acc8fc5 --- /dev/null +++ b/src/app/modules/nft/pages/nft-page/components/nft-info/components/shared/index.tsx @@ -0,0 +1,2 @@ +export * from './history-listings-event'; +export * from './empty-events'; diff --git a/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-history/TabHistory.tsx b/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-history/TabHistory.tsx index 8f0b25eb6..71c6d54a8 100644 --- a/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-history/TabHistory.tsx +++ b/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-history/TabHistory.tsx @@ -1,17 +1,19 @@ import { Box } from '@chakra-ui/react'; -import { IOrder } from '../../../../../../types'; -import { INFTHistory, } from '../../../../../../api'; -import HistoryEvent from './components/history-event/HistoryEvent'; +import { IOrder } from '../../../../../../types'; +import { INFTHistory } from '../../../../../../api'; +import HistoryEvent from '../shared/history-listings-event/HistoryEvent'; interface ITabHistoryProps { historyData?: INFTHistory; } -export const TabHistory = ({ historyData = {orderHistory: [], mintEvent: null as any} }: ITabHistoryProps) => { +export const TabHistory = ({ historyData = { orderHistory: [], mintEvent: null as any } }: ITabHistoryProps) => { const events = [...historyData?.orderHistory, historyData?.mintEvent]; return ( - {events.map((event: IOrder | any, i: number) => event && )} + {events.map( + (event: IOrder | any, i: number) => event && + )} ); }; diff --git a/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-history/components/history-event/HistoryEvent.tsx b/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-history/components/history-event/HistoryEvent.tsx deleted file mode 100644 index 3d8f83544..000000000 --- a/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-history/components/history-event/HistoryEvent.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import { Box, Flex, Text, Link, Image, Tooltip } from '@chakra-ui/react'; -import BigNumber from 'bignumber.js'; -import dayjs from 'dayjs'; -import { utils } from 'ethers'; -import React, { useEffect, useState } from 'react' -import { NFTTabItemWrapper } from '../../..'; -import { useAuthContext } from '../../../../../../../../../../../contexts/AuthContext'; -import { getEtherscanTxUrl } from '../../../../../../../../../../../utils/helpers'; -import { shortenEthereumAddress } from '../../../../../../../../../../../utils/helpers/format'; -import { getTokenByAddress, TOKENS_MAP, ZERO_ADDRESS } from '../../../../../../../../../../constants'; -import { TokenTicker } from '../../../../../../../../../../enums'; -import { useTokenPrice } from '../../../../../../../../../../hooks'; -import { IToken } from '../../../../../../../../../../types'; -import { IERC20AssetType, IERC721AssetType, IOrder } from '../../../../../../../../types'; -import { HistoryType } from '../../../../../../enums'; -import { actionIcon, nameLabels } from '../../constants'; -import { getAddedAtLabel } from '../../helpers'; -import * as styles from "../../styles"; -import EtherScanIcon from './../../../../../../../../../../../assets/images/etherscan.svg'; - -interface IHistoryEventProps { - event: IOrder; -} - -const HistoryEvent:React.FC = ({event}) => { - const { web3Provider } = useAuthContext() as any; - const [blockDate, setBlockDate] = useState(new Date()); - - let type: HistoryType = HistoryType.MINTED; - let price = ""; - let token: IToken = null as any; - - if (event.from !== ZERO_ADDRESS) { - const side = event.side; - const status = event.status; - type = (side === 1 && status === 2) ? HistoryType.BOUGHT : (side === 1 && status === 0) ? HistoryType.LISTED : HistoryType.OFFER; - - if (side === 0) { - token = getTokenByAddress((event.make.assetType as IERC721AssetType).contract); - const tokenDecimals = TOKENS_MAP[token.ticker]?.decimals ?? 18; - - price = new BigNumber(utils.formatUnits(event.make.value, tokenDecimals)).toFixed(2); - } else { - token = getTokenByAddress((event.take.assetType as IERC20AssetType).contract); - const tokenDecimals = token?.decimals ?? 18; - - price = new BigNumber(utils.formatUnits(event.take.value, tokenDecimals)).toFixed(2); - } - } - - const usdPrice = useTokenPrice(token?.ticker); - - const usd = new BigNumber(price).multipliedBy(usdPrice).toFixed(2); - - const endDate = new Date(event.end * 1000); - const expired = type === HistoryType.OFFER ? dayjs().diff(endDate) > 0 : false; - - const getBlockTimestamp = async () => { - const blockTimestamp = await web3Provider?.getBlock(event?.blockNum); - setBlockDate(new Date(blockTimestamp?.timestamp * 1000)); - } - - useEffect(() => { - getBlockTimestamp(); - }, [web3Provider, event]) - - return ( - - - - - - {nameLabels[type]} { event.makerData && (event.makerData.displayName ? event.makerData.displayName : shortenEthereumAddress(event.makerData.address)) } - - - {getAddedAtLabel(type === HistoryType.MINTED ? blockDate : event.createdAt)} - {expired && (expired)} - - - - - {!!price && - {price} {token?.ticker ?? ""} - ${usd} - } - {(type === HistoryType.BOUGHT || type === HistoryType.MINTED) && event.matchedTxHash && - - - - - - } - - - ); -} - -export default HistoryEvent \ No newline at end of file diff --git a/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-history/components/index.ts b/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-history/components/index.ts deleted file mode 100644 index cc9b4fc3f..000000000 --- a/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-history/components/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './history-event' \ No newline at end of file diff --git a/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-listings/TabListings.tsx b/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-listings/TabListings.tsx new file mode 100644 index 000000000..5c1e920f8 --- /dev/null +++ b/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-listings/TabListings.tsx @@ -0,0 +1,64 @@ +import { Box } from '@chakra-ui/react'; +import { useState } from 'react'; +import { NFTCancelListingPopup } from '../../..'; +import { IOrder, IUser } from '../../../../../../types'; +import { EventsEmpty } from '../shared'; +import HistoryEvent from '../shared/history-listings-event/HistoryEvent'; + +// TODO: refresh state after a listing is made +// TODO: refresh state after a listing is canceled + +interface ITabListingsProps { + orderHistory: IOrder[]; + owner: IUser; +} + +export const TabListings = (props: ITabListingsProps) => { + const [isCancelListingPopupOpened, setIsCancelListingPopupOpened] = useState(false); + const { orderHistory, owner } = props; + const listings = orderHistory + ?.filter((order: IOrder) => { + if ( + owner.address === order?.makerData?.address && + order.side === 1 && + (order.status === 0 || order.status === 4) + ) { + return order; + } + }) + .map((order) => { + return { + ...order, + start: Number(order.start), + end: Number(order.end), + salt: Number(order.salt), + }; + }); + + if (!listings?.length) { + return ; + } + + return ( + + {listings.map((listing: IOrder | any) => { + return ( + <> + + setIsCancelListingPopupOpened(false)} + handleCancel={() => setIsCancelListingPopupOpened(false)} + /> + + ); + })} + + ); +}; diff --git a/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-listings/index.tsx b/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-listings/index.tsx new file mode 100644 index 000000000..54f781c1e --- /dev/null +++ b/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-listings/index.tsx @@ -0,0 +1 @@ +export * from './TabListings'; diff --git a/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-offers/TabOffers.tsx b/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-offers/TabOffers.tsx index 86461ae41..47c66f912 100644 --- a/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-offers/TabOffers.tsx +++ b/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-offers/TabOffers.tsx @@ -1,6 +1,5 @@ import { Box } from '@chakra-ui/react'; -import { useEffect, useState } from 'react'; -import { NFTAcceptOfferPopup, OffersEmpty } from './components'; +import { useEffect, useState } from 'react'; import { IERC721AssetType, INFT, IOrder, IUser } from '../../../../../../types'; import { NFTOffer } from './components/nft-offer/NFTOffer'; import { LoadingPopup } from '../../../../../../../marketplace/components/popups/loading-popup'; @@ -12,24 +11,30 @@ import Contracts from '../../../../../../../../../contracts/contracts.json'; import { GetActiveListingApi, GetOrdersApi } from '../../../../../../api'; import { orderKeys } from '../../../../../../../../utils/query-keys'; import { useNFTPageData } from '../../../../NFTPage.context'; - +import { EventsEmpty } from '../shared'; interface ITabOffersProps { nft?: INFT; order?: IOrder; offers?: IOrder[]; usersMap?: Record; - setShowOfferPopup: React.Dispatch> - setOfferForAccept: React.Dispatch> + setShowOfferPopup: React.Dispatch>; + setOfferForAccept: React.Dispatch>; } enum CancelingText { PROGRESS = 'The transaction is in progress...', INDEXING = 'Indexing transaction...', - INDEXING_TAKING_TOO_LONG = "Receving the event from the blockchain is taking longer than expected. Please be patient." + INDEXING_TAKING_TOO_LONG = 'Receving the event from the blockchain is taking longer than expected. Please be patient.', } -export const TabOffers:React.FC = ({nft, offers, usersMap, setShowOfferPopup, setOfferForAccept}) => { +export const TabOffers: React.FC = ({ + nft, + offers, + usersMap, + setShowOfferPopup, + setOfferForAccept, +}) => { const { signer } = useAuthContext() as any; const [offerCanceling, setOfferCanceling] = useState(false); const [offerCancelingText, setOfferCancelingText] = useState(CancelingText.PROGRESS); @@ -46,100 +51,107 @@ export const TabOffers:React.FC = ({nft, offers, usersMap, setS if (orderInterval) { clearInterval(orderInterval); } - } - }, []) - + }; + }, []); const handleCancelOffer = async (offer: IOrder) => { setOfferCanceling(true); - setOfferCancelingText(CancelingText.PROGRESS) - const contract = new Contract(`${process.env.REACT_APP_MARKETPLACE_CONTRACT}`, contractsData.Marketplace.abi, signer); - - const { data: encodedOrderData } = (await encodeOrderMutation.mutateAsync({ - type: offer.type, - data: offer.data, - maker: offer.maker, - make: offer.make as any, - salt: offer.salt, - start: offer.start, - end: offer.end, - take: offer.take, - taker: offer.taker, - })); + setOfferCancelingText(CancelingText.PROGRESS); + const contract = new Contract( + `${process.env.REACT_APP_MARKETPLACE_CONTRACT}`, + contractsData.Marketplace.abi, + signer + ); + + const { data: encodedOrderData } = await encodeOrderMutation.mutateAsync({ + type: offer.type, + data: offer.data, + maker: offer.maker, + make: offer.make as any, + salt: offer.salt, + start: offer.start, + end: offer.end, + take: offer.take, + taker: offer.taker, + }); try { const cancelReceipt = await contract.cancel(encodedOrderData); const cancelTx = await cancelReceipt.wait(); - if(cancelTx.status !== 1) { + if (cancelTx.status !== 1) { console.error('display error'); return; } - setOfferCancelingText(CancelingText.INDEXING) - + setOfferCancelingText(CancelingText.INDEXING); + // This polling mechanic is temporary until we have marketplace web sockets let fetchCount = 0; const orderIndexing = setInterval(async () => { fetchCount += 1; - const stringifiedOffers = offers?.map(offer => offer.id).join(''); + const stringifiedOffers = offers?.map((offer) => offer.id).join(''); const convertedOrder = offer.take.assetType as IERC721AssetType; const tokenId = convertedOrder.tokenId?.toString(); const collectionAddress = convertedOrder.contract; - + // Fetch order api until a diffrent response is returned const newOffers = await GetOrdersApi({ - side: 0, - tokenIds: tokenId, - collection: collectionAddress - }) - + side: 0, + tokenIds: tokenId, + collection: collectionAddress, + }); + // Change query information about order - const newStringifiedoffers = newOffers?.orders?.map(offer => offer.id).join(''); + const newStringifiedoffers = newOffers?.orders?.map((offer) => offer.id).join(''); if (stringifiedOffers !== newStringifiedoffers) { clearInterval(orderIndexing); - queryClient.setQueryData(orderKeys.offers({tokenId, collectionAddress}), newOffers || undefined); - queryClient.invalidateQueries(orderKeys.listing({tokenId, collectionAddress})); + queryClient.setQueryData(orderKeys.offers({ tokenId, collectionAddress }), newOffers || undefined); + queryClient.invalidateQueries(orderKeys.listing({ tokenId, collectionAddress })); setOfferCanceling(false); - } - + if (fetchCount === 3) { - setOfferCancelingText(CancelingText.INDEXING_TAKING_TOO_LONG) + setOfferCancelingText(CancelingText.INDEXING_TAKING_TOO_LONG); } - - }, 4000); + }, 4000); setOrderInterval(orderIndexing); - } catch (error) { console.error(error); setOfferCanceling(false); } - } - - return !offers?.length ? : ( + }; + + return !offers?.length ? ( + + ) : ( - {offers?.map((offer) => ( - offer && nft && nft._ownerAddress && - ))} + {offers?.map( + (offer) => + offer && + nft && + nft._ownerAddress && ( + + ) + )} {/*TODO: add support of bundle*/} setOfferCanceling(false)} - transactions={[]} - /> + heading="Cancelling offer" + text={offerCancelingText} + isOpen={offerCanceling} + onClose={() => setOfferCanceling(false)} + transactions={[]} + /> ); -} \ No newline at end of file +}; diff --git a/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-offers/components/empty-offers/EmptyOffers.tsx b/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-offers/components/empty-offers/EmptyOffers.tsx deleted file mode 100644 index 0f32bd56f..000000000 --- a/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-offers/components/empty-offers/EmptyOffers.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { Flex, Image, Text } from '@chakra-ui/react'; - -import TextBubbleImage from '../../../../../../../../../../../assets/images/text-bubble.png'; - -export const OffersEmpty = () => ( - - - No active offers yet. - Be the first to make an offer! - -); diff --git a/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-offers/components/empty-offers/index.ts b/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-offers/components/empty-offers/index.ts deleted file mode 100644 index 557ba6290..000000000 --- a/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-offers/components/empty-offers/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './EmptyOffers'; diff --git a/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-offers/components/index.ts b/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-offers/components/index.ts index 24a537fb9..5c7d7f4f5 100644 --- a/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-offers/components/index.ts +++ b/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-offers/components/index.ts @@ -1,3 +1,2 @@ -export * from './empty-offers'; export * from './nft-accept-offer-popup'; export * from './nft-offer'; diff --git a/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-properties/TabProperties.tsx b/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-properties/TabProperties.tsx index 4b5428b2b..830b80709 100644 --- a/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-properties/TabProperties.tsx +++ b/src/app/modules/nft/pages/nft-page/components/nft-info/components/tab-properties/TabProperties.tsx @@ -9,12 +9,13 @@ import { PolymorphPropertyTrait } from '..'; import { PolymorphProperty } from '..'; import { INFTProperty } from '../../../../../../types'; import './TabProperties.scss'; +import { EventsEmpty } from '../shared'; interface ITabPropertiesProps { properties: INFTProperty[]; } -export const TabProperties = ({ properties = [] } : ITabPropertiesProps) => { +export const TabProperties = ({ properties = [] }: ITabPropertiesProps) => { const { isPolymorph } = useNFTPageData(); const polymorphProperties = useMemo(() => { @@ -22,34 +23,33 @@ export const TabProperties = ({ properties = [] } : ITabPropertiesProps) => { return []; } - return properties.filter((property) => ['Rank', 'Rarity score'].includes(property.traitType)) + return properties.filter((property) => ['Rank', 'Rarity score'].includes(property.traitType)); }, [isPolymorph, properties]); + if (!properties?.length) { + return ; + } + return ( {isPolymorph && ( - {polymorphProperties.map((property, i: number) => )} + {polymorphProperties.map((property, i: number) => ( + + ))} )} - {properties.map((property, i: number) => ( - isPolymorph - ? !polymorphProperties.includes(property) - ? - : null - : property.traitType && property.value && - ))} + {properties.map((property, i: number) => + isPolymorph ? ( + !polymorphProperties.includes(property) ? ( + + ) : null + ) : ( + property.traitType && property.value && + ) + )} - { - properties.length == 0 ? - - - This NFT doesn't have any properties. - - - : null - } ); }; From e2df1f1401df8f1235698b01cf138826cb8754f9 Mon Sep 17 00:00:00 2001 From: vikinatora Date: Wed, 16 Mar 2022 17:41:28 +0200 Subject: [PATCH 2/8] fix(coingecko): add try catch around coingecko calls --- src/contexts/AuthContext.jsx | 43 ++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/src/contexts/AuthContext.jsx b/src/contexts/AuthContext.jsx index bea772756..1da37329d 100644 --- a/src/contexts/AuthContext.jsx +++ b/src/contexts/AuthContext.jsx @@ -55,25 +55,30 @@ const AuthContextProvider = ({ children }) => { // Getters useEffect(() => { (async () => { - const [ethPrice, daiInfo, usdcInfo, xyzInfo, wethInfo] = await Promise.all([ - getEthPriceCoingecko(), - getERC20PriceCoingecko('dai'), - getERC20PriceCoingecko('usd-coin'), - getERC20PriceCoingecko('universe-xyz'), - getERC20PriceCoingecko('weth'), - ]); - - console.log(`wethPrice: ${wethInfo?.market_data?.current_price?.usd}`); - console.log(`ethPrice: ${ethPrice?.market_data?.current_price?.usd}`); - console.log(`usdcPrice: ${usdcInfo?.market_data?.current_price?.usd}`); - console.log(`daiPrice: ${daiInfo?.market_data?.current_price?.usd}`); - console.log(`xyzPrice: ${xyzInfo?.market_data?.current_price?.usd}`); - - setEthUsdPrice(ethPrice?.market_data?.current_price?.usd); - setDaiUsdPrice(daiInfo?.market_data?.current_price?.usd); - setUsdcUsdPrice(usdcInfo?.market_data?.current_price?.usd); - setXyzUsdPrice(xyzInfo?.market_data?.current_price?.usd); - setWethUsdPrice(wethInfo?.market_data?.current_price?.usd); + try { + const [ethPrice, daiInfo, usdcInfo, xyzInfo, wethInfo] = await Promise.all([ + getEthPriceCoingecko(), + getERC20PriceCoingecko('dai'), + getERC20PriceCoingecko('usd-coin'), + getERC20PriceCoingecko('universe-xyz'), + getERC20PriceCoingecko('weth'), + ]); + + console.log(`wethPrice: ${wethInfo?.market_data?.current_price?.usd}`); + console.log(`ethPrice: ${ethPrice?.market_data?.current_price?.usd}`); + console.log(`usdcPrice: ${usdcInfo?.market_data?.current_price?.usd}`); + console.log(`daiPrice: ${daiInfo?.market_data?.current_price?.usd}`); + console.log(`xyzPrice: ${xyzInfo?.market_data?.current_price?.usd}`); + + setEthUsdPrice(ethPrice?.market_data?.current_price?.usd); + setDaiUsdPrice(daiInfo?.market_data?.current_price?.usd); + setUsdcUsdPrice(usdcInfo?.market_data?.current_price?.usd); + setXyzUsdPrice(xyzInfo?.market_data?.current_price?.usd); + setWethUsdPrice(wethInfo?.market_data?.current_price?.usd); + } catch (err) { + console.log('coingecko price fetching failed'); + console.log(err); + } })(); }, []); From 813fd84a3027712506ef1d57e2c5564ea0f641e3 Mon Sep 17 00:00:00 2001 From: vikinatora Date: Wed, 16 Mar 2022 17:41:28 +0200 Subject: [PATCH 3/8] improve(query-invalidation): invalidate history on cancel and on list --- src/app/modules/marketplace/pages/sell-page/SellPage.tsx | 1 + .../nft-cancel-listing-popup/NFTCancelListingPopup.tsx | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/app/modules/marketplace/pages/sell-page/SellPage.tsx b/src/app/modules/marketplace/pages/sell-page/SellPage.tsx index 6f8624101..073892f8f 100644 --- a/src/app/modules/marketplace/pages/sell-page/SellPage.tsx +++ b/src/app/modules/marketplace/pages/sell-page/SellPage.tsx @@ -75,6 +75,7 @@ export const SellPage = () => { queryClient.refetchQueries(orderKeys.browseAny) queryClient.invalidateQueries(orderKeys.listing({ collectionAddress: params.collectionAddress.toLowerCase(), tokenId: params.tokenId })); + queryClient.invalidateQueries(orderKeys.history({ collectionAddress: params.collectionAddress.toLowerCase(), tokenId: params.tokenId })); queryClient.prefetchQuery(orderKeys.listing({ collectionAddress: params.collectionAddress.toLowerCase(), tokenId: params.tokenId }), async () => { const result = await GetActiveListingApi(params.collectionAddress.toLowerCase(), params.tokenId); return result; diff --git a/src/app/modules/nft/pages/nft-page/components/nft-cancel-listing-popup/NFTCancelListingPopup.tsx b/src/app/modules/nft/pages/nft-page/components/nft-cancel-listing-popup/NFTCancelListingPopup.tsx index 2b476f9fd..811df78d0 100644 --- a/src/app/modules/nft/pages/nft-page/components/nft-cancel-listing-popup/NFTCancelListingPopup.tsx +++ b/src/app/modules/nft/pages/nft-page/components/nft-cancel-listing-popup/NFTCancelListingPopup.tsx @@ -108,6 +108,8 @@ export const NFTCancelListingPopup = ({ order, isOpen, onClose, handleCancel }: // Change query information about order if (!newOrder?.id || order.id !== newOrder.id) { clearInterval(indexInterval); + + queryClient.invalidateQueries(orderKeys.history({tokenId, collectionAddress})); queryClient.setQueryData(orderKeys.listing({tokenId, collectionAddress}), newOrder || undefined); queryClient.refetchQueries(orderKeys.browseAny) closeLoading(); From 86bca790eb286dd3ed20be90b7c4d4c5640d9dbe Mon Sep 17 00:00:00 2001 From: vikinatora Date: Wed, 16 Mar 2022 17:41:28 +0200 Subject: [PATCH 4/8] improve(change-price): always cancel listing --- .../NFTChangeListingPricePopup.tsx | 57 +++++++++++++------ 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/src/app/modules/nft/pages/nft-page/components/nft-change-listing-price-popup/NFTChangeListingPricePopup.tsx b/src/app/modules/nft/pages/nft-page/components/nft-change-listing-price-popup/NFTChangeListingPricePopup.tsx index 0d1a7ba70..f167606bc 100644 --- a/src/app/modules/nft/pages/nft-page/components/nft-change-listing-price-popup/NFTChangeListingPricePopup.tsx +++ b/src/app/modules/nft/pages/nft-page/components/nft-change-listing-price-popup/NFTChangeListingPricePopup.tsx @@ -22,7 +22,7 @@ import { import axios from 'axios'; import { BigNumber, ethers } from 'ethers'; import React, { useEffect, useMemo, useRef, useState } from 'react'; -import { useMutation } from 'react-query'; +import { useMutation, useQueryClient } from 'react-query'; import { useFormik } from 'formik'; import * as Yup from 'yup'; @@ -39,6 +39,7 @@ import { useAuthContext } from '../../../../../../../contexts/AuthContext'; import { useErrorContext } from '../../../../../../../contexts/ErrorContext'; import { sign } from '../../../../../../helpers'; import { NFTCancelListingPopup } from '..'; +import { nftKeys, orderKeys } from '../../../../../../utils/query-keys'; export enum ChangeListingPriceState { FORM, @@ -62,8 +63,9 @@ export const NFTChangeListingPricePopup = ({ nft, order, isOpen, onClose, }: INF const tokensBtnRef = useRef(null); const [state, setState] = useState(ChangeListingPriceState.FORM); + const queryClient = useQueryClient(); const [isCancelListingPopupOpened, setIsCancelListingPopupOpened] = useState(false); - const [isMarkedForCancel, setIsMarkedForCancel] = useState(true); + const [oldOrder, setOldOrder] = useState(); const tokens = useMemo(() => TOKENS, []); @@ -87,14 +89,18 @@ export const NFTChangeListingPricePopup = ({ nft, order, isOpen, onClose, }: INF validationSchema: NFTChangeListingPriceValidationSchema, onSubmit: async (value) => { try { - if(nft == undefined || order == undefined) { + + if(nft == undefined) { return; } - if (BigNumber.from(ethers.utils.parseUnits(`${value.amount}`,`${TOKENS_MAP[value.token as TokenTicker].decimals}`)).gt(BigNumber.from(order.take.value)) && isMarkedForCancel) { - setIsCancelListingPopupOpened(true); - } else { + + if (!order) { updateListing(value); + } else { + setOldOrder(order); + setIsCancelListingPopupOpened(true); } + } catch (e) { setShowError(true); } @@ -103,9 +109,11 @@ export const NFTChangeListingPricePopup = ({ nft, order, isOpen, onClose, }: INF const updateListing = async (value: any) => { try { - if(nft == undefined || order == undefined) { + + if (nft == undefined || oldOrder == undefined) { return; } + setState(ChangeListingPriceState.PROCESSING); const network = await web3Provider.getNetwork(); const address = await signer.getAddress(); @@ -125,14 +133,14 @@ export const NFTChangeListingPricePopup = ({ nft, order, isOpen, onClose, }: INF const orderData: IEncodeOrderApiData = { salt: salt, - maker: order.maker, + maker: oldOrder.maker, make: make, - taker: order.taker, - take: order.take, - type: order.type, - start: order.start, - end: order.end, - data: order.data, + taker: oldOrder.taker, + take: oldOrder.take, + type: oldOrder.type, + start: oldOrder.start, + end: oldOrder.end, + data: oldOrder.data, }; const newToken = TOKENS_MAP[value.token as TokenTicker]; @@ -144,6 +152,9 @@ export const NFTChangeListingPricePopup = ({ nft, order, isOpen, onClose, }: INF if (newToken.ticker !== TokenTicker.ETH) { const tokenAddress = getTokenAddressByTicker(newToken.ticker) orderData.take.assetType.contract = tokenAddress; + } else { + // ETH order must never have contract address + delete orderData.take.assetType.contract; } const { data: encodedOrder } = (await encodeOrderMutation.mutateAsync(orderData as IEncodeOrderApiData)); @@ -157,7 +168,21 @@ export const NFTChangeListingPricePopup = ({ nft, order, isOpen, onClose, }: INF ); const createOrderResponse = (await createOrderMutation.mutateAsync({ ...orderData, signature })).data; - + + const tokenIdCollectionPair = { + collectionAddress: orderData.make.assetType.contract || "", + tokenId: orderData.make.assetType.tokenId || "" + } + + queryClient.setQueryData(orderKeys.listing(tokenIdCollectionPair), createOrderResponse) + queryClient.invalidateQueries(orderKeys.history(tokenIdCollectionPair)); + + //TODO: Invalidate browse marketplace page if order has been loaded + queryClient.refetchQueries(orderKeys.browseAny); + + // Invalidate my nfts query in order to see the new nft + queryClient.refetchQueries(nftKeys.userNfts(address)); + setState(ChangeListingPriceState.SUCCESS) } catch(e) { setShowError(true); @@ -282,7 +307,7 @@ export const NFTChangeListingPricePopup = ({ nft, order, isOpen, onClose, }: INF order={order} isOpen={isCancelListingPopupOpened} onClose={() => setIsCancelListingPopupOpened(false)} - handleCancel={() => setIsMarkedForCancel(false)} + handleCancel={() => {}} /> ); From 7d36b2dae195c9f9709f18a41ae7f4f127b655d6 Mon Sep 17 00:00:00 2001 From: vikinatora Date: Wed, 16 Mar 2022 17:42:13 +0200 Subject: [PATCH 5/8] improve(listings-tab): always show listing tab --- .../nft-page/components/nft-info/NFTInfo.tsx | 2 -- .../history-listings-event/HistoryEvent.tsx | 5 +++-- .../components/tab-listings/TabListings.tsx | 17 ++++++++++------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/app/modules/nft/pages/nft-page/components/nft-info/NFTInfo.tsx b/src/app/modules/nft/pages/nft-page/components/nft-info/NFTInfo.tsx index a1b5bd206..ec55105c4 100644 --- a/src/app/modules/nft/pages/nft-page/components/nft-info/NFTInfo.tsx +++ b/src/app/modules/nft/pages/nft-page/components/nft-info/NFTInfo.tsx @@ -175,8 +175,6 @@ export const NFTInfo = () => { } }, [offers, ethUsdPrice, daiUsdPrice, usdcUsdPrice, xyzUsdPrice, wethUsdPrice]); - const isOwner = owner?.address === address; - return ( <> {isLoading ? ( diff --git a/src/app/modules/nft/pages/nft-page/components/nft-info/components/shared/history-listings-event/HistoryEvent.tsx b/src/app/modules/nft/pages/nft-page/components/nft-info/components/shared/history-listings-event/HistoryEvent.tsx index a3881cc1c..ab695c756 100644 --- a/src/app/modules/nft/pages/nft-page/components/nft-info/components/shared/history-listings-event/HistoryEvent.tsx +++ b/src/app/modules/nft/pages/nft-page/components/nft-info/components/shared/history-listings-event/HistoryEvent.tsx @@ -21,9 +21,10 @@ interface IHistoryEventProps { event: IOrder; onlyListings?: boolean; cancelListing?: React.Dispatch>; + isOwner?: boolean; } -const HistoryEvent: React.FC = ({ event, onlyListings, cancelListing }) => { +const HistoryEvent: React.FC = ({ event, onlyListings, cancelListing, isOwner }) => { let type: HistoryType = HistoryType.MINTED; let price = ''; let token: IToken = null as any; @@ -94,7 +95,7 @@ const HistoryEvent: React.FC = ({ event, onlyListings, cance ${usd} )} - {onlyListings && cancelListing && ( + {isOwner && onlyListings && cancelListing && (