UNPKG

@mojito-inc/secondary-market

Version:

Mojito secondary market is the platform to purchase NFT.

759 lines (676 loc) 22.9 kB
<br /> <h1 align="center">☁️ Mojito Modules - Secondary Marketplace</h1> <br /><br /> <p align="center"> 👨‍💻 React components for the Mojito Platform, Reference App and third-party projects, including Mojito's Secondary Marketplace <br /> <p align="center"> Version: 1.0.0 </p> <br /> ## Using this library in your project You can install this project with one of these commands: npm install @mojito-inc/secondary-market </br> yarn add @mojito-inc/secondary-market <br /> Once the package is installed, you can import the library using import; ### For Theme Configuration &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;You can create a theme folder inside a /src folder.</br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Inside theme folder, Create a file <b>index.ts</b>.</br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Inside the <b>index.ts</b> file, you can copy and paste the below code. ``` import { createTheme } from '@mui/material'; export const theme = createTheme({ typography: { fontFamily: 'Sneak', }, components: { MuiTextField: { styleOverrides: { root: { '& input::-webkit-outer-spin-button, & input::-webkit-inner-spin-button': { display: 'none', }, '& input[type=number]': { MozAppearance: 'textfield', }, }, }, }, MuiCssBaseline: { styleOverrides: ` @font-face { font-family: "Sneak"; font-style: normal; font-display: swap; font-weight: 400; text-transform: none; font-size: 16px; } `, }, MuiButton: { styleOverrides: { root: { fontFamily: 'Sneak', textTransform: 'none', borderRadius: '4px', fontWeight: 500, fontSize: '16px', backgroundColor: '#6563FD', color: '#fff', '&:hover': { backgroundColor: '#6563FD', color: '#fff', opacity: 0.5, }, '&:disabled': { backgroundColor: '#F5F5F5', color: '#BDBDBD', }, }, }, }, MuiDialog: { styleOverrides: { paper: { border: '1px solid #D7D8DB', boxShadow: '0px 8px 16px rgba(0, 0, 0, 0.08)', borderRadius: '4px', }, }, }, MuiTooltip: { styleOverrides: { tooltip: { fontSize: '12px', color: '#ffffff', backgroundColor: '#000000', padding: '6px 8px 6px 8px', }, arrow: { color: '#000000', }, }, }, MuiDivider: { variants: [ { props: { orientation: 'horizontal' }, style: { ':before': { borderTop: 'thin solid #D7D8DB', }, ':after': { borderTop: 'thin solid #D7D8DB', }, }, }, ], }, }, palette: { primary: { main: '#6563FD', light: '#C9C8FE', dark: '#0703F7', }, secondary: { main: '#A6FF00', light: '#C9FF66', dark: '#95E600', }, appDefaultColor: { primary: { dark: '#FFFFFF', light: '#FFFFFF80', }, secondary: { dark: '#000000', light: '#00000080', }, }, border: { dark: '#616161', light: '#E0E0E0', }, background: { default: '#000', paper: '#fff', }, text: { primary: '#000', }, grey: { 50: '#FAFAFA', 100: '#F5F5F5', 200: '#EEEEEE', 300: '#E0E0E0', 400: '#BDBDBD', 500: '#9E9E9E', 600: '#757575', 700: '#616161', 800: '#424242', 900: '#212121', }, divider: '#fff', toastError: { 50: '#FEE3E5', 100: '#FDBBBD', 200: '#E2807A', 300: '#CD564F', 400: '#D0372E', 500: '#CE2818', 600: '#BF1E18', 700: '#AD1414', 800: '#9F0C10', 900: '#90030F', }, toastSuccess: { 50: '#E7EFE8', 100: '#CFDFD1', 200: '#B7CFB9', 300: '#9FBFA2', 400: '#6EA074', 500: '#3E8045', 600: '#0E6017', 700: '#0D5615', 800: '#0B4D12', 900: '#0A4310', 1000: '#1BB82D', 1100: '#D9F9DD', }, toastWarning: { 50: '#FFFFE5', 100: '#FFFEC0', 200: '#FCFB99', 300: '#F8F676', 400: '#F5F15C', 500: '#F0EB47', 600: '#FBDF47', 700: '#FDC740', 800: '#FCAD36', 900: '#F98028', }, }, }); ``` ### For Custom Theme Configuration &nbsp;&nbsp;&nbsp;&nbsp;Inside the theme folder, create a file <b>mui.d.ts</b>.</br> &nbsp;&nbsp;&nbsp;&nbsp;Inside the <b>mui.d.ts</b> file, copy and paste the below code to customize your theme. ``` import '@mui/material/styles'; interface SecondaryTheme { dark?: string; light?: string; } declare module '@mui/material/styles' { export interface Palette { appDefaultColor?: { primary?: SecondaryTheme, secondary?: SecondaryTheme } border?: SecondaryTheme toastError?: ColorPartial toastSuccess?: ColorPartial toastWarning?: ColorPartial } // allow configuration using `createTheme` export interface PaletteOptions { appDefaultColor?: { primary?: SecondaryTheme, secondary?: SecondaryTheme } border?: SecondaryTheme toastError?: ColorPartial toastSuccess?: ColorPartial toastWarning?: ColorPartial } } ``` ### For development URL baseURL = https://api-dev.mojito.xyz/query ### For production URL baseURL = https://api.mojito.xyz/query ``` import { SecondaryMarketProvider } from "@mojitoinc/secondary-market"; import { ThemeProvider } from '@mui/material/styles'; const AuthenticationProvider = ({ children }: AuthenticationProviderProps) => { const sessionData = sessionStorage.getItem('AuthToken'); const tokenData = sessionData ? JSON.parse(sessionData ?? '') : null; const client = useMemo( () => ({ uri: baseURL, token: tokenData ? `Bearer ${ tokenData }` : undefined, }), [tokenData], ); return ( <ThemeProvider theme={ theme }> <SecondaryMarketProvider theme={ theme } clientOptions={ client }> { children } </SecondaryMarketProvider> </ThemeProvider> ) } export default AuthenticationProvider; ``` </br> |Param |type | Description |:--- | --- | :---:| |uri| string| |theme| object | Create a theme using MUI createTheme |token| string| </br> After setup with SecondaryMarketProvider following the api are 1. [Product details page](#ProductDetailPage) 2. [List Item](#ListItem) 3. [Accept And Reject Offer](#AcceptAndRejectOffer) 4. [Buy Now](#BuyNow) 5. [Make Offer](#MakeOffer) ### ProductDetailPage The Product Details Page (PDP) is a crucial component of our project that provides users with comprehensive information about a specific product. This documentation will outline the key features and functionalities of the PDP, including the display of provenance, metadata, network details, offers, traits, and the ability to perform actions such as making offers, buying now, listing items, and accepting offers. ``` import { ProductDetailPage } from "@mojitoinc/secondary-market"; const ProductDetail = () => { const configuration = { orgId: ORG_ID, infuraId: INFURA_ID, paperClientId: PAPER_CLIENT_ID, walletOptions: { enableMetamask: true, enableWalletConnect: true, enableEmail: true, }, }; const Image = { ethIcon: Images.ETH_ICON.src, logo: Images.LOGO_ICON.src, metamask: Images.METAMASK.src, walletConnect: Images.WALLET_CONNECT.src, loader: Images.LOADER.src, }; return ( <ProductDetailPage config={ configuration } Image={ Image } walletDetails={ walletDetails } onClickDisconnectWallet={ onClickDisconnectWallet } onConnectWallet={ onConnectWallet } onRefetchBalance={ onRefetchBalance } tokenDetails={ tokenDetails } /> ) } export default ProductDetail; ``` |Param |type | Required | Description |:--- | --- | :---:| :---:| |configuration| Object|✅| [configuration](#configuration) |Image| Object |✅| [Image](#Image) |walletDetails| Object |✅| [walletDetails](#walletDetails) |onClickDisconnectWallet| function |✅| |onConnectWallet| function |✅| |onRefetchBalance| function |✅| |tokenDetails| Object |✅| [tokenDetails](#tokenDetails) #### interface ##### configuration |Param |type | Required | Description |:--- | --- | :---:| :---:| |orgId| string|✅| | |infuraId | string |✅| | |paperClientId | string |✅| | |walletOptions | Object |✅| [walletOptions](#walletOptions)| ##### walletOptions |Param |type | Required | Description |:--- | --- | :---:| :---:| |enableMetamask| boolean|✅| | |enableWalletConnect | boolean |✅| | |enableEmail | boolean |✅| | ##### Image |Param |type | Required | Description |:--- | --- | :---:| :---:| |ethIcon| string|✅| | |logo | string |✅| | |metamask | string |✅| | |walletConnect | string |✅| | |loader | string |✅| | |wethIcon | string |✅| | |maticIcon | string |✅| | |placeHolderImage | string | | | ##### walletDetails |Param |type | Required | Description |:--- | --- | :---:| :---:| |walletAddress| string|✅| | |networkDetails | Object |✅| [networkDetails](#networkDetails)| |providerType | string |✅| | |balance | Object |✅| [balance](#balance)| |open | boolean |✅| | |disConnect | boolean |✅| | |refetchBalance | boolean |✅| | ##### balance |Param |type | Required | Description |:--- | --- | :---:| :---:| |native| number|✅| | |nonNative | number |✅| | ##### networkDetails |Param |type | Required | Description |:--- | --- | :---:| :---:| |id| string|✅| | |chainID | number |✅| | |isTestnet | boolean |✅| | |name | string |✅| | ##### tokenDetails |Param |type | Required | Description |:--- | --- | :---:| :---:| |onChainTokenID| string|✅| | |contractAddress | string |✅| | |itemId | string |✅| | </br> ### ListItem &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ListItem outlines the process of making an NFT available for sale or auction, thereby entering it into the marketplace ``` import { ListItemContainer } from '@mojitoinc/secondary-market'; const ListItem = () => { const configuration = { orgId: ORG_ID, infuraId: INFURA_ID, paperClientId: PAPER_CLIENT_ID, walletOptions: { enableMetamask: true, enableWalletConnect: true, enableEmail: true, }, }; const Image = { ethIcon: Images.ETH_ICON.src, logo: Images.LOGO_ICON.src, metamask: Images.METAMASK.src, walletConnect: Images.WALLET_CONNECT.src, loader: Images.LOADER.src, }; return ( <ListItemContainer open={ openListItemModal } image={ Image } config={ configuration } tokenDetails={ tokenDetails } isRemoveListing={ isRemoveListing } walletDetails={ walletDetails } onClickViewItem={ onCloseListItemModal } onClickBackToMarketPlace={ onCloseListItemModal } onConnectWallet={ onConnectWallet } onCloseModal={ onCloseListItemModal } /> ); }; export default ListItem; ``` |Param |type | Required | Description |:--- | --- | :---:| :---:| |config| Object|✅| [config](#configuration) |image| Object |✅| [Image](#Image) |walletDetails| Object |✅| [walletDetails](#walletDetails) |open| boolean|✅| |tokenDetails| Object|✅| [tokenDetails](#tokenDetails) |isRemoveListing| boolean|✅| |onCloseModal| function|✅| To close the modal |onClickViewItem| function|✅| For custom redirection |onClickBackToMarketPlace| function|✅| For custom redirection |onConnectWallet| function|✅| </br> ### AcceptAndRejectOffer Accepting an offer: <br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;It outlines the process of accepting an offer for an NFT, discussing the necessary steps and platforms commonly used for managing offers. It covers topics such as negotiation, pricing considerations, and potential implications of accepting an offer.</br></br> Rejecting an offer:</br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The content provides insights into the reasons one might choose to reject an offer for an NFT. It discusses factors such as pricing misalignment, personal preferences, strategic decision-making, and the potential impact of rejecting an offer on the relationship with the potential buyer. ``` const AcceptAndRejectOfferPage = () => { const configuration = { orgId: ORG_ID, infuraId: INFURA_ID, paperClientId: PAPER_CLIENT_ID, walletOptions: { enableMetamask: true, enableWalletConnect: true, enableEmail: true, }, }; const Image = { ethIcon: Images.ETH_ICON.src, logo: Images.LOGO_ICON.src, metamask: Images.METAMASK.src, walletConnect: Images.WALLET_CONNECT.src, loader: Images.LOADER.src, }; return ( <AcceptAndRejectOffer open={ openOfferModal } config={ configuration } image={ Image } tokenDetails={ tokenDetails } orderId={ orderId } isRejectOffer={ isRejectOffer } walletDetails={ walletDetails } onClickViewItem={ onCloseOfferModal } onClickBackToMarketPlace={ onCloseOfferModal } onConnectWallet={ onConnectWallet } onCloseModal={ onCloseOfferModal } /> ); }; export default AcceptAndRejectOfferPage; ``` |Param |type | Required | Description |:--- | --- | :---:| :---:| |open| boolean|✅| |image| Object|✅| [Image](#Image) |config| Object|✅| [config](#configuration) |tokenDetails| Object|✅| [tokenDetails](#tokenDetails) |isRejectOffer| boolean|✅| |orderId| string|✅| |walletDetails| Object|✅| [walletDetails](#walletDetails) |onCloseModal| function|✅| |onClickViewItem| function|✅| |onConnectWallet| function|✅| |onClickBackToMarketPlace| function| | </br> ### BuyNow &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BuyNow enables buyers to instantly purchase an NFT at a fixed price, without engaging in an auction or negotiation process. ``` const BuyNowPage = () => { const configuration = { orgId: ORG_ID, infuraId: INFURA_ID, paperClientId: PAPER_CLIENT_ID, walletOptions: { enableMetamask: true, enableWalletConnect: true, enableEmail: true, }, }; const Image = { ethIcon: Images.ETH_ICON.src, logo: Images.LOGO_ICON.src, metamask: Images.METAMASK.src, walletConnect: Images.WALLET_CONNECT.src, loader: Images.LOADER.src, }; return ( <BuyNow open={ openBuyNowModal } config={ configuration } image={ Image } tokenDetails={ tokenDetails } walletDetails={ walletDetails } onClickViewItem={ onCloseBuyNowModal } onClickBackToMarketPlace={ onCloseBuyNowModal } onClickConnectWallet={ onConnectWallet } onClickDisconnectWallet={ onClickDisconnectWallet } onRefetchBalance={ onRefetchBalance } onCloseModal={ onCloseBuyNowModal } /> ); }; export default BuyNowPage; ``` |Param |type | Required | Description |:--- | --- | :---:| :---:| | open| boolean|✅| |image| Object|✅| [Image](#Image) |config| Object|✅| [config](#configuration) |tokenDetails| Object|✅| [tokenDetails](#tokenDetails) |walletDetails| Object|✅| [walletDetails](#walletDetails) |onCloseModal |function |✅| To close the Modal |onClickViewItem |function |✅| For custom redirection |onClickConnectWallet | function |✅| To connect wallet |onClickDisconnectWallet| function |✅| To disconnect Wallet |onClickBackToMarketPlace| function | | For custom redirection |onRefetchBalance| function || To get new Balance </br> ### MakeOffer &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MakeOffer enables potential buyers to express their interest in purchasing an NFT by proposing a price they are willing to pay. ``` const MakeOfferPage = () => { const configuration = { orgId: ORG_ID, infuraId: INFURA_ID, paperClientId: PAPER_CLIENT_ID, walletOptions: { enableMetamask: true, enableWalletConnect: true, enableEmail: true, }, }; const Image = { ethIcon: Images.ETH_ICON.src, logo: Images.LOGO_ICON.src, metamask: Images.METAMASK.src, walletConnect: Images.WALLET_CONNECT.src, loader: Images.LOADER.src, }; return ( <MakeOffer open={ openMakeOfferModal } config={ configuration } image={ Image } tokenDetails={ tokenDetails } offerOrderId={ selectedOffer?.id || '' } isCancelOffer={ isCancelOffer } walletDetails={ walletDetails } onClickViewItem={ onCloseMakeOfferModal } onClickBackToMarketPlace={ onCloseMakeOfferModal } onRefetchBalance={ onRefetchBalance } onConnectWallet={ onConnectWallet } onCloseModal={ onCloseMakeOfferModal } /> ); }; export default MakeOfferPage; ``` |Param |type | Required | Description |:--- | --- | :---:| :---:| |open | boolean |✅| |image| Object|✅| [Image](#Image) |config| Object|✅| [config](#configuration) |tokenDetails| Object|✅| [tokenDetails](#tokenDetails) |isCancelOffer| boolean|✅| |offerOrderId| string|✅| |walletDetails| Object|✅| [walletDetails](#walletDetails) |onCloseModal| function|✅| To close the Modal |onClickViewItem| function| ✅| For custom redirection |onClickBackToMarketPlace| function | | For custom redirection |onConnectWallet| function|✅| |onRefetchBalance| function| | To get new Balance </br> ### Account Wallet &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Account Wallet feature page allows user to view the purchased NFTs and the invoices generated ``` const Wallets = () => { enum ListingType { SALE = 'sale', CLAIMABLE = 'claimable', } const config = { orgId: ORG_ID, paperClientId: PAPER_CLIENT_ID, projectId: PROJECT_ID, walletOptions: { enableMetamask: true, enableWalletConnect: true, enableEmail: true, }, }; const Image = { ethIcon: Images.ETH_ICON.src, logo: Images.LOGO_ICON.src, metamask: Images.METAMASK.src, walletConnect: Images.WALLET_CONNECT.src, loader: Images.LOADER.src, wethIcon: Images.WETH_ICON.src, maticIcon: Images.MATIC.src, placeHolderImage: Images.PLACEHOLDER.src, }; const menusToDisplay=['Edit Listing', 'Transfer NFT', 'Copy Link', 'Download Artwork', 'Download Media']; return ( <WalletsPage walletDetails={ walletDetails } config={ config } Image={ Image } tabConfig={ [ { tabLabel: 'Wallet', showTab: true, }, { tabLabel: 'Activity', showTab: true, }, { tabLabel: 'Account', showTab: true, }, ] } showViewItem showInvoice showMenu menuToDisplay={ menusToDisplay } showSearch={ false } showSort={ false } showRefresh={ false } hideWalletBalance showFilter content={{ noDataContent: '', disconnectText: 'Disconnect Wallet', copyAddressText: 'Copy wallet address', }} listingType={ ListingType?.CLAIMABLE } onClickLogout={ onClickDisconnectWallet } onConnectWallet={ onConnectWallet } onClickCard={ onClickCard } onViewItem={ onClickViewItem } /> ); }; export default Wallets; ``` |Param |type | Required | Description |:--- | --- | :---:| :---:| |walletDetails| Object|✅| [walletDetails](#walletDetails) |config| Object|✅| [config](#configuration) |image| Object|✅| [Image](#Image) |showViewItem| boolean | | To show View Item button in Activity tab |showInvoice| boolean | | To show invoice download option in Activity tab |hideWalletBalance| boolean | | To hide balance details in Account tab |showSearch| boolean | | To hide or show search in wallet tab |showSort| boolean | | To hide or show sort in wallet tab |showRefresh| boolean | | To hide or show refresh button in wallet tab |showMenu| boolean | | if true we can see menu in wallet tab else it will not show |menusToDisplay| Object | | to specify the menus when clicked on three dot menu under wallet tab |listingType| enum | | for sale listing user can give ListingType?.SALE and for claimable listing user can give ListingType?.CLAIMABLE |content| object | | Custom text changes |tabConfig| object | | To customize the tab name and the tabs, by default all the three tabs will show |filterByStatus| string[] | | To fetch invoice by status |onClickLogout| function |✅| To disconnect Wallet |onConnectWallet| function|✅| To connect Wallet |onClickCard| function | | For custom redirection |onViewItem| function | | For custom redirection </br>