2022-03-04 18:35:35 -08:00
|
|
|
import React from "react";
|
|
|
|
import {
|
|
|
|
NFTData,
|
|
|
|
useFetchAccountInfo,
|
|
|
|
useMintAccountInfo,
|
|
|
|
} from "providers/accounts";
|
2021-11-28 13:39:33 -08:00
|
|
|
import { programs } from "@metaplex/js";
|
2021-10-16 19:14:50 -07:00
|
|
|
import { ArtContent } from "components/common/NFTArt";
|
2021-10-05 11:30:05 -07:00
|
|
|
import { InfoTooltip } from "components/common/InfoTooltip";
|
|
|
|
import { clusterPath } from "utils/url";
|
|
|
|
import { Link } from "react-router-dom";
|
2021-10-16 19:14:50 -07:00
|
|
|
import { EditionInfo } from "providers/accounts/utils/getEditionInfo";
|
2022-03-04 18:35:35 -08:00
|
|
|
import { PublicKey } from "@solana/web3.js";
|
2021-10-05 11:30:05 -07:00
|
|
|
|
2022-08-26 09:49:37 -07:00
|
|
|
export function MetaplexNFTHeader({
|
2021-10-05 11:30:05 -07:00
|
|
|
nftData,
|
|
|
|
address,
|
|
|
|
}: {
|
|
|
|
nftData: NFTData;
|
|
|
|
address: string;
|
|
|
|
}) {
|
2022-03-04 18:35:35 -08:00
|
|
|
const collectionAddress = nftData.metadata.collection?.key;
|
|
|
|
const collectionMintInfo = useMintAccountInfo(collectionAddress);
|
|
|
|
const fetchAccountInfo = useFetchAccountInfo();
|
|
|
|
|
|
|
|
React.useEffect(() => {
|
|
|
|
if (collectionAddress && !collectionMintInfo) {
|
|
|
|
fetchAccountInfo(new PublicKey(collectionAddress));
|
|
|
|
}
|
|
|
|
}, [fetchAccountInfo, collectionAddress]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
|
|
|
2021-10-05 11:30:05 -07:00
|
|
|
const metadata = nftData.metadata;
|
2021-11-28 16:22:27 -08:00
|
|
|
const data = nftData.json;
|
2022-03-04 18:35:35 -08:00
|
|
|
const isVerifiedCollection =
|
|
|
|
metadata.collection != null &&
|
|
|
|
metadata.collection?.verified &&
|
|
|
|
collectionMintInfo !== undefined;
|
2021-10-05 11:30:05 -07:00
|
|
|
return (
|
2021-10-16 19:19:08 -07:00
|
|
|
<div className="row">
|
2021-11-28 12:49:22 -08:00
|
|
|
<div className="col-auto ms-2 d-flex align-items-center">
|
2021-11-28 16:22:27 -08:00
|
|
|
<ArtContent metadata={metadata} pubkey={address} data={data} />
|
2021-10-05 11:30:05 -07:00
|
|
|
</div>
|
2021-11-28 12:49:22 -08:00
|
|
|
<div className="col mb-3 ms-0.5 mt-3">
|
|
|
|
{<h6 className="header-pretitle ms-1">Metaplex NFT</h6>}
|
2021-10-05 11:30:05 -07:00
|
|
|
<div className="d-flex align-items-center">
|
2021-11-28 12:49:22 -08:00
|
|
|
<h2 className="header-title ms-1 align-items-center no-overflow-with-ellipsis">
|
2021-10-05 11:30:05 -07:00
|
|
|
{metadata.data.name !== ""
|
|
|
|
? metadata.data.name
|
|
|
|
: "No NFT name was found"}
|
|
|
|
</h2>
|
2021-10-16 19:14:50 -07:00
|
|
|
{getEditionPill(nftData.editionInfo)}
|
2022-03-09 13:44:12 -08:00
|
|
|
{isVerifiedCollection ? getVerifiedCollectionPill() : null}
|
2021-10-05 11:30:05 -07:00
|
|
|
</div>
|
2021-11-28 12:49:22 -08:00
|
|
|
<h4 className="header-pretitle ms-1 mt-1 no-overflow-with-ellipsis">
|
2021-10-05 11:30:05 -07:00
|
|
|
{metadata.data.symbol !== ""
|
|
|
|
? metadata.data.symbol
|
|
|
|
: "No Symbol was found"}
|
|
|
|
</h4>
|
|
|
|
<div className="mb-2 mt-2">
|
|
|
|
{getSaleTypePill(metadata.primarySaleHappened)}
|
|
|
|
</div>
|
|
|
|
<div className="mb-3 mt-2">{getIsMutablePill(metadata.isMutable)}</div>
|
|
|
|
<div className="btn-group">
|
|
|
|
<button
|
|
|
|
className="btn btn-dark btn-sm dropdown-toggle creators-dropdown-button-width"
|
|
|
|
type="button"
|
2021-11-28 12:49:22 -08:00
|
|
|
data-bs-toggle="dropdown"
|
2021-10-05 11:30:05 -07:00
|
|
|
aria-haspopup="true"
|
|
|
|
aria-expanded="false"
|
|
|
|
>
|
|
|
|
Creators
|
|
|
|
</button>
|
|
|
|
<div className="dropdown-menu mt-2">
|
|
|
|
{getCreatorDropdownItems(metadata.data.creators)}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-11-28 13:39:33 -08:00
|
|
|
type Creator = programs.metadata.Creator;
|
2021-10-05 11:30:05 -07:00
|
|
|
function getCreatorDropdownItems(creators: Creator[] | null) {
|
|
|
|
const CreatorHeader = () => {
|
|
|
|
const creatorTooltip =
|
|
|
|
"Verified creators signed the metadata associated with this NFT when it was created.";
|
|
|
|
|
|
|
|
const shareTooltip =
|
|
|
|
"The percentage of the proceeds a creator receives when this NFT is sold.";
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div
|
|
|
|
className={
|
|
|
|
"d-flex align-items-center dropdown-header creator-dropdown-entry"
|
|
|
|
}
|
|
|
|
>
|
2021-11-28 12:49:22 -08:00
|
|
|
<div className="d-flex font-monospace creator-dropdown-header">
|
2021-10-05 11:30:05 -07:00
|
|
|
<span>Creator Address</span>
|
|
|
|
<InfoTooltip bottom text={creatorTooltip} />
|
|
|
|
</div>
|
2021-11-28 12:49:22 -08:00
|
|
|
<div className="d-flex font-monospace">
|
|
|
|
<span className="font-monospace">Royalty</span>
|
2021-10-05 11:30:05 -07:00
|
|
|
<InfoTooltip bottom text={shareTooltip} />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const getVerifiedIcon = (isVerified: boolean) => {
|
|
|
|
const className = isVerified ? "fe fe-check" : "fe fe-alert-octagon";
|
2021-11-28 12:49:22 -08:00
|
|
|
return <i className={`ms-3 ${className}`}></i>;
|
2021-10-05 11:30:05 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
const CreatorEntry = (creator: Creator) => {
|
|
|
|
return (
|
2021-10-08 13:17:32 -07:00
|
|
|
<div
|
|
|
|
className={
|
2021-11-28 12:49:22 -08:00
|
|
|
"d-flex align-items-center font-monospace creator-dropdown-entry ms-3 me-3"
|
2021-10-08 13:17:32 -07:00
|
|
|
}
|
|
|
|
>
|
2021-10-05 11:30:05 -07:00
|
|
|
{getVerifiedIcon(creator.verified)}
|
|
|
|
<Link
|
2021-11-28 12:49:22 -08:00
|
|
|
className="dropdown-item font-monospace creator-dropdown-entry-address"
|
2021-10-05 11:30:05 -07:00
|
|
|
to={clusterPath(`/address/${creator.address}`)}
|
|
|
|
>
|
|
|
|
{creator.address}
|
|
|
|
</Link>
|
2021-11-28 12:49:22 -08:00
|
|
|
<div className="me-3"> {`${creator.share}%`}</div>
|
2021-10-05 11:30:05 -07:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
if (creators && creators.length > 0) {
|
|
|
|
let listOfCreators: JSX.Element[] = [];
|
|
|
|
|
|
|
|
listOfCreators.push(<CreatorHeader key={"header"} />);
|
|
|
|
creators.forEach((creator) => {
|
|
|
|
listOfCreators.push(<CreatorEntry key={creator.address} {...creator} />);
|
|
|
|
});
|
|
|
|
|
|
|
|
return listOfCreators;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
2021-11-28 12:49:22 -08:00
|
|
|
<div className={"dropdown-item font-monospace"}>
|
|
|
|
<div className="me-3">No creators are associated with this NFT.</div>
|
2021-10-05 11:30:05 -07:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-10-16 19:14:50 -07:00
|
|
|
function getEditionPill(editionInfo: EditionInfo) {
|
|
|
|
const masterEdition = editionInfo.masterEdition;
|
|
|
|
const edition = editionInfo.edition;
|
2021-10-05 11:30:05 -07:00
|
|
|
|
|
|
|
return (
|
2021-11-28 12:49:22 -08:00
|
|
|
<div className={"d-inline-flex ms-2"}>
|
|
|
|
<span className="badge badge-pill bg-dark">{`${
|
2021-10-05 11:30:05 -07:00
|
|
|
edition && masterEdition
|
|
|
|
? `Edition ${edition.edition.toNumber()} / ${masterEdition.supply.toNumber()}`
|
|
|
|
: masterEdition
|
|
|
|
? "Master Edition"
|
|
|
|
: "No Master Edition Information"
|
|
|
|
}`}</span>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function getSaleTypePill(hasPrimarySaleHappened: boolean) {
|
|
|
|
const primaryMarketTooltip =
|
|
|
|
"Creator(s) split 100% of the proceeds when this NFT is sold.";
|
|
|
|
|
|
|
|
const secondaryMarketTooltip =
|
|
|
|
"Creator(s) split the Seller Fee when this NFT is sold. The owner receives the remaining proceeds.";
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div className={"d-inline-flex align-items-center"}>
|
2021-11-28 12:49:22 -08:00
|
|
|
<span className="badge badge-pill bg-dark">{`${
|
2021-10-05 11:30:05 -07:00
|
|
|
hasPrimarySaleHappened ? "Secondary Market" : "Primary Market"
|
|
|
|
}`}</span>
|
|
|
|
<InfoTooltip
|
|
|
|
bottom
|
|
|
|
text={
|
|
|
|
hasPrimarySaleHappened ? secondaryMarketTooltip : primaryMarketTooltip
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function getIsMutablePill(isMutable: boolean) {
|
|
|
|
return (
|
2021-11-28 12:49:22 -08:00
|
|
|
<span className="badge badge-pill bg-dark">{`${
|
2021-10-05 11:30:05 -07:00
|
|
|
isMutable ? "Mutable" : "Immutable"
|
|
|
|
}`}</span>
|
|
|
|
);
|
|
|
|
}
|
2022-03-04 18:35:35 -08:00
|
|
|
|
|
|
|
function getVerifiedCollectionPill() {
|
|
|
|
const onchainVerifiedToolTip =
|
|
|
|
"This NFT has been verified as a member of an on-chain collection. This tag guarantees authenticity.";
|
|
|
|
return (
|
|
|
|
<div className={"d-inline-flex align-items-center ms-2"}>
|
|
|
|
<span className="badge badge-pill bg-dark">{"Verified Collection"}</span>
|
|
|
|
<InfoTooltip bottom text={onchainVerifiedToolTip} />
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|