├── .env.example ├── .eslintrc.json ├── .github └── workflows │ └── release-please.yml ├── .gitignore ├── .prettierrc ├── .vscode └── settings.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── REQUIREMENTS.md ├── compiled-lang ├── cs-CZ.json ├── en-US.json ├── es-ES.json └── pt-BR.json ├── config ├── app.development.json ├── app.json ├── default.collectionlist.json └── default.tokenlist.json ├── docs └── ADD_LANGUAGE.md ├── funding.json ├── lang ├── cs-CZ.json ├── en-US.json ├── es-ES.json └── pt-BR.json ├── next-env.d.ts ├── next-seo.config.ts ├── next.config.js ├── package.json ├── pages ├── 404.tsx ├── _app.tsx ├── _document.tsx ├── api │ └── token.ts ├── asset │ └── [network] │ │ └── [address] │ │ └── [id].tsx ├── collection │ └── [network] │ │ └── [address] │ │ └── index.tsx ├── collections.tsx ├── index.tsx ├── order │ ├── [network] │ │ └── [hash].tsx │ └── create.tsx └── wallet │ ├── connect.tsx │ ├── index.tsx │ ├── nfts.tsx │ └── orders.tsx ├── public ├── assets │ ├── images │ │ ├── cat-hero.svg │ │ ├── connect-wallet-background.svg │ │ ├── ethereum.svg │ │ ├── icons │ │ │ ├── arbitrum.png │ │ │ ├── avax.png │ │ │ ├── bnb.svg │ │ │ ├── eth.png │ │ │ ├── fantom.svg │ │ │ ├── optimism.svg │ │ │ ├── polygon.png │ │ │ └── setting-2.svg │ │ ├── market-logo.svg │ │ ├── metamask-fox.svg │ │ ├── trade-button.svg │ │ └── walletconnect-circle-blue.svg │ └── kittygotchi │ │ ├── banner.svg │ │ ├── banner_bsc.svg │ │ ├── banner_eth.svg │ │ ├── banner_polygon.svg │ │ └── kittygotchi_banner.jpg ├── favicon.ico ├── robots.txt ├── sitemap-0.xml └── sitemap.xml ├── src ├── actions │ └── index.ts ├── components │ ├── AppDialogTitle.tsx │ ├── AppDrawer.tsx │ ├── AppErrorBoundary.tsx │ ├── AppFeePercentageSpan.tsx │ ├── AppIntlProvider.tsx │ ├── CopyIconButton.tsx │ ├── DatetimeFromNowSpan.tsx │ ├── Footer.tsx │ ├── Icon.tsx │ ├── LazyYoutubeFrame.tsx │ ├── Link.tsx │ ├── MomentFromNow.tsx │ ├── Navbar.tsx │ ├── PageHeader.tsx │ ├── SidebarFilters.tsx │ ├── SidebarFiltersAccordion.tsx │ ├── SidebarFiltersContent.tsx │ ├── TransactionTitle.tsx │ ├── WalletButton.tsx │ ├── dialogs │ │ ├── AppTransactionsDialog.tsx │ │ ├── AssetApprovalDialog.tsx │ │ ├── ConnectWalletDialog.tsx │ │ ├── ImportTokenDialog.tsx │ │ ├── SelectCurrencyDialog.tsx │ │ ├── SelectLanguageDialog.tsx │ │ ├── SelectNetworkDialog.tsx │ │ ├── SignMessageDialog.tsx │ │ ├── SwitchNetworkDialog.tsx │ │ └── TransactionDialog.tsx │ ├── icons │ │ ├── ArrowSwap.tsx │ │ ├── Calendar.tsx │ │ ├── CardTick.tsx │ │ ├── CloseCircle.tsx │ │ ├── DollarSquare.tsx │ │ ├── Ethereum.tsx │ │ ├── Export.tsx │ │ ├── Filter.tsx │ │ ├── Heart.tsx │ │ ├── MoneyReceive.tsx │ │ ├── MoneySend.tsx │ │ ├── Notification.tsx │ │ ├── ReceiptText.tsx │ │ ├── RotateRight.tsx │ │ ├── Setting.tsx │ │ ├── Share.tsx │ │ ├── Tag.tsx │ │ ├── TickCircle.tsx │ │ └── Wallet.tsx │ ├── layouts │ │ └── main.tsx │ └── transactions │ │ └── Updater.tsx ├── connectors │ ├── metamask.ts │ └── walletConnect.ts ├── constants │ ├── abis │ │ └── index.ts │ ├── chain.ts │ ├── chains.ts │ ├── enum.ts │ └── index.ts ├── createEmotionCache.ts ├── hooks │ ├── app.ts │ ├── balances.ts │ ├── blockchain.ts │ ├── currency.ts │ ├── misc.ts │ └── nft.ts ├── index.d.ts ├── modules │ ├── favorites │ │ └── components │ │ │ ├── FavoriteAssetsSection.tsx │ │ │ └── RemoveFavoriteDialog.tsx │ ├── home │ │ └── components │ │ │ ├── ActionButton.tsx │ │ │ ├── ActionButtonsSection.tsx │ │ │ ├── CallToActionSection.tsx │ │ │ ├── CollectionCard.tsx │ │ │ ├── CollectionCardWithData.tsx │ │ │ ├── CollectionsSection.tsx │ │ │ ├── ConnectWalletButton.tsx │ │ │ ├── FeaturedSection.tsx │ │ │ └── VideoSection.tsx │ ├── nft │ │ └── components │ │ │ ├── AssetAttributePaper.tsx │ │ │ ├── AssetCard.tsx │ │ │ ├── AssetCardWidthData.tsx │ │ │ ├── AssetDetails.tsx │ │ │ ├── AssetHead.tsx │ │ │ ├── AssetIframe.tsx │ │ │ ├── AssetImage.tsx │ │ │ ├── AssetLeftSection.tsx │ │ │ ├── AssetList.tsx │ │ │ ├── AssetMedia.tsx │ │ │ ├── AssetPageActions.tsx │ │ │ ├── AssetPageTitle.tsx │ │ │ ├── AssetPricePaper.tsx │ │ │ ├── AssetRightSection.tsx │ │ │ ├── AssetTabs.tsx │ │ │ ├── CollectionHeader.tsx │ │ │ ├── CollectionPageHeader.tsx │ │ │ ├── DurationSelect.tsx │ │ │ ├── dialogs │ │ │ ├── ConfirmBuyDialog.tsx │ │ │ ├── MakeListingDialog.tsx │ │ │ ├── MakeOfferDialog.tsx │ │ │ └── ShareDialog.tsx │ │ │ └── tables │ │ │ ├── ListingsTable.tsx │ │ │ ├── ListingsTableRow.tsx │ │ │ ├── OffersTable.tsx │ │ │ ├── OffersTableRow.tsx │ │ │ └── TableSkeleton.tsx │ ├── orders │ │ └── components │ │ │ ├── OrderLeftSection.tsx │ │ │ ├── OrderPageActions.tsx │ │ │ ├── OrderRightSection.tsx │ │ │ ├── dialogs │ │ │ ├── ImportAssetDialog.tsx │ │ │ └── OrderCreatedDialog.tsx │ │ │ └── forms │ │ │ ├── MakeListingForm.tsx │ │ │ └── MakeOfferForm.tsx │ └── wallet │ │ └── components │ │ ├── TransactionsTable.tsx │ │ ├── TransactionsTableRow.tsx │ │ ├── WalletActionButton.tsx │ │ ├── WalletBalancesTable.tsx │ │ ├── WalletButton.tsx │ │ ├── WalletOrders.tsx │ │ ├── WalletOrdersTable.tsx │ │ ├── WalletOrdersTableRow.tsx │ │ ├── WalletTableRow.tsx │ │ ├── WalletTotalBalance.tsx │ │ ├── WalletTotalBalanceContainer.tsx │ │ └── dialogs │ │ └── ReceiveDialog.tsx ├── services │ ├── app.ts │ ├── balances.ts │ ├── blockchain.ts │ ├── currency.ts │ ├── multical.ts │ ├── nft.ts │ └── providers.ts ├── state │ └── atoms.ts ├── theme.ts ├── themes │ ├── index.ts │ └── kittygotchi.ts ├── types │ ├── actions.ts │ ├── app.ts │ ├── blockchain.ts │ ├── chains.ts │ ├── config.ts │ ├── nft.ts │ └── orderbook.ts └── utils │ ├── blockchain.ts │ ├── browser.ts │ ├── intl.ts │ ├── ipfs.ts │ ├── nfts.ts │ ├── numbers.ts │ ├── token.ts │ └── types.ts ├── tsconfig.json └── yarn.lock /.env.example: -------------------------------------------------------------------------------- 1 | NEXT_PUBLIC_TRANSAK_API_KEY= 2 | INFURA_API_KEY= -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /.github/workflows/release-please.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - main 5 | name: release-please 6 | jobs: 7 | release-please: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: google-github-actions/release-please-action@v3 11 | with: 12 | release-type: node 13 | package-name: release-please-action 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env.local 30 | .env.development.local 31 | .env.test.local 32 | .env.production.local 33 | .env.development 34 | .env.production 35 | .env 36 | 37 | # vercel 38 | .vercel 39 | 40 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "singleQuote": true, 4 | "jsxSingleQuote": false, 5 | "useTabs": false 6 | } 7 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "telemetry.enableTelemetry": false, 3 | "files.watcherExclude": { 4 | "**/.git/objects/**": true, 5 | "**/.git/subtree-cache/**": true, 6 | "**/node_modules/**": true, 7 | "**/env/**": true, 8 | "**/venv/**": true, 9 | "env-*": true 10 | }, 11 | "[jsonc]": { 12 | "editor.defaultFormatter": "esbenp.prettier-vscode" 13 | }, 14 | "editor.formatOnSave": true, 15 | "editor.tabSize": 2, 16 | "typescript.updateImportsOnFileMove.enabled": "always", 17 | "window.zoomLevel": 1, 18 | "javascript.updateImportsOnFileMove.enabled": "always" 19 | } 20 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [0.0.2](https://github.com/DexKit/open-nft-marketplace/compare/v0.0.1...v0.0.2) (2023-02-01) 4 | 5 | 6 | ### Bug Fixes 7 | 8 | * **lang:** remove non translated file ([2a1095f](https://github.com/DexKit/open-nft-marketplace/commit/2a1095f413e8c064967c96c710f2bf7b0c6797bc)) 9 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thank you for your interest in contributing to the open nft marketplace. 4 | 5 | # Development 6 | 7 | ## Running the interface locally 8 | 9 | Using yarn 10 | 11 | 1. clone this repo with `git clone https://github.com/DexKit/open-nft-marketplace.git` 12 | 2. run `yarn` once to install dependencies 13 | 3. finally run `yarn dev` 14 | 15 | ## How to Contribute 16 | 17 | You can contribute creating issues on this repo with features that you want to be implemented, if the issue is of high community interest, anyone is open to contribute and implement it. 18 | 19 | If you implemented an issue requested by the community, please open a pull request against the main branch, the maintainer will evaluate as soon as possible 20 | 21 | This is list of welcome contributions to this repo: 22 | 23 | - [Adding languages](./docs/ADD_LANGUAGE.md) 24 | - Fix language typo's 25 | - bug fix's reporting 26 | - Add tests 27 | 28 | ## Features Discussion 29 | 30 | If you would to discuss first if an issue should be open, there is a discord channel on DexKit for it, check it out at [Open NFT Support](https://discord.gg/FnkrFAY7Za) 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NFT Marketplace [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Open%20source%20nft%20marketplace:&url=https://github.com/DexKit/open-nft-marketplace) 2 | 3 | [![NFT marketplace](https://img.youtube.com/vi/9UxtgAkNG1k/0.jpg)](https://www.youtube.com/watch?v=9UxtgAkNG1k 'Marketplace by DexKit') 4 | 5 | This marketplace is the DexKit open source showcase on how to use 0x v4 nft smart contracts on a production app. Additionally, we are building a [zero code solution](https://whitelabel-nft.dexkit.com/admin/setup) with premium features to help artists deploy their own marketplace in an easy and secure way. Check our docs about it [here](https://docs.dexkit.com/defi-products/nft-marketplace/overview). 6 | 7 | On this marketplace you can make offers and listings of ERC721 Tokens on the chains supported by 0x smart contracts, namely: Ethereum, Binance Smart Chain, Polygon, Fantom, Avalanche, Celo and Optimism. 8 | 9 | # How to Start 10 | 11 | clone this repo 12 | 13 | ``` 14 | git clone https://github.com/DexKit/open-nft-marketplace.git 15 | ``` 16 | 17 | Install it: 18 | 19 | ```sh 20 | yarn 21 | ``` 22 | 23 | Create an .env file with INFURA_API_KEY set with your Infura API key and then run the app 24 | 25 | ```sh 26 | yarn dev 27 | ``` 28 | 29 | # Contributing 30 | 31 | Check [Contributing](CONTRIBUTING.md) for a more in depth way how to contribute. 32 | 33 | # Deployment 34 | 35 | We recommend Vercel to deploy this app, after you made your changes on the app.json config file, just use the button below: 36 | 37 | [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FDexKit%2Fopen-nft-marketplace&env=INFURA_API_KEY) 38 | 39 | Note that you need to set up INFURA_API_KEY to Next js be able to generate pages. 40 | 41 | # Tech used 42 | 43 | Started from [NEXT JS + Material UI+ Typescript + Boilerplat](https://github.com/mui/material-ui/tree/master/examples/nextjs-with-typescript) 44 | 45 | Additionally we use trader sdk to handle nft smart contract interactions, react query to handle all http and blockchain requests, format js for internalization, web3 react to handle wallet logic. You can check our requirements [here](REQUIREMENTS.md). 46 | 47 | # Roadmap 48 | 49 | We will be adding any new evm network that 0x smart contracts will support. 50 | 51 | It is also planned to extract all common hooks and state used to interact with the blockchain to a library repo. 52 | 53 | # Customization 54 | 55 | If you need a zero code solution we are building one currently in beta at [wizard](https://whitelabel-nft.dexkit.com/admin/setup), check our [docs](https://docs.dexkit.com/defi-products/nft-marketplace/overview) as well about it. Instead, if you want to deploy your own custom solution using this repo, please fork it, update the app.json file accordingly on the config folder and then deploy on Vercel (Recommended) or Heroku. 56 | 57 | # Missing feature? 58 | 59 | We welcome missing features, but take in mind that this repo is intended to be a base app for any dev to start working on, if it makes sense to have that feature on this base app we will include, if it is considered a premium feature, we will be including on our premium marketplace which uses this one as a base. 60 | 61 | We at the moment consider premium features as follows: 62 | 63 | - [ ] - NFT trading history 64 | 65 | - [ ] - Artist page 66 | 67 | - [ ] - Cache optimizations 68 | 69 | - [ ] - Fetch NFT and token balances via api without the need to import, using Alchemy for instance 70 | 71 | - [ ] - Swap ERC20 <-> ERC20 tokens 72 | 73 | - [ ] - Collection level stats like orders, max supply, floor price, number of trades 74 | 75 | - [ ] - Improved SEO 76 | 77 | # Acknowledgements 78 | 79 | We would like to thank ZRX project for these amazing tools and ZRX DAO for the support on building this open source app. 80 | 81 | # Wanna talk about this repo 82 | 83 | Join our dedicated channel [Open NFT Support](https://discord.gg/FnkrFAY7Za) 84 | -------------------------------------------------------------------------------- /REQUIREMENTS.md: -------------------------------------------------------------------------------- 1 | # REQUIREMENTS 2 | 3 | DexKit Whitelabel Marketplace will use the follow technologies: 4 | 5 | - NEXT js - for handle SEO and app loading 6 | - Web3React - for web3 wallet management 7 | - TraderSDK - for easy swaps management using 0x behind the hood 8 | - Material UI - battle tested framework and easily configurable 9 | - TheGraph - Orders history and onchain orders discovery 10 | - ReactQuery - for fetching APIS and mutations 11 | - Typescript - for easy typings 12 | 13 | ## APP structure 14 | 15 | The Apps follows a standard structure by modules, being each module planned to act independently 16 | src/ 17 | 18 | - hooks 19 | - services 20 | - constants 21 | - components 22 | - utils 23 | - themes 24 | - actions 25 | - state 26 | - types 27 | - conectors 28 | - modules 29 | - favories 30 | - home 31 | - orders 32 | - nft 33 | - wallet 34 | 35 | Each module is structured as follows: 36 | 37 | - components - pure components 38 | - constants - constants used on this module 39 | - hooks - act as the connection between services and pages 40 | - services - async fetching and outside logic 41 | - pages - presentation 42 | - utils - pure functions 43 | - tests 44 | - integration 45 | - unit 46 | 47 | index.tsx --> routes 48 | 49 | ## APP Features 50 | 51 | - Wallet ERC20 balance fetching for the main tokens and coins dependent of chain. APP supports natively the follow tokens USDC, USDT, DAI, and as coins ETH, MATIC and BNB, this part is configurable. Unsupported tokens could be imported 52 | - Wallet ERC721 balance display. User can import any NFT by ID. Collections could be added by wizard 53 | - Notifications - Each in app interaction generates a notification for user and stores a transaction on the store 54 | - NFT list of available orders for trade 55 | - NFT detail - A visit to a page it will fetch all data onchain, by /:chainname/:contract_address/:id . User can place sell order, buy order, or transfer 56 | - internationalization - It will be built from the ground up with internationalization in mind 57 | -------------------------------------------------------------------------------- /config/default.collectionlist.json: -------------------------------------------------------------------------------- 1 | { 2 | "collections": [ 3 | { 4 | "image": "https://dweb.link/ipfs/QmZfhEwTcTvXy4GfcyNvqDvGK6qzCFbZeTX71hUT3RWL8X", 5 | "name": "Coin League Champions", 6 | "backgroundImage": "https://dweb.link/ipfs/QmZfhEwTcTvXy4GfcyNvqDvGK6qzCFbZeTX71hUT3RWL8X", 7 | "chainId": 80001, 8 | "contractAddress": "0x05b93425e4b44c9042ed97b7a332ab1575ebd25d", 9 | "description": "", 10 | "uri": "coinleaguechampions" 11 | }, 12 | { 13 | "image": "https://dweb.link/ipfs/QmZfhEwTcTvXy4GfcyNvqDvGK6qzCFbZeTX71hUT3RWL8X", 14 | "name": "Coin League Champions", 15 | "backgroundImage": "https://dweb.link/ipfs/QmZfhEwTcTvXy4GfcyNvqDvGK6qzCFbZeTX71hUT3RWL8X", 16 | "chainId": 80001, 17 | "contractAddress": "0x05b93425e4b44c9042ed97b7a332ab1575ebd25d", 18 | "description": "", 19 | "uri": "coinleaguechampions" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /config/default.tokenlist.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Test tokens", 3 | "logoURI": "ipfs://QmUSNbwUxUYNMvMksKypkgWs8unSm8dX2GjCPBVGZ7GGMr", 4 | "keywords": ["faucet", "test"], 5 | "tags": { 6 | "faucet": { 7 | "name": "Faucet token for testing on ropsten", 8 | "description": "ERC20 tokens for testing" 9 | } 10 | }, 11 | "timestamp": "2020-06-12T00:00:00+00:00", 12 | "tokens": [ 13 | { 14 | "chainId": 3, 15 | "address": "0xfab46e002bbf0b4509813474841e0716e6730136", 16 | "symbol": "FAU", 17 | "name": "FaucetToken", 18 | "decimals": 18, 19 | "logoURI": "ipfs://QmUSNbwUxUYNMvMksKypkgWs8unSm8dX2GjCPBVGZ7GGMr", 20 | "tags": ["faucet", "test"] 21 | }, 22 | { 23 | "chainId": 4, 24 | "address": "0xFab46E002BbF0b4509813474841E0716E6730136", 25 | "symbol": "FAU", 26 | "name": "FaucetToken", 27 | "decimals": 18, 28 | "logoURI": "ipfs://QmUSNbwUxUYNMvMksKypkgWs8unSm8dX2GjCPBVGZ7GGMr", 29 | "tags": ["faucet", "test"] 30 | }, 31 | { 32 | "chainId": 3, 33 | "address": "0xad6d458402f60fd3bd25163575031acdce07538d", 34 | "symbol": "DAI", 35 | "name": "DAI Stable Coin", 36 | "decimals": 18, 37 | "logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png", 38 | "tags": ["faucet", "test"] 39 | }, 40 | { 41 | "chainId": 3, 42 | "address": "0xc778417e063141139fce010982780140aa0cd5ab", 43 | "symbol": "WETH", 44 | "name": "Wrapped Ether", 45 | "decimals": 18, 46 | "logoURI": "ipfs://QmUSNbwUxUYNMvMksKypkgWs8unSm8dX2GjCPBVGZ7GGMr", 47 | "tags": ["weth", "test"] 48 | }, 49 | { 50 | "chainId": 80001, 51 | "address": "0xa6fa4fb5f76172d178d61b04b0ecd319c5d1c0aa", 52 | "symbol": "WETH", 53 | "name": "Wrapped ETH", 54 | "decimals": 18, 55 | "logoURI": "https://polygonscan.com/token/images/wMatic_32.png", 56 | "tags": ["polygon", "wrapped token"] 57 | }, 58 | { 59 | "chainId": 137, 60 | "address": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", 61 | "symbol": "USDC", 62 | "name": "USD Coin", 63 | "decimals": 6, 64 | "logoURI": "https://polygonscan.com/token/images/centre-usdc_32.png", 65 | "tags": ["polygon", "stable coin"] 66 | } 67 | ], 68 | "version": { 69 | "major": 1, 70 | "minor": 0, 71 | "patch": 0 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /docs/ADD_LANGUAGE.md: -------------------------------------------------------------------------------- 1 | # How to add a language to NFT Marketplace 2 | 3 | ## First step 4 | 5 | Under lang folder copy en-US.json and create a json file with your language code and translate it on same folder. 6 | 7 | ## Second step 8 | 9 | Add the language you wanna add to src/constants/index.ts file 10 | 11 | ## Third step 12 | 13 | Run 14 | 15 | ` yarn compile lang/your-language-code.json --out-file compiled-lang/your-language-code.json` 16 | 17 | Example for pt-BR 18 | 19 | `yarn compile lang/pt-BR.json --out-file compiled-lang/pt-BR.json` 20 | 21 | ## Fourth step 22 | 23 | Add language you wanna add to src/utils/intl.ts file 24 | -------------------------------------------------------------------------------- /funding.json: -------------------------------------------------------------------------------- 1 | { 2 | "opRetro": { 3 | "projectId": "0xcc9301a401320c626839db9c4415f28a6e1f2fb3abdf38ada785b57409bdedb6" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /next-seo.config.ts: -------------------------------------------------------------------------------- 1 | import { getAppConfig } from './src/services/app'; 2 | 3 | const config = getAppConfig(); 4 | 5 | const seoConfig: any = { 6 | defaultTitle: config.seo?.home?.title || config.name, 7 | titleTemplate: `${config.name} | %s`, 8 | description: config.seo?.home?.description, 9 | canonical: config.url, 10 | }; 11 | 12 | if (config.social) { 13 | for (let social of config.social) { 14 | if (social.type === 'twitter') { 15 | seoConfig.twitter = { 16 | handle: `@${social.handle}`, 17 | site: `@${social.handle}`, 18 | cardType: "summary_large_image" 19 | }; 20 | } 21 | } 22 | } 23 | 24 | export default seoConfig; 25 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | module.exports = { 3 | reactStrictMode: true, 4 | staticPageGenerationTimeout: 120, 5 | images: { 6 | domains: [ 7 | 'dweb.link', 8 | 'ipfs.io', 9 | 'ipfs.moralis.io', 10 | 'raw.githubusercontent.com', 11 | 'arpeggi.io', 12 | 'arweave.net', 13 | 'metadata.ens.domains', 14 | ], 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "open-nft-marketplace", 3 | "version": "0.0.2", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev -p 3001", 7 | "build": "next build --debug", 8 | "start": "next start", 9 | "lint": "next lint", 10 | "post-update": "echo \"codesandbox preview only, need an update\" && yarn upgrade --latest", 11 | "extract": "formatjs extract", 12 | "compile": "formatjs compile", 13 | "generate-lang-files": "yarn extract 'src/**/*.ts*' --ignore='**/*.d.ts' --out-file lang/en.json --id-interpolation-pattern '[sha512:contenthash:base64:6]'" 14 | }, 15 | "dependencies": { 16 | "@0x/contract-addresses": "^6.14.0", 17 | "@date-io/moment": "^2.13.1", 18 | "@emotion/cache": "^11.7.1", 19 | "@emotion/react": "^11.9.0", 20 | "@emotion/server": "^11.4.0", 21 | "@emotion/styled": "^11.8.1", 22 | "@indexed-finance/multicall": "^2.0.0", 23 | "@mui/icons-material": "^5.6.2", 24 | "@mui/material": "^5.6.3", 25 | "@mui/x-date-pickers": "^5.0.0-alpha.2", 26 | "@react-hook/intersection-observer": "^3.1.1", 27 | "@svgr/webpack": "^6.2.1", 28 | "@traderxyz/nft-swap-sdk": "0.25.0", 29 | "@transak/transak-sdk": "^1.0.31", 30 | "@walletconnect/ethereum-provider": "^1.7.7", 31 | "@web3-react/core": "8.0.28-beta.0", 32 | "@web3-react/metamask": "8.0.23-beta.0", 33 | "@web3-react/network": "^8.0.0-beta.0", 34 | "@web3-react/walletconnect": "8.0.30-beta.0", 35 | "axios": "^0.27.2", 36 | "ethers": "^5.6.4", 37 | "formik": "^2.2.9", 38 | "jotai": "^1.6.5", 39 | "moment": "^2.29.3", 40 | "next": "^12.1.5", 41 | "next-seo": "^5.4.0", 42 | "notistack": "^2.0.5", 43 | "optics-ts": "^2.3.0", 44 | "qrcode.react": "^3.0.2", 45 | "qs": "^6.11.0", 46 | "react": "^18.1.0", 47 | "react-dom": "^18.1.0", 48 | "react-error-boundary": "^3.1.4", 49 | "react-intl": "^5.24.8", 50 | "react-markdown": "^8.0.5", 51 | "react-query": "^3.34.19", 52 | "remark-gfm": "^3.0.1", 53 | "yup": "^0.32.11" 54 | }, 55 | "devDependencies": { 56 | "@formatjs/cli": "^4.8.3", 57 | "@types/qs": "^6.9.7", 58 | "@web3-react/types": "8.0.16-beta.0", 59 | "eslint": "^8.14.0", 60 | "eslint-config-next": "^12.1.5", 61 | "typescript": "^4.6.4" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /pages/404.tsx: -------------------------------------------------------------------------------- 1 | import ArrowBackIcon from '@mui/icons-material/ArrowBack'; 2 | import { Box, Button, Container, Grid, Typography } from '@mui/material'; 3 | import type { NextPage } from 'next'; 4 | import MainLayout from '../src/components/layouts/main'; 5 | 6 | import Image from 'next/image'; 7 | 8 | import { FormattedMessage } from 'react-intl'; 9 | import catHeroImg from '../public/assets/images/cat-hero.svg'; 10 | import Link from '../src/components/Link'; 11 | 12 | const NotFound: NextPage = () => { 13 | return ( 14 | 15 | 16 | 17 | 18 | 26 | 31 | 35 | 36 | 41 | 42 | 43 | 50 | 62 | 63 | 64 | 72 | Cat Hero 73 | 74 | 75 | 76 | 77 | 78 | ); 79 | }; 80 | 81 | export default NotFound; 82 | -------------------------------------------------------------------------------- /pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import { CacheProvider, EmotionCache } from '@emotion/react'; 2 | import CssBaseline from '@mui/material/CssBaseline'; 3 | import { responsiveFontSizes, ThemeProvider } from '@mui/material/styles'; 4 | import { AppProps } from 'next/app'; 5 | import Head from 'next/head'; 6 | import * as React from 'react'; 7 | import { Hydrate, QueryClient, QueryClientProvider } from 'react-query'; 8 | import createEmotionCache from '../src/createEmotionCache'; 9 | import { getTheme } from '../src/theme'; 10 | 11 | import { DefaultSeo } from 'next-seo'; 12 | 13 | import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; 14 | 15 | import { AdapterMoment } from '@mui/x-date-pickers/AdapterMoment'; 16 | 17 | import { Web3ReactProvider } from '@web3-react/core'; 18 | import { Provider } from 'jotai'; 19 | import { hooks as metaMaskHooks, metaMask } from '../src/connectors/metamask'; 20 | import { 21 | hooks as walletConnectHooks, 22 | walletConnect, 23 | } from '../src/connectors/walletConnect'; 24 | 25 | import { SnackbarProvider } from 'notistack'; 26 | import AppIntlProvider from '../src/components/AppIntlProvider'; 27 | import { Updater } from '../src/components/transactions/Updater'; 28 | import { getAppConfig } from '../src/services/app'; 29 | 30 | import SEO from '../next-seo.config'; 31 | 32 | // Client-side cache, shared for the whole session of the user in the browser. 33 | const clientSideEmotionCache = createEmotionCache(); 34 | 35 | interface MyAppProps extends AppProps { 36 | emotionCache?: EmotionCache; 37 | } 38 | 39 | const appConfig = getAppConfig(); 40 | 41 | const tempTheme = getTheme(appConfig.theme); 42 | 43 | const theme = responsiveFontSizes(tempTheme); 44 | 45 | export default function MyApp(props: MyAppProps) { 46 | const { Component, emotionCache = clientSideEmotionCache, pageProps } = props; 47 | 48 | const [queryClient] = React.useState( 49 | new QueryClient({ 50 | defaultOptions: { 51 | queries: { 52 | suspense: false, 53 | }, 54 | }, 55 | }) 56 | ); 57 | 58 | const getLayout = (Component as any).getLayout || ((page: any) => page); 59 | 60 | return ( 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 81 | 82 | {getLayout()} 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | ); 93 | } 94 | -------------------------------------------------------------------------------- /pages/_document.tsx: -------------------------------------------------------------------------------- 1 | import createEmotionServer from '@emotion/server/create-instance'; 2 | import Document, { Head, Html, Main, NextScript } from 'next/document'; 3 | 4 | import createEmotionCache from '../src/createEmotionCache'; 5 | import { getAppConfig } from '../src/services/app'; 6 | import { getTheme } from '../src/theme'; 7 | 8 | const appConfig = getAppConfig(); 9 | const theme = getTheme(appConfig.theme); 10 | 11 | export default class MyDocument extends Document { 12 | render() { 13 | return ( 14 | 15 | 16 | {/* PWA primary color */} 17 | 18 | 19 | 20 | 21 | 25 | {(this.props as any).emotionStyleTags} 26 | 27 | 28 |
29 | 30 | 31 | 32 | ); 33 | } 34 | } 35 | 36 | // `getInitialProps` belongs to `_document` (instead of `_app`), 37 | // it's compatible with static-site generation (SSG). 38 | MyDocument.getInitialProps = async (ctx) => { 39 | // Resolution order 40 | // 41 | // On the server: 42 | // 1. app.getInitialProps 43 | // 2. page.getInitialProps 44 | // 3. document.getInitialProps 45 | // 4. app.render 46 | // 5. page.render 47 | // 6. document.render 48 | // 49 | // On the server with error: 50 | // 1. document.getInitialProps 51 | // 2. app.render 52 | // 3. page.render 53 | // 4. document.render 54 | // 55 | // On the client 56 | // 1. app.getInitialProps 57 | // 2. page.getInitialProps 58 | // 3. app.render 59 | // 4. page.render 60 | 61 | const originalRenderPage = ctx.renderPage; 62 | 63 | // You can consider sharing the same emotion cache between all the SSR requests to speed up performance. 64 | // However, be aware that it can have global side effects. 65 | const cache = createEmotionCache(); 66 | const { extractCriticalToChunks } = createEmotionServer(cache); 67 | 68 | ctx.renderPage = () => 69 | originalRenderPage({ 70 | enhanceApp: (App: any) => 71 | function EnhanceApp(props) { 72 | return ; 73 | }, 74 | }); 75 | 76 | const initialProps = await Document.getInitialProps(ctx); 77 | // This is important. It prevents emotion to render invalid HTML. 78 | // See https://github.com/mui/material-ui/issues/26561#issuecomment-855286153 79 | const emotionStyles = extractCriticalToChunks(initialProps.html); 80 | const emotionStyleTags = emotionStyles.styles.map((style) => ( 81 |