├── .editorconfig ├── .eslintrc.js ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── config.yml │ ├── documentation.yml │ └── feature_request.yml ├── PULL_REQUEST_TEMPLATE.md ├── config.yml ├── dependabot.yml └── workflows │ ├── close-invalid.yml │ ├── codacy-analysis.yml │ ├── github-release.yml │ ├── mark-stale.yml │ ├── merge-deps.yml │ └── repo-labels.yml ├── .gitignore ├── .markdownlintignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── artifacts ├── @openzeppelin │ └── contracts │ │ ├── security │ │ └── ReentrancyGuard.sol │ │ │ ├── ReentrancyGuard.dbg.json │ │ │ └── ReentrancyGuard.json │ │ ├── token │ │ └── ERC721 │ │ │ ├── ERC721.sol │ │ │ ├── ERC721.dbg.json │ │ │ └── ERC721.json │ │ │ ├── IERC721.sol │ │ │ ├── IERC721.dbg.json │ │ │ └── IERC721.json │ │ │ ├── IERC721Receiver.sol │ │ │ ├── IERC721Receiver.dbg.json │ │ │ └── IERC721Receiver.json │ │ │ └── extensions │ │ │ ├── ERC721URIStorage.sol │ │ │ ├── ERC721URIStorage.dbg.json │ │ │ └── ERC721URIStorage.json │ │ │ └── IERC721Metadata.sol │ │ │ ├── IERC721Metadata.dbg.json │ │ │ └── IERC721Metadata.json │ │ └── utils │ │ ├── Address.sol │ │ ├── Address.dbg.json │ │ └── Address.json │ │ ├── Context.sol │ │ ├── Context.dbg.json │ │ └── Context.json │ │ ├── Counters.sol │ │ ├── Counters.dbg.json │ │ └── Counters.json │ │ ├── Strings.sol │ │ ├── Strings.dbg.json │ │ └── Strings.json │ │ └── introspection │ │ ├── ERC165.sol │ │ ├── ERC165.dbg.json │ │ └── ERC165.json │ │ └── IERC165.sol │ │ ├── IERC165.dbg.json │ │ └── IERC165.json ├── build-info │ ├── 1684140606a8b826ecd0a3b1ad391a8f.json │ └── 579c9bb0c7a4732fcd31a6d6f36c0bab.json ├── contracts │ ├── Market.sol │ │ ├── NFTMarket.dbg.json │ │ └── NFTMarket.json │ └── NFT.sol │ │ ├── NFT.dbg.json │ │ └── NFT.json └── hardhat │ └── console.sol │ ├── console.dbg.json │ └── console.json ├── cache └── solidity-files-cache.json ├── components ├── MarketplaceList.js ├── ReposList.js ├── ReposModal.js ├── SvgPreview.js ├── landing │ ├── faq.js │ ├── features.js │ ├── footer.js │ ├── hero.js │ └── stoken.js └── nav │ └── dashboard-navbar.js ├── config.js ├── contracts ├── Market.sol └── NFT.sol ├── hardhat.config.js ├── layout └── Layout.js ├── mkubdev-pr.md ├── netlify.toml ├── next.config.js ├── package.json ├── pages ├── _app.js ├── api │ ├── auth │ │ └── [...nextauth].js │ └── hello.js ├── dashboard │ ├── create-nft.js │ ├── index.js │ ├── my-creations.js │ └── my-nfts.js ├── index.js ├── login.js └── repos-list.js ├── postcss.config.js ├── public ├── DevNFT.png ├── DevNFT.svg ├── favicon.ico ├── hero.png ├── metamask-fox.svg ├── section-media.png └── vercel.svg ├── styles ├── Home.module.css └── globals.css └── tailwind.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | charset = utf-8 11 | trim_trailing_whitespace = true 12 | insert_final_newline = true 13 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | commonjs: true, 4 | es2021: true, 5 | node: true 6 | }, 7 | extends: ['eslint:recommended', 'next'], 8 | parserOptions: { 9 | ecmaVersion: 6 10 | }, 11 | rules: { 12 | 'semi': 0, 13 | 'no-unused-var': 'off' 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: File a bug report 3 | title: "[Bug]: " 4 | labels: ["💻 aspect: code", "🛠 goal: fix", "🚦 status: awaiting triage"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for taking the time to fill out this bug report! 10 | 11 | - type: textarea 12 | id: detailed-description 13 | attributes: 14 | label: Detailed Description 15 | description: Add a detailed description of the bug report. 16 | placeholder: A detailed description of the bug report. 17 | value: "I found this error in this project where ..." 18 | validations: 19 | required: true 20 | 21 | - type: textarea 22 | id: expected-behavior 23 | attributes: 24 | label: Expected Behavior 25 | description: What did you expect to happen? 26 | placeholder: What should be expected? 27 | value: "I expected that..." 28 | validations: 29 | required: true 30 | 31 | - type: textarea 32 | id: reproduce 33 | attributes: 34 | label: How can someone reproduce the behavior? 35 | description: Steps to reproduce the behavior you were facing. 36 | placeholder: How can someone reproduce the behavior you were facing? 37 | value: | 38 | 1. Go to... 39 | 2. Do... 40 | 3. Now... 41 | 4. Finally... 42 | validations: 43 | required: true 44 | 45 | - type: checkboxes 46 | id: contributing 47 | attributes: 48 | label: Contributing 49 | description: You accept that you've read the [contributing guidelines](https://github.com/WebXDAO/DEV-NFT/blob/main/CONTRIBUTING.md) 50 | options: 51 | - label: I have read the project's contribution guidelines. 52 | required: true 53 | 54 | - type: checkboxes 55 | id: code-of-conduct 56 | attributes: 57 | label: Code of Conduct 58 | description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/WebXDAO/DEV-NFT/blob/main/CODE_OF_CONDUCT.md) 59 | options: 60 | - label: I agree to follow this project's Code of Conduct 61 | required: true 62 | 63 | - type: textarea 64 | attributes: 65 | label: Anything else? 66 | description: | 67 | Links? References? Anything that will give us more context about the issue you are encountering! 68 | 69 | Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. 70 | validations: 71 | required: false 72 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Our socials 4 | url: https://bio.link/WebXDAO 5 | about: Feel free to contact us via your preferred platform. 6 | - name: Discord community 7 | url: https://discord.gg/TSRwqx4K2v 8 | about: Join WebXDAO, a community focusing on decentralized applications, web3, blockchain, open source technologies, collaboration, and fun chats with community members. 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation.yml: -------------------------------------------------------------------------------- 1 | name: Documentation 2 | description: File a documentation request/report 3 | title: "[Docs]: " 4 | labels: ["📄 aspect: text", "✨ goal: improvement", "🚦 status: awaiting triage"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for taking the time to fill out this documentation request! 10 | 11 | - type: textarea 12 | id: detailed-description 13 | attributes: 14 | label: Detailed Description 15 | description: Add a detailed description of the documentation request. 16 | placeholder: A detailed description of the documentation request. 17 | value: "We should add documentation about this part ..." 18 | validations: 19 | required: true 20 | 21 | - type: checkboxes 22 | id: contributing 23 | attributes: 24 | label: Contributing 25 | description: You accept that you've read the [contributing guidelines](https://github.com/WebXDAO/DEV-NFT/blob/main/CONTRIBUTING.md) 26 | options: 27 | - label: I have read the project's contribution guidelines. 28 | required: true 29 | 30 | - type: checkboxes 31 | id: code-of-conduct 32 | attributes: 33 | label: Code of Conduct 34 | description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/WebXDAO/DEV-NFT/blob/main/CODE_OF_CONDUCT.md) 35 | options: 36 | - label: I agree to follow this project's Code of Conduct 37 | required: true 38 | 39 | - type: textarea 40 | attributes: 41 | label: Anything else? 42 | description: | 43 | Links? References? Anything that will give us more context about the issue you are encountering! 44 | 45 | Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. 46 | validations: 47 | required: false 48 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Feature Request 2 | description: File a feature request 3 | title: "[Feat]: " 4 | labels: ["💻 aspect: code", "⭐ goal: addition", "🚦 status: awaiting triage"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for taking the time to fill out this feature request! 10 | 11 | - type: textarea 12 | id: detailed-description 13 | attributes: 14 | label: Detailed Description 15 | description: Add a detailed description of the feature request. 16 | placeholder: A detailed description of the feature request. 17 | value: "I think the feature [placeholder] should be added because ..." 18 | validations: 19 | required: true 20 | 21 | - type: checkboxes 22 | id: contributing 23 | attributes: 24 | label: Contributing 25 | description: You accept that you've read the [contributing guidelines](https://github.com/WebXDAO/DEV-NFT/blob/main/CONTRIBUTING.md) 26 | options: 27 | - label: I have read the project's contribution guidelines. 28 | required: true 29 | 30 | - type: checkboxes 31 | id: code-of-conduct 32 | attributes: 33 | label: Code of Conduct 34 | description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/WebXDAO/DEV-NFT/blob/main/CODE_OF_CONDUCT.md) 35 | options: 36 | - label: I agree to follow this project's Code of Conduct 37 | required: true 38 | 39 | - type: textarea 40 | attributes: 41 | label: Anything else? 42 | description: | 43 | Links? References? Anything that will give us more context about the issue you are encountering! 44 | 45 | Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. 46 | validations: 47 | required: false 48 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | #### Description of the change\* 3 | 4 | 5 | 6 | CLOSES #ISSUENO 7 | 8 | #### Checklist\* 9 | 10 | **Please make sure you have done the following:** 11 | 12 | - [ ] 😄 I've read [CONTRIBUTING.md][contributing] and my PR is up to standards. 13 | - [ ] 🎨 The changes in this PR meet the design plan. 14 | - [ ] 🐛 I've tested my PR's source changes for any bugs/render issues. 15 | - [ ] 🧪 I've worked through build failures and tests are passing. 16 | - [ ] 📄 I've updated the necessary documentation changes. 17 | 18 | #### Notes 19 | 20 | 28 | 29 | 30 | 31 | [contributing]: https://github.com/WebXDAO/DEV-NFT/blob/main/CONTRIBUTING.md 32 | -------------------------------------------------------------------------------- /.github/config.yml: -------------------------------------------------------------------------------- 1 | # Configuration for welcome - https://github.com/behaviorbot/welcome 2 | 3 | # Configuration for new-issue-welcome - https://github.com/behaviorbot/new-issue-welcome 4 | 5 | # Comment to be posted to on first time issues 6 | newIssueWelcomeComment: > 7 | Thank you for your valuable contributions! 🚀 Welcome to the community 🎉 We appreciate every and single contribution! 😄 8 | 9 | # Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome 10 | 11 | # Comment to be posted to on PRs from first time contributors in your repository 12 | newPRWelcomeComment: > 13 | Thanks for opening this pull request! Please check out our contributing guidelines. A maintainer will review it soon 😄 14 | 15 | # Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge 16 | 17 | # Comment to be posted to on pull requests merged by a first time user 18 | firstPRMergeComment: > 19 | Congrats on merging your first pull request! Welcome to the community 🎉 20 | 21 | # It is recommended to include as many gifs and emojis as possible! 22 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | updates: 2 | - directory: / 3 | open-pull-requests-limit: 5 4 | package-ecosystem: npm 5 | rebase-strategy: auto 6 | schedule: 7 | interval: "weekly" 8 | 9 | 10 | version: 2 11 | -------------------------------------------------------------------------------- /.github/workflows/close-invalid.yml: -------------------------------------------------------------------------------- 1 | # Automation to close issues on "invalid" label addition 2 | 3 | name: Close Issue/PR on adding invalid label 4 | 5 | 6 | on: 7 | issues: 8 | types: [labeled] 9 | pull_request_target: 10 | types: [labeled] 11 | 12 | permissions: 13 | issues: write 14 | pull-requests: write 15 | 16 | jobs: 17 | close-on-adding-invalid-label: 18 | if: github.event.label.name == 'invalid' && github.repository_owner == 'WebXDAO' 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - name: Close issue 23 | if: ${{ github.event_name == 'issues' }} 24 | env: 25 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 26 | run: gh issue close ${{ github.event.issue.html_url }} 27 | 28 | - name: Close PR 29 | if: ${{ github.event_name == 'pull_request_target' }} 30 | env: 31 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 32 | run: gh pr close ${{ github.event.pull_request.html_url }} 33 | 34 | -------------------------------------------------------------------------------- /.github/workflows/codacy-analysis.yml: -------------------------------------------------------------------------------- 1 | # Run Codacy Analysis on Push 2 | 3 | name: Codacy Analysis CLI 4 | 5 | on: ["push"] 6 | 7 | jobs: 8 | codacy-analysis-cli: 9 | name: Codacy Analysis CLI 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout code 13 | uses: actions/checkout@main 14 | 15 | - name: Run Codacy Analysis CLI 16 | uses: codacy/codacy-analysis-cli-action@master 17 | -------------------------------------------------------------------------------- /.github/workflows/github-release.yml: -------------------------------------------------------------------------------- 1 | # Release to github using semantic versioning and conventional commits 2 | 3 | name: GitHub Release 4 | on: 5 | push: 6 | branches: 7 | - main 8 | 9 | jobs: 10 | changelog: 11 | if: github.repository_owner == 'WebXDAO' 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@main 16 | 17 | - name: conventional Changelog Action 18 | id: changelog 19 | uses: TriPSs/conventional-changelog-action@v3.7.1 20 | with: 21 | github-token: ${{ secrets.GITHUB_TOKEN }} 22 | 23 | - name: create release 24 | uses: actions/create-release@main 25 | if: ${{ steps.changelog.outputs.skipped == 'false' }} 26 | env: 27 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 28 | with: 29 | tag_name: ${{ steps.changelog.outputs.tag }} 30 | release_name: ${{ steps.changelog.outputs.tag }} 31 | body: ${{ steps.changelog.outputs.clean_changelog }} 32 | -------------------------------------------------------------------------------- /.github/workflows/mark-stale.yml: -------------------------------------------------------------------------------- 1 | # Automation to mark inactive issues/prs as stale 2 | 3 | name: Mark Stale Issues/PRs 4 | 5 | on: 6 | schedule: 7 | - cron: '30 1 * * *' 8 | 9 | jobs: 10 | stale: 11 | if: github.repository_owner == 'WebXDAO' 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/stale@v1 16 | with: 17 | repo-token: ${{ secrets.GITHUB_TOKEN }} 18 | stale-issue-message: 'Stale issue message' 19 | stale-pr-message: 'Stale pull request message' 20 | stale-issue-label: 'no-issue-activity' 21 | stale-pr-label: 'no-issue-activity' 22 | days-before-stale: 14 23 | days-before-close: 14 24 | -------------------------------------------------------------------------------- /.github/workflows/merge-deps.yml: -------------------------------------------------------------------------------- 1 | # Automatation to merge dependency updates automatically 2 | 3 | name: Merge Dependency Updates Automatically 4 | 5 | on: 6 | pull_request_target: 7 | paths: 8 | - 'package*.json' 9 | - 'yarn.lock' 10 | pull_request_review: 11 | types: 12 | - edited 13 | - submitted 14 | 15 | jobs: 16 | run: 17 | if: github.repository_owner == 'WebXDAO' 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: tjenkinson/gh-action-auto-merge-dependency-updates@v1 21 | with: 22 | allowed-actors: dependabot-preview[bot], dependabot[bot] 23 | -------------------------------------------------------------------------------- /.github/workflows/repo-labels.yml: -------------------------------------------------------------------------------- 1 | # Import Repo Standard Labels whenever needed. 2 | 3 | name: Label importer 4 | 5 | on: workflow_dispatch 6 | 7 | jobs: 8 | labels: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: actions/setup-node@v2 13 | with: 14 | node-version: '14' 15 | - uses: EddieHubCommunity/gh-action-open-source-labels@main 16 | with: 17 | github-token: ${{ secrets.GITHUB_TOKEN }} 18 | owner-name: ${{ github.repository_owner }} 19 | repository-name: ${{ github.event.repository.name }} 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Node ### 2 | # Logs 3 | logs 4 | *.log 5 | npm-debug.log* 6 | yarn-debug.log* 7 | yarn-error.log* 8 | lerna-debug.log* 9 | .pnpm-debug.log* 10 | 11 | # Diagnostic reports (https://nodejs.org/api/report.html) 12 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 13 | 14 | # Runtime data 15 | pids 16 | *.pid 17 | *.seed 18 | *.pid.lock 19 | 20 | # Directory for instrumented libs generated by jscoverage/JSCover 21 | lib-cov 22 | 23 | # Coverage directory used by tools like istanbul 24 | coverage 25 | *.lcov 26 | 27 | # nyc test coverage 28 | .nyc_output 29 | 30 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 31 | .grunt 32 | 33 | # Bower dependency directory (https://bower.io/) 34 | bower_components 35 | 36 | # node-waf configuration 37 | .lock-wscript 38 | 39 | # Compiled binary addons (https://nodejs.org/api/addons.html) 40 | build/Release 41 | 42 | # Dependency directories 43 | node_modules/ 44 | jspm_packages/ 45 | 46 | # Snowpack dependency directory (https://snowpack.dev/) 47 | web_modules/ 48 | 49 | # TypeScript cache 50 | *.tsbuildinfo 51 | 52 | # Optional npm cache directory 53 | .npm 54 | 55 | # Optional eslint cache 56 | .eslintcache 57 | 58 | # Microbundle cache 59 | .rpt2_cache/ 60 | .rts2_cache_cjs/ 61 | .rts2_cache_es/ 62 | .rts2_cache_umd/ 63 | 64 | # Optional REPL history 65 | .node_repl_history 66 | 67 | # Output of 'npm pack' 68 | *.tgz 69 | 70 | # Yarn Integrity file 71 | .yarn-integrity 72 | 73 | # dotenv environment variables file 74 | .env 75 | .env.test 76 | .env.production 77 | 78 | # parcel-bundler cache (https://parceljs.org/) 79 | .cache 80 | .parcel-cache 81 | 82 | # Next.js build output 83 | .next 84 | out 85 | 86 | # Nuxt.js build / generate output 87 | .nuxt 88 | dist 89 | 90 | # Gatsby files 91 | .cache/ 92 | # Comment in the public line in if your project uses Gatsby and not Next.js 93 | # https://nextjs.org/blog/next-9-1#public-directory-support 94 | # public 95 | 96 | # vuepress build output 97 | .vuepress/dist 98 | 99 | # Serverless directories 100 | .serverless/ 101 | 102 | # FuseBox cache 103 | .fusebox/ 104 | 105 | # DynamoDB Local files 106 | .dynamodb/ 107 | 108 | # TernJS port file 109 | .tern-port 110 | 111 | # Stores VSCode versions used for testing VSCode extensions 112 | .vscode-test 113 | 114 | # yarn v2 115 | .yarn/cache 116 | .yarn/unplugged 117 | .yarn/build-state.yml 118 | .yarn/install-state.gz 119 | .pnp.* 120 | 121 | ### Node Patch ### 122 | # Serverless Webpack directories 123 | .webpack/ 124 | 125 | # Optional stylelint cache 126 | .stylelintcache 127 | 128 | # SvelteKit build / generate output 129 | .svelte-kit 130 | 131 | # Nextjs - lockfile 132 | package-lock.json 133 | 134 | 135 | #secret 136 | .secret 137 | 138 | #Hardhat files 139 | 140 | -------------------------------------------------------------------------------- /.markdownlintignore: -------------------------------------------------------------------------------- 1 | node_modules/**/** 2 | 3 | CHANGELOG.md 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [0.2.4](https://github.com/web3community/DEV-NFT/compare/v0.2.3...v0.2.4) (2021-12-30) 2 | 3 | 4 | ### Bug Fixes 5 | 6 | * Login Session issue in Mobile View ([#55](https://github.com/web3community/DEV-NFT/issues/55)) ([bad76c7](https://github.com/web3community/DEV-NFT/commit/bad76c723623731e0e139f68ff01f182d0556589)) 7 | 8 | 9 | 10 | ## [0.2.3](https://github.com/web3community/DEV-NFT/compare/v0.2.2...v0.2.3) (2021-12-15) 11 | 12 | 13 | ### Bug Fixes 14 | 15 | * missing items sold cards ([d934fd8](https://github.com/web3community/DEV-NFT/commit/d934fd8786d2a7bc593fefc06ff650dc88751eb6)) 16 | 17 | 18 | 19 | ## [0.2.2](https://github.com/web3community/DEV-NFT/compare/v0.2.1...v0.2.2) (2021-12-14) 20 | 21 | 22 | ### Bug Fixes 23 | 24 | * allow user to see my-creation and my-nft pages ([dd6f099](https://github.com/web3community/DEV-NFT/commit/dd6f099ba78adefca30159cb633a932614181175)) 25 | * nft price correctly placed on cards ([4035ecf](https://github.com/web3community/DEV-NFT/commit/4035ecf3323a6dd93f84917bad1b890127ea75a1)) 26 | * remove the redirection on create-nft page ([576becc](https://github.com/web3community/DEV-NFT/commit/576becc2f51327760a93a533e9634d8a453e3546)) 27 | 28 | 29 | 30 | ## [0.2.1](https://github.com/web3community/DEV-NFT/compare/v0.2.0...v0.2.1) (2021-12-14) 31 | 32 | 33 | ### Bug Fixes 34 | 35 | * session return missing ([9aad9c5](https://github.com/web3community/DEV-NFT/commit/9aad9c5f267eb2f38d3a15d5b6929713e3e53e25)) 36 | * the user canno't access the marketplace if not logged to github. We redirect the user to the /login page ([c080a95](https://github.com/web3community/DEV-NFT/commit/c080a951dfe02d1313c4aff3518bdaa6d1b5675c)) 37 | 38 | 39 | 40 | # [0.2.0](https://github.com/web3community/DEV-NFT/compare/v0.1.1...v0.2.0) (2021-12-12) 41 | 42 | 43 | ### Features 44 | 45 | * new svg ([a7b1977](https://github.com/web3community/DEV-NFT/commit/a7b197711860d05e98ea62f84207fb3f385c6c22)) 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, caste, color, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | - Demonstrating empathy and kindness toward other people 21 | - Being respectful of differing opinions, viewpoints, and experiences 22 | - Giving and gracefully accepting constructive feedback 23 | - Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | - Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | - The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | - Trolling, insulting or derogatory comments, and personal or political attacks 33 | - Public or private harassment 34 | - Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | - Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at web3opensourcecommunity@gmail.com. 63 | All complaints will be reviewed and investigated promptly and fairly. 64 | 65 | All community leaders are obligated to respect the privacy and security of the 66 | reporter of any incident. 67 | 68 | ## Enforcement Guidelines 69 | 70 | Community leaders will follow these Community Impact Guidelines in determining 71 | the consequences for any action they deem in violation of this Code of Conduct: 72 | 73 | ### 1. Correction 74 | 75 | **Community Impact**: Use of inappropriate language or other behavior deemed 76 | unprofessional or unwelcome in the community. 77 | 78 | **Consequence**: A private, written warning from community leaders, providing 79 | clarity around the nature of the violation and an explanation of why the 80 | behavior was inappropriate. A public apology may be requested. 81 | 82 | ### 2. Warning 83 | 84 | **Community Impact**: A violation through a single incident or series 85 | of actions. 86 | 87 | **Consequence**: A warning with consequences for continued behavior. No 88 | interaction with the people involved, including unsolicited interaction with 89 | those enforcing the Code of Conduct, for a specified period of time. This 90 | includes avoiding interactions in community spaces as well as external channels 91 | like social media. Violating these terms may lead to a temporary or 92 | permanent ban. 93 | 94 | ### 3. Temporary Ban 95 | 96 | **Community Impact**: A serious violation of community standards, including 97 | sustained inappropriate behavior. 98 | 99 | **Consequence**: A temporary ban from any sort of interaction or public 100 | communication with the community for a specified period of time. No public or 101 | private interaction with the people involved, including unsolicited interaction 102 | with those enforcing the Code of Conduct, is allowed during this period. 103 | Violating these terms may lead to a permanent ban. 104 | 105 | ### 4. Permanent Ban 106 | 107 | **Community Impact**: Demonstrating a pattern of violation of community 108 | standards, including sustained inappropriate behavior, harassment of an 109 | individual, or aggression toward or disparagement of classes of individuals. 110 | 111 | **Consequence**: A permanent ban from any sort of public interaction within 112 | the community. 113 | 114 | ## Attribution 115 | 116 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 117 | version 2.1, available at 118 | [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. 119 | 120 | Community Impact Guidelines were inspired by 121 | [Mozilla's code of conduct enforcement ladder][mozilla coc]. 122 | 123 | For answers to common questions about this code of conduct, see the FAQ at 124 | [https://www.contributor-covenant.org/faq][faq]. Translations are available 125 | at [https://www.contributor-covenant.org/translations][translations]. 126 | 127 | [homepage]: https://www.contributor-covenant.org 128 | [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html 129 | [mozilla coc]: https://github.com/mozilla/diversity 130 | [faq]: https://www.contributor-covenant.org/faq 131 | [translations]: https://www.contributor-covenant.org/translations 132 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | 🎉 **First of all, thanks for taking the time to contribute!** 🎉 4 | 5 | The following is a set of guidelines for contributing to this project. These are mostly guidelines, not rules. Use your best judgement, and feel free to propose changes to this document in a pull request. 6 | 7 | ## 📜 Code of Conduct 8 | 9 | This project and everyone participating in it is governed by a [Code of Conduct](https://github.com/WebXDAO/DEV-NFT/blob/main/CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to one of our moderators via your preferred platform or in our [Discord server](https://discord.gg/TSRwqx4K2v). 10 | 11 | ## 🤔 How can I contribute? 12 | 13 | ### 💣 Reporting Bugs 14 | 15 | This section guides you through submitting a bug report. Following these guidelines helps maintainers and the community understand your report 📝, reproduce the behavior 💻, and find related reports. 🔎 16 | 17 | Since the new GitHub Issue forms we only suggest you to include most information possible. But you can also **Perform a [cursory search](issues)** to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one. 18 | 19 | > **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one. 20 | 21 | ### 🛠 Suggesting Enhancements 22 | 23 | This section guides you through submitting an enhancement suggestion, including completely new features and minor improvements to existing functionality. Following these guidelines helps maintainers and the community understand your suggestion 📝 and find related suggestions. 🔎 24 | 25 | Since GitHub Issue forms we only suggest you to include most information possible. 26 | 27 | You can see **issues** to see if the enhancement has already been suggested. 28 | If it has, add a comment to the existing issue instead of opening a new one. 29 | 30 | > **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one. 31 | 32 | ### 🟩 Your First Code Contribution 33 | 34 | Unsure where to begin contributing to this project? You can start by looking through these beginner-friendly issues: 35 | 36 | - [Beginner issues](good-first-issues) - issues that require less work. 37 | - [Help wanted issues](help-wanted) - issues that are a bit more involved. 38 | 39 | ### 📣 Pull Requests 40 | 41 | The process described here has several goals: 42 | 43 | - Maintain the project's quality. 44 | - Fix problems that are important to users. 45 | - Engage the community in working toward the best possible outcome! 46 | - Enable a sustainable system for maintainers to review contributions. 47 | 48 | Please follow all instructions in [the template](https://github.com/WebXDAO/DEV-NFT/blob/main/.github/PULL_REQUEST_TEMPLATE.md) 49 | 50 | ## Style Guide for Git Commit Messages 📝 51 | 52 | **How you can add more value to your contribution logs:** 53 | 54 | - Use the present tense. (Example: "Add feature" instead of "Added feature") 55 | - Use the imperative mood. (Example: "Move item to...", instead of "Moves item to...") 56 | - Limit the first line (also called the Subject Line) to _50 characters or less_. 57 | - Capitalize the Subject Line. 58 | - Separate subject from body with a blank line. 59 | - Do not end the subject line with a period. 60 | - Wrap the body at _72 characters_. 61 | - Use the body to explain the _what_, _why_, _vs_, and _how_. 62 | - Reference [issues](issues) and [pull requests](prs) liberally after the first line. 63 | - Follow the [conventional commits](conventional-commits) guidelines 64 | 65 | ## How to Contribute 🚀 66 | 67 | - Please create an [issue](issues) before creating a pull request. 68 | - Fork the repository and create a branch for any issue that you are working on. 69 | - Create a pull request which will be reviewed and suggestions would be provided. 70 | - Add Screenshots to help us know what changes you have done. 71 | 72 | ## How to make a pull request 🤔 73 | 74 | **1.** Fork [this](repo) repository. 75 | 76 | **2.** Clone the forked repository. 77 | 78 | ```bash 79 | git clone https://github.com//DEV-NFT.git 80 | ``` 81 | 82 | **3.** Navigate to the project directory. 83 | 84 | ```bash 85 | cd DEV-NFT 86 | ``` 87 | 88 | **4.** Create a new branch 89 | 90 | Kindly give your branch a more descriptive name like `feat-optimize-images` instead of `patch-1`. 91 | 92 | You could follow this convention. Some ideas to get you started: 93 | 94 | - Feature Updates: `feat-<2-3-Words-Description>-` 95 | - Bug Fixes: `fix-<2-3-Words-Description>-` 96 | - Documentation: `docs-<2-3-Words-Description>-` 97 | - And so on... 98 | 99 | ```bash 100 | git checkout -b your-branch-name 101 | ``` 102 | 103 | **5.** Make the necessary changes. 104 | 105 | **6.** Stage your changes and commit. 106 | 107 | ```bash 108 | git add . # Stages all the changes 109 | git commit -m "" 110 | ``` 111 | 112 | [**Follow our commit guide from above**](#style-guide-for-git-commit-messages-) 113 | 114 | **7.** Push your local commits to the remote repository. 115 | 116 | ```bash 117 | git push origin your-branch-name 118 | ``` 119 | 120 | **8.** Create a new [pull request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request) from `your-branch-name` 121 | 122 | **9.** 🎉 Congratulations! You've made your first pull request! Now, you should just wait until the maintainers review your pull request. 123 | 124 | ## 🛑 Important 125 | 126 | ### ✅ Good Practice 127 | 128 | - Comment on the issue to get assigned 129 | - Create an issue before you make a Pull Request 130 | 131 | ### ❌ Bad Practice 132 | 133 | - Creating PRs without assignment will not be accepted and will be closed. 134 | 135 | ## 📈 Getting started 136 | 137 | - 😕 Not sure where to start? Join our community on [Discord](https://discord.gg/TSRwqx4K2v) 138 | - ✨ You can also take part in our [Community Discussions](https://github.com/WebXDAO/DEV-NFT/discussions) 139 | 140 | [repo]: https://github.com/WebXDAO/DEV-NFT 141 | [good-first-issues]: https://github.com/WebXDAO/DEV-NFT/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22 142 | [help-wanted]: https://github.com/WebXDAO/DEV-NFT/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22 143 | [issues]: https://github.com/WebXDAO/DEV-NFT/issues 144 | [prs]: https://github.com/WebXDAO/DEV-NFT/pulls 145 | 146 | [conventional-commits]: https://www.conventionalcommits.org/en/v1.0.0/ 147 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Business Source License 1.1 2 | 3 | License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved. 4 | "Business Source License" is a trademark of MariaDB Corporation Ab. 5 | 6 | ----------------------------------------------------------------------------- 7 | 8 | Parameters 9 | 10 | Licensor: WebX DAO 11 | 12 | Licensed Work: DevNFT 13 | The Licensed Work is (c) 2022 WebX DAO 14 | 15 | ----------------------------------------------------------------------------- 16 | 17 | Terms 18 | 19 | The Licensor hereby grants you the right to copy, modify, create derivative 20 | works, redistribute, and make non-production use of the Licensed Work. The 21 | Licensor may make an Additional Use Grant, above, permitting limited 22 | production use. 23 | 24 | Effective on the Change Date, or the fourth anniversary of the first publicly 25 | available distribution of a specific version of the Licensed Work under this 26 | License, whichever comes first, the Licensor hereby grants you rights under 27 | the terms of the Change License, and the rights granted in the paragraph 28 | above terminate. 29 | 30 | If your use of the Licensed Work does not comply with the requirements 31 | currently in effect as described in this License, you must purchase a 32 | commercial license from the Licensor, its affiliated entities, or authorized 33 | resellers, or you must refrain from using the Licensed Work. 34 | 35 | All copies of the original and modified Licensed Work, and derivative works 36 | of the Licensed Work, are subject to this License. This License applies 37 | separately for each version of the Licensed Work and the Change Date may vary 38 | for each version of the Licensed Work released by Licensor. 39 | 40 | You must conspicuously display this License on each original or modified copy 41 | of the Licensed Work. If you receive the Licensed Work in original or 42 | modified form from a third party, the terms and conditions set forth in this 43 | License apply to your use of that work. 44 | 45 | Any use of the Licensed Work in violation of this License will automatically 46 | terminate your rights under this License for the current and all other 47 | versions of the Licensed Work. 48 | 49 | This License does not grant you any right in any trademark or logo of 50 | Licensor or its affiliates (provided that you may use a trademark or logo of 51 | Licensor as expressly required by this License). 52 | 53 | TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON 54 | AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, 55 | EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF 56 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND 57 | TITLE. 58 | 59 | MariaDB hereby grants you permission to use this License’s text to license 60 | your works, and to refer to it using the trademark "Business Source License", 61 | as long as you comply with the Covenants of Licensor below. 62 | 63 | ----------------------------------------------------------------------------- 64 | 65 | Covenants of Licensor 66 | 67 | In consideration of the right to use this License’s text and the "Business 68 | Source License" name and trademark, Licensor covenants to MariaDB, and to all 69 | other recipients of the licensed work to be provided by Licensor: 70 | 71 | 1. To specify as the Change License the GPL Version 2.0 or any later version, 72 | or a license that is compatible with GPL Version 2.0 or a later version, 73 | where "compatible" means that software provided under the Change License can 74 | be included in a program with software provided under GPL Version 2.0 or a 75 | later version. Licensor may specify additional Change Licenses without 76 | limitation. 77 | 78 | 2. To either: (a) specify an additional grant of rights to use that does not 79 | impose any additional restriction on the right granted in this License, as 80 | the Additional Use Grant; or (b) insert the text "None". 81 | 82 | 3. To specify a Change Date. 83 | 84 | 4. Not to modify this License in any other way. 85 | 86 | ----------------------------------------------------------------------------- 87 | 88 | Notice 89 | 90 | The Business Source License (this document, or the "License") is not an Open 91 | Source license. However, the Licensed Work will eventually be made available 92 | under an Open Source License, as stated in this License. 93 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DEV-NFT [![Stake to support us](https://badge.devprotocol.xyz/0x803854e0676cd5892f6100eb452551D22e9c38ec/descriptive)](https://stakes.social/0x803854e0676cd5892f6100eb452551D22e9c38ec) 2 | 3 | 4 |

5 | animated 6 | 7 |

8 | 9 | This project aims for [Buidl it](https://buidlit.polygon.technology/) & [Dev Dapp Starter Grant](https://www.notion.so/Welcome-to-DEV-DAPP-STARTER-GRANTS-5cb95252f18540258111581ea54d8808) 10 | 11 | # Hackathon results 12 | 13 | This project won 2 prizes for [Buidl it](https://devfolio.co/submissions/devnft-210b) hackathon 🏆 : 14 | 15 | 16 | 17 | Check the project submission [here](https://devfolio.co/submissions/devnft-210b)! 18 | 19 | # Network 20 | 21 | We are currently on mumbai testnet. 22 | To use DevNFT you need to setup mumbai testnet network on metamask. 23 | - Go to metamask settings > add network > 24 | - NetworkName: Mumbai 25 | - chainId: 80001 26 | - Gas Token: MATIC Token 27 | - Rpc url: https://matic-mumbai.chainstacklabs.com 28 | - blockscan: https://mumbai.polygonscan.com/ 29 | 30 | ![image](https://user-images.githubusercontent.com/57281769/145784891-9902e059-59e8-442f-8ce1-ed7af6108784.png) 31 | 32 | To mint NFT you need test matic 33 | - Take them from : https://faucet.polygon.technology/ 34 | 35 | Tools we are using 36 | - IPFS infura node 37 | - Contract templates by [Nader Dabit](https://github.com/dabit3) 38 | - Nextjs for building Client 39 | - Hardhat for abi generation 40 | 41 | ## Environment Variables 42 | 43 | For local development, developers need to create environment variables in .env file. If you are not familiar with environment variables, here is a great [article](https://medium.com/the-node-js-collection/making-your-node-js-work-everywhere-with-environment-variables-2da8cdf6e786) explaining it. 44 | 45 | - To define permanent environment variables in this project, create a file called .env in the root of your project with following variables: 46 | 47 | ```bash 48 | GITHUB_CLIENT_ID= 49 | GITHUB_CLIENT_SECRET= 50 | NEXTAUTH_URL=http://localhost:3000 51 | ``` 52 | 53 | - You need to obtain your own Github Client ID and Secret Key for OAuth authentication for the app which would also be assigned to 'GITHUB_CLIENT_ID' and 'GITHUB_CLIENT_SECRET' variable above. If you want to understand further about client ID and Secret Key, as well as OAuth authentication, please read this [document](https://docs.github.com/en/rest/guides/basics-of-authentication). 54 | - You need to first register your app to obtain your Client ID and Secret Key. Click [here](https://github.com/settings/applications/new) to begin. 55 | - Fill in the information as shown below and click "Register application" button to proceed. 56 | ![image](https://user-images.githubusercontent.com/38476995/151486332-b9223452-91ef-4b45-b96f-686db5015361.png) 57 | - There you have it. Your client ID and client secret keys come from your application's configuration page. You should never, ever store these values in GitHub or any other public place, for that matter. We recommend storing them as environment variables which is exactly what we've done here. 58 | 59 | ![image](https://user-images.githubusercontent.com/38476995/151487977-44958f32-bfdb-4efe-945a-0a428f6d5dcb.png) 60 | 61 | - Double check .gitignore file and make sure .env is listed as shown below. 62 | 63 | ![image](https://user-images.githubusercontent.com/38476995/151290850-9cfe4b8d-d2db-4a90-a5e8-5f5e2f910706.png) 64 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Currently none of the versions are production ready 6 | 7 | | Version | Supported | 8 | | ------- | --------- | 9 | | x.x.x | :x: | 10 | 11 | ## Reporting a Vulnerability 12 | 13 | Report security vulnerabilities to web3opensourcecommunity@gmail.com 14 | -------------------------------------------------------------------------------- /artifacts/@openzeppelin/contracts/security/ReentrancyGuard.sol/ReentrancyGuard.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "..\\..\\..\\..\\build-info\\1684140606a8b826ecd0a3b1ad391a8f.json" 4 | } 5 | -------------------------------------------------------------------------------- /artifacts/@openzeppelin/contracts/security/ReentrancyGuard.sol/ReentrancyGuard.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "ReentrancyGuard", 4 | "sourceName": "@openzeppelin/contracts/security/ReentrancyGuard.sol", 5 | "abi": [], 6 | "bytecode": "0x", 7 | "deployedBytecode": "0x", 8 | "linkReferences": {}, 9 | "deployedLinkReferences": {} 10 | } 11 | -------------------------------------------------------------------------------- /artifacts/@openzeppelin/contracts/token/ERC721/ERC721.sol/ERC721.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "..\\..\\..\\..\\..\\build-info\\1684140606a8b826ecd0a3b1ad391a8f.json" 4 | } 5 | -------------------------------------------------------------------------------- /artifacts/@openzeppelin/contracts/token/ERC721/IERC721.sol/IERC721.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "..\\..\\..\\..\\..\\build-info\\1684140606a8b826ecd0a3b1ad391a8f.json" 4 | } 5 | -------------------------------------------------------------------------------- /artifacts/@openzeppelin/contracts/token/ERC721/IERC721.sol/IERC721.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "IERC721", 4 | "sourceName": "@openzeppelin/contracts/token/ERC721/IERC721.sol", 5 | "abi": [ 6 | { 7 | "anonymous": false, 8 | "inputs": [ 9 | { 10 | "indexed": true, 11 | "internalType": "address", 12 | "name": "owner", 13 | "type": "address" 14 | }, 15 | { 16 | "indexed": true, 17 | "internalType": "address", 18 | "name": "approved", 19 | "type": "address" 20 | }, 21 | { 22 | "indexed": true, 23 | "internalType": "uint256", 24 | "name": "tokenId", 25 | "type": "uint256" 26 | } 27 | ], 28 | "name": "Approval", 29 | "type": "event" 30 | }, 31 | { 32 | "anonymous": false, 33 | "inputs": [ 34 | { 35 | "indexed": true, 36 | "internalType": "address", 37 | "name": "owner", 38 | "type": "address" 39 | }, 40 | { 41 | "indexed": true, 42 | "internalType": "address", 43 | "name": "operator", 44 | "type": "address" 45 | }, 46 | { 47 | "indexed": false, 48 | "internalType": "bool", 49 | "name": "approved", 50 | "type": "bool" 51 | } 52 | ], 53 | "name": "ApprovalForAll", 54 | "type": "event" 55 | }, 56 | { 57 | "anonymous": false, 58 | "inputs": [ 59 | { 60 | "indexed": true, 61 | "internalType": "address", 62 | "name": "from", 63 | "type": "address" 64 | }, 65 | { 66 | "indexed": true, 67 | "internalType": "address", 68 | "name": "to", 69 | "type": "address" 70 | }, 71 | { 72 | "indexed": true, 73 | "internalType": "uint256", 74 | "name": "tokenId", 75 | "type": "uint256" 76 | } 77 | ], 78 | "name": "Transfer", 79 | "type": "event" 80 | }, 81 | { 82 | "inputs": [ 83 | { 84 | "internalType": "address", 85 | "name": "to", 86 | "type": "address" 87 | }, 88 | { 89 | "internalType": "uint256", 90 | "name": "tokenId", 91 | "type": "uint256" 92 | } 93 | ], 94 | "name": "approve", 95 | "outputs": [], 96 | "stateMutability": "nonpayable", 97 | "type": "function" 98 | }, 99 | { 100 | "inputs": [ 101 | { 102 | "internalType": "address", 103 | "name": "owner", 104 | "type": "address" 105 | } 106 | ], 107 | "name": "balanceOf", 108 | "outputs": [ 109 | { 110 | "internalType": "uint256", 111 | "name": "balance", 112 | "type": "uint256" 113 | } 114 | ], 115 | "stateMutability": "view", 116 | "type": "function" 117 | }, 118 | { 119 | "inputs": [ 120 | { 121 | "internalType": "uint256", 122 | "name": "tokenId", 123 | "type": "uint256" 124 | } 125 | ], 126 | "name": "getApproved", 127 | "outputs": [ 128 | { 129 | "internalType": "address", 130 | "name": "operator", 131 | "type": "address" 132 | } 133 | ], 134 | "stateMutability": "view", 135 | "type": "function" 136 | }, 137 | { 138 | "inputs": [ 139 | { 140 | "internalType": "address", 141 | "name": "owner", 142 | "type": "address" 143 | }, 144 | { 145 | "internalType": "address", 146 | "name": "operator", 147 | "type": "address" 148 | } 149 | ], 150 | "name": "isApprovedForAll", 151 | "outputs": [ 152 | { 153 | "internalType": "bool", 154 | "name": "", 155 | "type": "bool" 156 | } 157 | ], 158 | "stateMutability": "view", 159 | "type": "function" 160 | }, 161 | { 162 | "inputs": [ 163 | { 164 | "internalType": "uint256", 165 | "name": "tokenId", 166 | "type": "uint256" 167 | } 168 | ], 169 | "name": "ownerOf", 170 | "outputs": [ 171 | { 172 | "internalType": "address", 173 | "name": "owner", 174 | "type": "address" 175 | } 176 | ], 177 | "stateMutability": "view", 178 | "type": "function" 179 | }, 180 | { 181 | "inputs": [ 182 | { 183 | "internalType": "address", 184 | "name": "from", 185 | "type": "address" 186 | }, 187 | { 188 | "internalType": "address", 189 | "name": "to", 190 | "type": "address" 191 | }, 192 | { 193 | "internalType": "uint256", 194 | "name": "tokenId", 195 | "type": "uint256" 196 | } 197 | ], 198 | "name": "safeTransferFrom", 199 | "outputs": [], 200 | "stateMutability": "nonpayable", 201 | "type": "function" 202 | }, 203 | { 204 | "inputs": [ 205 | { 206 | "internalType": "address", 207 | "name": "from", 208 | "type": "address" 209 | }, 210 | { 211 | "internalType": "address", 212 | "name": "to", 213 | "type": "address" 214 | }, 215 | { 216 | "internalType": "uint256", 217 | "name": "tokenId", 218 | "type": "uint256" 219 | }, 220 | { 221 | "internalType": "bytes", 222 | "name": "data", 223 | "type": "bytes" 224 | } 225 | ], 226 | "name": "safeTransferFrom", 227 | "outputs": [], 228 | "stateMutability": "nonpayable", 229 | "type": "function" 230 | }, 231 | { 232 | "inputs": [ 233 | { 234 | "internalType": "address", 235 | "name": "operator", 236 | "type": "address" 237 | }, 238 | { 239 | "internalType": "bool", 240 | "name": "_approved", 241 | "type": "bool" 242 | } 243 | ], 244 | "name": "setApprovalForAll", 245 | "outputs": [], 246 | "stateMutability": "nonpayable", 247 | "type": "function" 248 | }, 249 | { 250 | "inputs": [ 251 | { 252 | "internalType": "bytes4", 253 | "name": "interfaceId", 254 | "type": "bytes4" 255 | } 256 | ], 257 | "name": "supportsInterface", 258 | "outputs": [ 259 | { 260 | "internalType": "bool", 261 | "name": "", 262 | "type": "bool" 263 | } 264 | ], 265 | "stateMutability": "view", 266 | "type": "function" 267 | }, 268 | { 269 | "inputs": [ 270 | { 271 | "internalType": "address", 272 | "name": "from", 273 | "type": "address" 274 | }, 275 | { 276 | "internalType": "address", 277 | "name": "to", 278 | "type": "address" 279 | }, 280 | { 281 | "internalType": "uint256", 282 | "name": "tokenId", 283 | "type": "uint256" 284 | } 285 | ], 286 | "name": "transferFrom", 287 | "outputs": [], 288 | "stateMutability": "nonpayable", 289 | "type": "function" 290 | } 291 | ], 292 | "bytecode": "0x", 293 | "deployedBytecode": "0x", 294 | "linkReferences": {}, 295 | "deployedLinkReferences": {} 296 | } 297 | -------------------------------------------------------------------------------- /artifacts/@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol/IERC721Receiver.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "..\\..\\..\\..\\..\\build-info\\1684140606a8b826ecd0a3b1ad391a8f.json" 4 | } 5 | -------------------------------------------------------------------------------- /artifacts/@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol/IERC721Receiver.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "IERC721Receiver", 4 | "sourceName": "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol", 5 | "abi": [ 6 | { 7 | "inputs": [ 8 | { 9 | "internalType": "address", 10 | "name": "operator", 11 | "type": "address" 12 | }, 13 | { 14 | "internalType": "address", 15 | "name": "from", 16 | "type": "address" 17 | }, 18 | { 19 | "internalType": "uint256", 20 | "name": "tokenId", 21 | "type": "uint256" 22 | }, 23 | { 24 | "internalType": "bytes", 25 | "name": "data", 26 | "type": "bytes" 27 | } 28 | ], 29 | "name": "onERC721Received", 30 | "outputs": [ 31 | { 32 | "internalType": "bytes4", 33 | "name": "", 34 | "type": "bytes4" 35 | } 36 | ], 37 | "stateMutability": "nonpayable", 38 | "type": "function" 39 | } 40 | ], 41 | "bytecode": "0x", 42 | "deployedBytecode": "0x", 43 | "linkReferences": {}, 44 | "deployedLinkReferences": {} 45 | } 46 | -------------------------------------------------------------------------------- /artifacts/@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol/ERC721URIStorage.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "..\\..\\..\\..\\..\\..\\build-info\\1684140606a8b826ecd0a3b1ad391a8f.json" 4 | } 5 | -------------------------------------------------------------------------------- /artifacts/@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol/ERC721URIStorage.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "ERC721URIStorage", 4 | "sourceName": "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", 5 | "abi": [ 6 | { 7 | "anonymous": false, 8 | "inputs": [ 9 | { 10 | "indexed": true, 11 | "internalType": "address", 12 | "name": "owner", 13 | "type": "address" 14 | }, 15 | { 16 | "indexed": true, 17 | "internalType": "address", 18 | "name": "approved", 19 | "type": "address" 20 | }, 21 | { 22 | "indexed": true, 23 | "internalType": "uint256", 24 | "name": "tokenId", 25 | "type": "uint256" 26 | } 27 | ], 28 | "name": "Approval", 29 | "type": "event" 30 | }, 31 | { 32 | "anonymous": false, 33 | "inputs": [ 34 | { 35 | "indexed": true, 36 | "internalType": "address", 37 | "name": "owner", 38 | "type": "address" 39 | }, 40 | { 41 | "indexed": true, 42 | "internalType": "address", 43 | "name": "operator", 44 | "type": "address" 45 | }, 46 | { 47 | "indexed": false, 48 | "internalType": "bool", 49 | "name": "approved", 50 | "type": "bool" 51 | } 52 | ], 53 | "name": "ApprovalForAll", 54 | "type": "event" 55 | }, 56 | { 57 | "anonymous": false, 58 | "inputs": [ 59 | { 60 | "indexed": true, 61 | "internalType": "address", 62 | "name": "from", 63 | "type": "address" 64 | }, 65 | { 66 | "indexed": true, 67 | "internalType": "address", 68 | "name": "to", 69 | "type": "address" 70 | }, 71 | { 72 | "indexed": true, 73 | "internalType": "uint256", 74 | "name": "tokenId", 75 | "type": "uint256" 76 | } 77 | ], 78 | "name": "Transfer", 79 | "type": "event" 80 | }, 81 | { 82 | "inputs": [ 83 | { 84 | "internalType": "address", 85 | "name": "to", 86 | "type": "address" 87 | }, 88 | { 89 | "internalType": "uint256", 90 | "name": "tokenId", 91 | "type": "uint256" 92 | } 93 | ], 94 | "name": "approve", 95 | "outputs": [], 96 | "stateMutability": "nonpayable", 97 | "type": "function" 98 | }, 99 | { 100 | "inputs": [ 101 | { 102 | "internalType": "address", 103 | "name": "owner", 104 | "type": "address" 105 | } 106 | ], 107 | "name": "balanceOf", 108 | "outputs": [ 109 | { 110 | "internalType": "uint256", 111 | "name": "", 112 | "type": "uint256" 113 | } 114 | ], 115 | "stateMutability": "view", 116 | "type": "function" 117 | }, 118 | { 119 | "inputs": [ 120 | { 121 | "internalType": "uint256", 122 | "name": "tokenId", 123 | "type": "uint256" 124 | } 125 | ], 126 | "name": "getApproved", 127 | "outputs": [ 128 | { 129 | "internalType": "address", 130 | "name": "", 131 | "type": "address" 132 | } 133 | ], 134 | "stateMutability": "view", 135 | "type": "function" 136 | }, 137 | { 138 | "inputs": [ 139 | { 140 | "internalType": "address", 141 | "name": "owner", 142 | "type": "address" 143 | }, 144 | { 145 | "internalType": "address", 146 | "name": "operator", 147 | "type": "address" 148 | } 149 | ], 150 | "name": "isApprovedForAll", 151 | "outputs": [ 152 | { 153 | "internalType": "bool", 154 | "name": "", 155 | "type": "bool" 156 | } 157 | ], 158 | "stateMutability": "view", 159 | "type": "function" 160 | }, 161 | { 162 | "inputs": [], 163 | "name": "name", 164 | "outputs": [ 165 | { 166 | "internalType": "string", 167 | "name": "", 168 | "type": "string" 169 | } 170 | ], 171 | "stateMutability": "view", 172 | "type": "function" 173 | }, 174 | { 175 | "inputs": [ 176 | { 177 | "internalType": "uint256", 178 | "name": "tokenId", 179 | "type": "uint256" 180 | } 181 | ], 182 | "name": "ownerOf", 183 | "outputs": [ 184 | { 185 | "internalType": "address", 186 | "name": "", 187 | "type": "address" 188 | } 189 | ], 190 | "stateMutability": "view", 191 | "type": "function" 192 | }, 193 | { 194 | "inputs": [ 195 | { 196 | "internalType": "address", 197 | "name": "from", 198 | "type": "address" 199 | }, 200 | { 201 | "internalType": "address", 202 | "name": "to", 203 | "type": "address" 204 | }, 205 | { 206 | "internalType": "uint256", 207 | "name": "tokenId", 208 | "type": "uint256" 209 | } 210 | ], 211 | "name": "safeTransferFrom", 212 | "outputs": [], 213 | "stateMutability": "nonpayable", 214 | "type": "function" 215 | }, 216 | { 217 | "inputs": [ 218 | { 219 | "internalType": "address", 220 | "name": "from", 221 | "type": "address" 222 | }, 223 | { 224 | "internalType": "address", 225 | "name": "to", 226 | "type": "address" 227 | }, 228 | { 229 | "internalType": "uint256", 230 | "name": "tokenId", 231 | "type": "uint256" 232 | }, 233 | { 234 | "internalType": "bytes", 235 | "name": "_data", 236 | "type": "bytes" 237 | } 238 | ], 239 | "name": "safeTransferFrom", 240 | "outputs": [], 241 | "stateMutability": "nonpayable", 242 | "type": "function" 243 | }, 244 | { 245 | "inputs": [ 246 | { 247 | "internalType": "address", 248 | "name": "operator", 249 | "type": "address" 250 | }, 251 | { 252 | "internalType": "bool", 253 | "name": "approved", 254 | "type": "bool" 255 | } 256 | ], 257 | "name": "setApprovalForAll", 258 | "outputs": [], 259 | "stateMutability": "nonpayable", 260 | "type": "function" 261 | }, 262 | { 263 | "inputs": [ 264 | { 265 | "internalType": "bytes4", 266 | "name": "interfaceId", 267 | "type": "bytes4" 268 | } 269 | ], 270 | "name": "supportsInterface", 271 | "outputs": [ 272 | { 273 | "internalType": "bool", 274 | "name": "", 275 | "type": "bool" 276 | } 277 | ], 278 | "stateMutability": "view", 279 | "type": "function" 280 | }, 281 | { 282 | "inputs": [], 283 | "name": "symbol", 284 | "outputs": [ 285 | { 286 | "internalType": "string", 287 | "name": "", 288 | "type": "string" 289 | } 290 | ], 291 | "stateMutability": "view", 292 | "type": "function" 293 | }, 294 | { 295 | "inputs": [ 296 | { 297 | "internalType": "uint256", 298 | "name": "tokenId", 299 | "type": "uint256" 300 | } 301 | ], 302 | "name": "tokenURI", 303 | "outputs": [ 304 | { 305 | "internalType": "string", 306 | "name": "", 307 | "type": "string" 308 | } 309 | ], 310 | "stateMutability": "view", 311 | "type": "function" 312 | }, 313 | { 314 | "inputs": [ 315 | { 316 | "internalType": "address", 317 | "name": "from", 318 | "type": "address" 319 | }, 320 | { 321 | "internalType": "address", 322 | "name": "to", 323 | "type": "address" 324 | }, 325 | { 326 | "internalType": "uint256", 327 | "name": "tokenId", 328 | "type": "uint256" 329 | } 330 | ], 331 | "name": "transferFrom", 332 | "outputs": [], 333 | "stateMutability": "nonpayable", 334 | "type": "function" 335 | } 336 | ], 337 | "bytecode": "0x", 338 | "deployedBytecode": "0x", 339 | "linkReferences": {}, 340 | "deployedLinkReferences": {} 341 | } 342 | -------------------------------------------------------------------------------- /artifacts/@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol/IERC721Metadata.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "..\\..\\..\\..\\..\\..\\build-info\\1684140606a8b826ecd0a3b1ad391a8f.json" 4 | } 5 | -------------------------------------------------------------------------------- /artifacts/@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol/IERC721Metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "IERC721Metadata", 4 | "sourceName": "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol", 5 | "abi": [ 6 | { 7 | "anonymous": false, 8 | "inputs": [ 9 | { 10 | "indexed": true, 11 | "internalType": "address", 12 | "name": "owner", 13 | "type": "address" 14 | }, 15 | { 16 | "indexed": true, 17 | "internalType": "address", 18 | "name": "approved", 19 | "type": "address" 20 | }, 21 | { 22 | "indexed": true, 23 | "internalType": "uint256", 24 | "name": "tokenId", 25 | "type": "uint256" 26 | } 27 | ], 28 | "name": "Approval", 29 | "type": "event" 30 | }, 31 | { 32 | "anonymous": false, 33 | "inputs": [ 34 | { 35 | "indexed": true, 36 | "internalType": "address", 37 | "name": "owner", 38 | "type": "address" 39 | }, 40 | { 41 | "indexed": true, 42 | "internalType": "address", 43 | "name": "operator", 44 | "type": "address" 45 | }, 46 | { 47 | "indexed": false, 48 | "internalType": "bool", 49 | "name": "approved", 50 | "type": "bool" 51 | } 52 | ], 53 | "name": "ApprovalForAll", 54 | "type": "event" 55 | }, 56 | { 57 | "anonymous": false, 58 | "inputs": [ 59 | { 60 | "indexed": true, 61 | "internalType": "address", 62 | "name": "from", 63 | "type": "address" 64 | }, 65 | { 66 | "indexed": true, 67 | "internalType": "address", 68 | "name": "to", 69 | "type": "address" 70 | }, 71 | { 72 | "indexed": true, 73 | "internalType": "uint256", 74 | "name": "tokenId", 75 | "type": "uint256" 76 | } 77 | ], 78 | "name": "Transfer", 79 | "type": "event" 80 | }, 81 | { 82 | "inputs": [ 83 | { 84 | "internalType": "address", 85 | "name": "to", 86 | "type": "address" 87 | }, 88 | { 89 | "internalType": "uint256", 90 | "name": "tokenId", 91 | "type": "uint256" 92 | } 93 | ], 94 | "name": "approve", 95 | "outputs": [], 96 | "stateMutability": "nonpayable", 97 | "type": "function" 98 | }, 99 | { 100 | "inputs": [ 101 | { 102 | "internalType": "address", 103 | "name": "owner", 104 | "type": "address" 105 | } 106 | ], 107 | "name": "balanceOf", 108 | "outputs": [ 109 | { 110 | "internalType": "uint256", 111 | "name": "balance", 112 | "type": "uint256" 113 | } 114 | ], 115 | "stateMutability": "view", 116 | "type": "function" 117 | }, 118 | { 119 | "inputs": [ 120 | { 121 | "internalType": "uint256", 122 | "name": "tokenId", 123 | "type": "uint256" 124 | } 125 | ], 126 | "name": "getApproved", 127 | "outputs": [ 128 | { 129 | "internalType": "address", 130 | "name": "operator", 131 | "type": "address" 132 | } 133 | ], 134 | "stateMutability": "view", 135 | "type": "function" 136 | }, 137 | { 138 | "inputs": [ 139 | { 140 | "internalType": "address", 141 | "name": "owner", 142 | "type": "address" 143 | }, 144 | { 145 | "internalType": "address", 146 | "name": "operator", 147 | "type": "address" 148 | } 149 | ], 150 | "name": "isApprovedForAll", 151 | "outputs": [ 152 | { 153 | "internalType": "bool", 154 | "name": "", 155 | "type": "bool" 156 | } 157 | ], 158 | "stateMutability": "view", 159 | "type": "function" 160 | }, 161 | { 162 | "inputs": [], 163 | "name": "name", 164 | "outputs": [ 165 | { 166 | "internalType": "string", 167 | "name": "", 168 | "type": "string" 169 | } 170 | ], 171 | "stateMutability": "view", 172 | "type": "function" 173 | }, 174 | { 175 | "inputs": [ 176 | { 177 | "internalType": "uint256", 178 | "name": "tokenId", 179 | "type": "uint256" 180 | } 181 | ], 182 | "name": "ownerOf", 183 | "outputs": [ 184 | { 185 | "internalType": "address", 186 | "name": "owner", 187 | "type": "address" 188 | } 189 | ], 190 | "stateMutability": "view", 191 | "type": "function" 192 | }, 193 | { 194 | "inputs": [ 195 | { 196 | "internalType": "address", 197 | "name": "from", 198 | "type": "address" 199 | }, 200 | { 201 | "internalType": "address", 202 | "name": "to", 203 | "type": "address" 204 | }, 205 | { 206 | "internalType": "uint256", 207 | "name": "tokenId", 208 | "type": "uint256" 209 | } 210 | ], 211 | "name": "safeTransferFrom", 212 | "outputs": [], 213 | "stateMutability": "nonpayable", 214 | "type": "function" 215 | }, 216 | { 217 | "inputs": [ 218 | { 219 | "internalType": "address", 220 | "name": "from", 221 | "type": "address" 222 | }, 223 | { 224 | "internalType": "address", 225 | "name": "to", 226 | "type": "address" 227 | }, 228 | { 229 | "internalType": "uint256", 230 | "name": "tokenId", 231 | "type": "uint256" 232 | }, 233 | { 234 | "internalType": "bytes", 235 | "name": "data", 236 | "type": "bytes" 237 | } 238 | ], 239 | "name": "safeTransferFrom", 240 | "outputs": [], 241 | "stateMutability": "nonpayable", 242 | "type": "function" 243 | }, 244 | { 245 | "inputs": [ 246 | { 247 | "internalType": "address", 248 | "name": "operator", 249 | "type": "address" 250 | }, 251 | { 252 | "internalType": "bool", 253 | "name": "_approved", 254 | "type": "bool" 255 | } 256 | ], 257 | "name": "setApprovalForAll", 258 | "outputs": [], 259 | "stateMutability": "nonpayable", 260 | "type": "function" 261 | }, 262 | { 263 | "inputs": [ 264 | { 265 | "internalType": "bytes4", 266 | "name": "interfaceId", 267 | "type": "bytes4" 268 | } 269 | ], 270 | "name": "supportsInterface", 271 | "outputs": [ 272 | { 273 | "internalType": "bool", 274 | "name": "", 275 | "type": "bool" 276 | } 277 | ], 278 | "stateMutability": "view", 279 | "type": "function" 280 | }, 281 | { 282 | "inputs": [], 283 | "name": "symbol", 284 | "outputs": [ 285 | { 286 | "internalType": "string", 287 | "name": "", 288 | "type": "string" 289 | } 290 | ], 291 | "stateMutability": "view", 292 | "type": "function" 293 | }, 294 | { 295 | "inputs": [ 296 | { 297 | "internalType": "uint256", 298 | "name": "tokenId", 299 | "type": "uint256" 300 | } 301 | ], 302 | "name": "tokenURI", 303 | "outputs": [ 304 | { 305 | "internalType": "string", 306 | "name": "", 307 | "type": "string" 308 | } 309 | ], 310 | "stateMutability": "view", 311 | "type": "function" 312 | }, 313 | { 314 | "inputs": [ 315 | { 316 | "internalType": "address", 317 | "name": "from", 318 | "type": "address" 319 | }, 320 | { 321 | "internalType": "address", 322 | "name": "to", 323 | "type": "address" 324 | }, 325 | { 326 | "internalType": "uint256", 327 | "name": "tokenId", 328 | "type": "uint256" 329 | } 330 | ], 331 | "name": "transferFrom", 332 | "outputs": [], 333 | "stateMutability": "nonpayable", 334 | "type": "function" 335 | } 336 | ], 337 | "bytecode": "0x", 338 | "deployedBytecode": "0x", 339 | "linkReferences": {}, 340 | "deployedLinkReferences": {} 341 | } 342 | -------------------------------------------------------------------------------- /artifacts/@openzeppelin/contracts/utils/Address.sol/Address.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "..\\..\\..\\..\\build-info\\1684140606a8b826ecd0a3b1ad391a8f.json" 4 | } 5 | -------------------------------------------------------------------------------- /artifacts/@openzeppelin/contracts/utils/Address.sol/Address.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "Address", 4 | "sourceName": "@openzeppelin/contracts/utils/Address.sol", 5 | "abi": [], 6 | "bytecode": "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220066a9250189743a9cbeb9f28d0c873e97a8b27ae17f890744fc9ec97e7daf75564736f6c63430008040033", 7 | "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220066a9250189743a9cbeb9f28d0c873e97a8b27ae17f890744fc9ec97e7daf75564736f6c63430008040033", 8 | "linkReferences": {}, 9 | "deployedLinkReferences": {} 10 | } 11 | -------------------------------------------------------------------------------- /artifacts/@openzeppelin/contracts/utils/Context.sol/Context.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "..\\..\\..\\..\\build-info\\1684140606a8b826ecd0a3b1ad391a8f.json" 4 | } 5 | -------------------------------------------------------------------------------- /artifacts/@openzeppelin/contracts/utils/Context.sol/Context.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "Context", 4 | "sourceName": "@openzeppelin/contracts/utils/Context.sol", 5 | "abi": [], 6 | "bytecode": "0x", 7 | "deployedBytecode": "0x", 8 | "linkReferences": {}, 9 | "deployedLinkReferences": {} 10 | } 11 | -------------------------------------------------------------------------------- /artifacts/@openzeppelin/contracts/utils/Counters.sol/Counters.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "..\\..\\..\\..\\build-info\\1684140606a8b826ecd0a3b1ad391a8f.json" 4 | } 5 | -------------------------------------------------------------------------------- /artifacts/@openzeppelin/contracts/utils/Counters.sol/Counters.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "Counters", 4 | "sourceName": "@openzeppelin/contracts/utils/Counters.sol", 5 | "abi": [], 6 | "bytecode": "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122082363737ed86c46311e47b3ce5016b7a17d55e4018a56219d1b6c8c6c803ba5064736f6c63430008040033", 7 | "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122082363737ed86c46311e47b3ce5016b7a17d55e4018a56219d1b6c8c6c803ba5064736f6c63430008040033", 8 | "linkReferences": {}, 9 | "deployedLinkReferences": {} 10 | } 11 | -------------------------------------------------------------------------------- /artifacts/@openzeppelin/contracts/utils/Strings.sol/Strings.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "..\\..\\..\\..\\build-info\\1684140606a8b826ecd0a3b1ad391a8f.json" 4 | } 5 | -------------------------------------------------------------------------------- /artifacts/@openzeppelin/contracts/utils/Strings.sol/Strings.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "Strings", 4 | "sourceName": "@openzeppelin/contracts/utils/Strings.sol", 5 | "abi": [], 6 | "bytecode": "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212205cc7f5402224d733656a2c53cd0af9c605b30556e49491a001cfbf2f80887e2364736f6c63430008040033", 7 | "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212205cc7f5402224d733656a2c53cd0af9c605b30556e49491a001cfbf2f80887e2364736f6c63430008040033", 8 | "linkReferences": {}, 9 | "deployedLinkReferences": {} 10 | } 11 | -------------------------------------------------------------------------------- /artifacts/@openzeppelin/contracts/utils/introspection/ERC165.sol/ERC165.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "..\\..\\..\\..\\..\\build-info\\1684140606a8b826ecd0a3b1ad391a8f.json" 4 | } 5 | -------------------------------------------------------------------------------- /artifacts/@openzeppelin/contracts/utils/introspection/ERC165.sol/ERC165.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "ERC165", 4 | "sourceName": "@openzeppelin/contracts/utils/introspection/ERC165.sol", 5 | "abi": [ 6 | { 7 | "inputs": [ 8 | { 9 | "internalType": "bytes4", 10 | "name": "interfaceId", 11 | "type": "bytes4" 12 | } 13 | ], 14 | "name": "supportsInterface", 15 | "outputs": [ 16 | { 17 | "internalType": "bool", 18 | "name": "", 19 | "type": "bool" 20 | } 21 | ], 22 | "stateMutability": "view", 23 | "type": "function" 24 | } 25 | ], 26 | "bytecode": "0x", 27 | "deployedBytecode": "0x", 28 | "linkReferences": {}, 29 | "deployedLinkReferences": {} 30 | } 31 | -------------------------------------------------------------------------------- /artifacts/@openzeppelin/contracts/utils/introspection/IERC165.sol/IERC165.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "..\\..\\..\\..\\..\\build-info\\1684140606a8b826ecd0a3b1ad391a8f.json" 4 | } 5 | -------------------------------------------------------------------------------- /artifacts/@openzeppelin/contracts/utils/introspection/IERC165.sol/IERC165.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "IERC165", 4 | "sourceName": "@openzeppelin/contracts/utils/introspection/IERC165.sol", 5 | "abi": [ 6 | { 7 | "inputs": [ 8 | { 9 | "internalType": "bytes4", 10 | "name": "interfaceId", 11 | "type": "bytes4" 12 | } 13 | ], 14 | "name": "supportsInterface", 15 | "outputs": [ 16 | { 17 | "internalType": "bool", 18 | "name": "", 19 | "type": "bool" 20 | } 21 | ], 22 | "stateMutability": "view", 23 | "type": "function" 24 | } 25 | ], 26 | "bytecode": "0x", 27 | "deployedBytecode": "0x", 28 | "linkReferences": {}, 29 | "deployedLinkReferences": {} 30 | } 31 | -------------------------------------------------------------------------------- /artifacts/contracts/Market.sol/NFTMarket.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "..\\..\\build-info\\1684140606a8b826ecd0a3b1ad391a8f.json" 4 | } 5 | -------------------------------------------------------------------------------- /artifacts/contracts/NFT.sol/NFT.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "..\\..\\build-info\\1684140606a8b826ecd0a3b1ad391a8f.json" 4 | } 5 | -------------------------------------------------------------------------------- /artifacts/hardhat/console.sol/console.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "..\\..\\build-info\\1684140606a8b826ecd0a3b1ad391a8f.json" 4 | } 5 | -------------------------------------------------------------------------------- /artifacts/hardhat/console.sol/console.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "console", 4 | "sourceName": "hardhat/console.sol", 5 | "abi": [], 6 | "bytecode": "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220cd1e8ce572c5f24bf61821c96174df3966ca45777a0f790101d5619d487d5aa664736f6c63430008040033", 7 | "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220cd1e8ce572c5f24bf61821c96174df3966ca45777a0f790101d5619d487d5aa664736f6c63430008040033", 8 | "linkReferences": {}, 9 | "deployedLinkReferences": {} 10 | } 11 | -------------------------------------------------------------------------------- /cache/solidity-files-cache.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-cache-2", 3 | "files": { 4 | "G:\\Projects\\DEV-NFT\\contracts\\Market.sol": { 5 | "lastModificationDate": 1638786706448, 6 | "contentHash": "8265a30344512b641af4b28ed3fbfe7f", 7 | "sourceName": "contracts/Market.sol", 8 | "solcConfig": { 9 | "version": "0.8.4", 10 | "settings": { 11 | "optimizer": { 12 | "enabled": true, 13 | "runs": 200 14 | }, 15 | "outputSelection": { 16 | "*": { 17 | "*": [ 18 | "abi", 19 | "evm.bytecode", 20 | "evm.deployedBytecode", 21 | "evm.methodIdentifiers", 22 | "metadata" 23 | ], 24 | "": [ 25 | "ast" 26 | ] 27 | } 28 | } 29 | } 30 | }, 31 | "imports": [ 32 | "@openzeppelin/contracts/utils/Counters.sol", 33 | "@openzeppelin/contracts/security/ReentrancyGuard.sol", 34 | "@openzeppelin/contracts/token/ERC721/ERC721.sol", 35 | "hardhat/console.sol" 36 | ], 37 | "versionPragmas": [ 38 | "^0.8.3" 39 | ], 40 | "artifacts": [ 41 | "NFTMarket" 42 | ] 43 | }, 44 | "G:\\Projects\\DEV-NFT\\node_modules\\@openzeppelin\\contracts\\utils\\Counters.sol": { 45 | "lastModificationDate": 1637760793850, 46 | "contentHash": "b7811964d33f23b2d45ed3ebb76a4548", 47 | "sourceName": "@openzeppelin/contracts/utils/Counters.sol", 48 | "solcConfig": { 49 | "version": "0.8.4", 50 | "settings": { 51 | "optimizer": { 52 | "enabled": true, 53 | "runs": 200 54 | }, 55 | "outputSelection": { 56 | "*": { 57 | "*": [ 58 | "abi", 59 | "evm.bytecode", 60 | "evm.deployedBytecode", 61 | "evm.methodIdentifiers", 62 | "metadata" 63 | ], 64 | "": [ 65 | "ast" 66 | ] 67 | } 68 | } 69 | } 70 | }, 71 | "imports": [], 72 | "versionPragmas": [ 73 | "^0.8.0" 74 | ], 75 | "artifacts": [ 76 | "Counters" 77 | ] 78 | }, 79 | "G:\\Projects\\DEV-NFT\\node_modules\\@openzeppelin\\contracts\\security\\ReentrancyGuard.sol": { 80 | "lastModificationDate": 1637760798965, 81 | "contentHash": "53fbff678f378956efcb207fa748eaa6", 82 | "sourceName": "@openzeppelin/contracts/security/ReentrancyGuard.sol", 83 | "solcConfig": { 84 | "version": "0.8.4", 85 | "settings": { 86 | "optimizer": { 87 | "enabled": true, 88 | "runs": 200 89 | }, 90 | "outputSelection": { 91 | "*": { 92 | "*": [ 93 | "abi", 94 | "evm.bytecode", 95 | "evm.deployedBytecode", 96 | "evm.methodIdentifiers", 97 | "metadata" 98 | ], 99 | "": [ 100 | "ast" 101 | ] 102 | } 103 | } 104 | } 105 | }, 106 | "imports": [], 107 | "versionPragmas": [ 108 | "^0.8.0" 109 | ], 110 | "artifacts": [ 111 | "ReentrancyGuard" 112 | ] 113 | }, 114 | "G:\\Projects\\DEV-NFT\\node_modules\\@openzeppelin\\contracts\\token\\ERC721\\ERC721.sol": { 115 | "lastModificationDate": 1637760795100, 116 | "contentHash": "a4f6dccf3f15b6844e357f737a572388", 117 | "sourceName": "@openzeppelin/contracts/token/ERC721/ERC721.sol", 118 | "solcConfig": { 119 | "version": "0.8.4", 120 | "settings": { 121 | "optimizer": { 122 | "enabled": true, 123 | "runs": 200 124 | }, 125 | "outputSelection": { 126 | "*": { 127 | "*": [ 128 | "abi", 129 | "evm.bytecode", 130 | "evm.deployedBytecode", 131 | "evm.methodIdentifiers", 132 | "metadata" 133 | ], 134 | "": [ 135 | "ast" 136 | ] 137 | } 138 | } 139 | } 140 | }, 141 | "imports": [ 142 | "./IERC721.sol", 143 | "./IERC721Receiver.sol", 144 | "./extensions/IERC721Metadata.sol", 145 | "../../utils/Address.sol", 146 | "../../utils/Context.sol", 147 | "../../utils/Strings.sol", 148 | "../../utils/introspection/ERC165.sol" 149 | ], 150 | "versionPragmas": [ 151 | "^0.8.0" 152 | ], 153 | "artifacts": [ 154 | "ERC721" 155 | ] 156 | }, 157 | "G:\\Projects\\DEV-NFT\\node_modules\\hardhat\\console.sol": { 158 | "lastModificationDate": 1637759788190, 159 | "contentHash": "cc4777addd464ea56fa35b1c45df0591", 160 | "sourceName": "hardhat/console.sol", 161 | "solcConfig": { 162 | "version": "0.8.4", 163 | "settings": { 164 | "optimizer": { 165 | "enabled": true, 166 | "runs": 200 167 | }, 168 | "outputSelection": { 169 | "*": { 170 | "*": [ 171 | "abi", 172 | "evm.bytecode", 173 | "evm.deployedBytecode", 174 | "evm.methodIdentifiers", 175 | "metadata" 176 | ], 177 | "": [ 178 | "ast" 179 | ] 180 | } 181 | } 182 | } 183 | }, 184 | "imports": [], 185 | "versionPragmas": [ 186 | ">=0.4.22 <0.9.0" 187 | ], 188 | "artifacts": [ 189 | "console" 190 | ] 191 | }, 192 | "G:\\Projects\\DEV-NFT\\node_modules\\@openzeppelin\\contracts\\token\\ERC721\\IERC721.sol": { 193 | "lastModificationDate": 1637760798314, 194 | "contentHash": "53919d6975f2c0f3dffee5e3a1064116", 195 | "sourceName": "@openzeppelin/contracts/token/ERC721/IERC721.sol", 196 | "solcConfig": { 197 | "version": "0.8.4", 198 | "settings": { 199 | "optimizer": { 200 | "enabled": true, 201 | "runs": 200 202 | }, 203 | "outputSelection": { 204 | "*": { 205 | "*": [ 206 | "abi", 207 | "evm.bytecode", 208 | "evm.deployedBytecode", 209 | "evm.methodIdentifiers", 210 | "metadata" 211 | ], 212 | "": [ 213 | "ast" 214 | ] 215 | } 216 | } 217 | } 218 | }, 219 | "imports": [ 220 | "../../utils/introspection/IERC165.sol" 221 | ], 222 | "versionPragmas": [ 223 | "^0.8.0" 224 | ], 225 | "artifacts": [ 226 | "IERC721" 227 | ] 228 | }, 229 | "G:\\Projects\\DEV-NFT\\node_modules\\@openzeppelin\\contracts\\token\\ERC721\\IERC721Receiver.sol": { 230 | "lastModificationDate": 1637760798511, 231 | "contentHash": "9a367cecca6fed80a3e975b7e6b3bd5c", 232 | "sourceName": "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol", 233 | "solcConfig": { 234 | "version": "0.8.4", 235 | "settings": { 236 | "optimizer": { 237 | "enabled": true, 238 | "runs": 200 239 | }, 240 | "outputSelection": { 241 | "*": { 242 | "*": [ 243 | "abi", 244 | "evm.bytecode", 245 | "evm.deployedBytecode", 246 | "evm.methodIdentifiers", 247 | "metadata" 248 | ], 249 | "": [ 250 | "ast" 251 | ] 252 | } 253 | } 254 | } 255 | }, 256 | "imports": [], 257 | "versionPragmas": [ 258 | "^0.8.0" 259 | ], 260 | "artifacts": [ 261 | "IERC721Receiver" 262 | ] 263 | }, 264 | "G:\\Projects\\DEV-NFT\\node_modules\\@openzeppelin\\contracts\\token\\ERC721\\extensions\\IERC721Metadata.sol": { 265 | "lastModificationDate": 1637760798327, 266 | "contentHash": "8aa69ca8424167555baaaa9f607801db", 267 | "sourceName": "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol", 268 | "solcConfig": { 269 | "version": "0.8.4", 270 | "settings": { 271 | "optimizer": { 272 | "enabled": true, 273 | "runs": 200 274 | }, 275 | "outputSelection": { 276 | "*": { 277 | "*": [ 278 | "abi", 279 | "evm.bytecode", 280 | "evm.deployedBytecode", 281 | "evm.methodIdentifiers", 282 | "metadata" 283 | ], 284 | "": [ 285 | "ast" 286 | ] 287 | } 288 | } 289 | } 290 | }, 291 | "imports": [ 292 | "../IERC721.sol" 293 | ], 294 | "versionPragmas": [ 295 | "^0.8.0" 296 | ], 297 | "artifacts": [ 298 | "IERC721Metadata" 299 | ] 300 | }, 301 | "G:\\Projects\\DEV-NFT\\node_modules\\@openzeppelin\\contracts\\utils\\Address.sol": { 302 | "lastModificationDate": 1637760793415, 303 | "contentHash": "c5f6c4e4df069c789e7d84b4c3011913", 304 | "sourceName": "@openzeppelin/contracts/utils/Address.sol", 305 | "solcConfig": { 306 | "version": "0.8.4", 307 | "settings": { 308 | "optimizer": { 309 | "enabled": true, 310 | "runs": 200 311 | }, 312 | "outputSelection": { 313 | "*": { 314 | "*": [ 315 | "abi", 316 | "evm.bytecode", 317 | "evm.deployedBytecode", 318 | "evm.methodIdentifiers", 319 | "metadata" 320 | ], 321 | "": [ 322 | "ast" 323 | ] 324 | } 325 | } 326 | } 327 | }, 328 | "imports": [], 329 | "versionPragmas": [ 330 | "^0.8.0" 331 | ], 332 | "artifacts": [ 333 | "Address" 334 | ] 335 | }, 336 | "G:\\Projects\\DEV-NFT\\node_modules\\@openzeppelin\\contracts\\utils\\Context.sol": { 337 | "lastModificationDate": 1637760793845, 338 | "contentHash": "851485d5b925529b1a2f34a0be077891", 339 | "sourceName": "@openzeppelin/contracts/utils/Context.sol", 340 | "solcConfig": { 341 | "version": "0.8.4", 342 | "settings": { 343 | "optimizer": { 344 | "enabled": true, 345 | "runs": 200 346 | }, 347 | "outputSelection": { 348 | "*": { 349 | "*": [ 350 | "abi", 351 | "evm.bytecode", 352 | "evm.deployedBytecode", 353 | "evm.methodIdentifiers", 354 | "metadata" 355 | ], 356 | "": [ 357 | "ast" 358 | ] 359 | } 360 | } 361 | } 362 | }, 363 | "imports": [], 364 | "versionPragmas": [ 365 | "^0.8.0" 366 | ], 367 | "artifacts": [ 368 | "Context" 369 | ] 370 | }, 371 | "G:\\Projects\\DEV-NFT\\node_modules\\@openzeppelin\\contracts\\utils\\Strings.sol": { 372 | "lastModificationDate": 1637760799015, 373 | "contentHash": "62142442bed149f965c5ed971fae4182", 374 | "sourceName": "@openzeppelin/contracts/utils/Strings.sol", 375 | "solcConfig": { 376 | "version": "0.8.4", 377 | "settings": { 378 | "optimizer": { 379 | "enabled": true, 380 | "runs": 200 381 | }, 382 | "outputSelection": { 383 | "*": { 384 | "*": [ 385 | "abi", 386 | "evm.bytecode", 387 | "evm.deployedBytecode", 388 | "evm.methodIdentifiers", 389 | "metadata" 390 | ], 391 | "": [ 392 | "ast" 393 | ] 394 | } 395 | } 396 | } 397 | }, 398 | "imports": [], 399 | "versionPragmas": [ 400 | "^0.8.0" 401 | ], 402 | "artifacts": [ 403 | "Strings" 404 | ] 405 | }, 406 | "G:\\Projects\\DEV-NFT\\node_modules\\@openzeppelin\\contracts\\utils\\introspection\\ERC165.sol": { 407 | "lastModificationDate": 1637760794394, 408 | "contentHash": "a9a5319dff9088c6ffe757ea1c2a6729", 409 | "sourceName": "@openzeppelin/contracts/utils/introspection/ERC165.sol", 410 | "solcConfig": { 411 | "version": "0.8.4", 412 | "settings": { 413 | "optimizer": { 414 | "enabled": true, 415 | "runs": 200 416 | }, 417 | "outputSelection": { 418 | "*": { 419 | "*": [ 420 | "abi", 421 | "evm.bytecode", 422 | "evm.deployedBytecode", 423 | "evm.methodIdentifiers", 424 | "metadata" 425 | ], 426 | "": [ 427 | "ast" 428 | ] 429 | } 430 | } 431 | } 432 | }, 433 | "imports": [ 434 | "./IERC165.sol" 435 | ], 436 | "versionPragmas": [ 437 | "^0.8.0" 438 | ], 439 | "artifacts": [ 440 | "ERC165" 441 | ] 442 | }, 443 | "G:\\Projects\\DEV-NFT\\node_modules\\@openzeppelin\\contracts\\utils\\introspection\\IERC165.sol": { 444 | "lastModificationDate": 1637760798127, 445 | "contentHash": "9a04322bb8f6b8f2767d8358d1d2537b", 446 | "sourceName": "@openzeppelin/contracts/utils/introspection/IERC165.sol", 447 | "solcConfig": { 448 | "version": "0.8.4", 449 | "settings": { 450 | "optimizer": { 451 | "enabled": true, 452 | "runs": 200 453 | }, 454 | "outputSelection": { 455 | "*": { 456 | "*": [ 457 | "abi", 458 | "evm.bytecode", 459 | "evm.deployedBytecode", 460 | "evm.methodIdentifiers", 461 | "metadata" 462 | ], 463 | "": [ 464 | "ast" 465 | ] 466 | } 467 | } 468 | } 469 | }, 470 | "imports": [], 471 | "versionPragmas": [ 472 | "^0.8.0" 473 | ], 474 | "artifacts": [ 475 | "IERC165" 476 | ] 477 | }, 478 | "G:\\Projects\\DEV-NFT\\contracts\\NFT.sol": { 479 | "lastModificationDate": 1638786663925, 480 | "contentHash": "cc1da4417bf6eb112274571bf4edf4f0", 481 | "sourceName": "contracts/NFT.sol", 482 | "solcConfig": { 483 | "version": "0.8.4", 484 | "settings": { 485 | "optimizer": { 486 | "enabled": true, 487 | "runs": 200 488 | }, 489 | "outputSelection": { 490 | "*": { 491 | "*": [ 492 | "abi", 493 | "evm.bytecode", 494 | "evm.deployedBytecode", 495 | "evm.methodIdentifiers", 496 | "metadata" 497 | ], 498 | "": [ 499 | "ast" 500 | ] 501 | } 502 | } 503 | } 504 | }, 505 | "imports": [ 506 | "@openzeppelin/contracts/utils/Counters.sol", 507 | "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", 508 | "@openzeppelin/contracts/token/ERC721/ERC721.sol", 509 | "hardhat/console.sol" 510 | ], 511 | "versionPragmas": [ 512 | "^0.8.3" 513 | ], 514 | "artifacts": [ 515 | "NFT" 516 | ] 517 | }, 518 | "G:\\Projects\\DEV-NFT\\node_modules\\@openzeppelin\\contracts\\token\\ERC721\\extensions\\ERC721URIStorage.sol": { 519 | "lastModificationDate": 1637760796472, 520 | "contentHash": "94da923c22e9773af388607307182c80", 521 | "sourceName": "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", 522 | "solcConfig": { 523 | "version": "0.8.4", 524 | "settings": { 525 | "optimizer": { 526 | "enabled": true, 527 | "runs": 200 528 | }, 529 | "outputSelection": { 530 | "*": { 531 | "*": [ 532 | "abi", 533 | "evm.bytecode", 534 | "evm.deployedBytecode", 535 | "evm.methodIdentifiers", 536 | "metadata" 537 | ], 538 | "": [ 539 | "ast" 540 | ] 541 | } 542 | } 543 | } 544 | }, 545 | "imports": [ 546 | "../ERC721.sol" 547 | ], 548 | "versionPragmas": [ 549 | "^0.8.0" 550 | ], 551 | "artifacts": [ 552 | "ERC721URIStorage" 553 | ] 554 | } 555 | } 556 | } 557 | -------------------------------------------------------------------------------- /components/MarketplaceList.js: -------------------------------------------------------------------------------- 1 | import { ethers } from 'ethers' 2 | import { useEffect, useState } from 'react' 3 | import axios from 'axios' 4 | import Web3Modal from "web3modal" 5 | import Image from "next/image"; 6 | import NFT from '../artifacts/contracts/NFT.sol/NFT.json' 7 | import Market from '../artifacts/contracts/Market.sol/NFTMarket.json' 8 | 9 | 10 | import { 11 | nftaddress, nftmarketaddress 12 | } from '../config' 13 | 14 | 15 | function MarketplaceList() { 16 | 17 | // Load the NFTs from mainnet : 18 | const [nfts, setNfts] = useState([]) 19 | const [loadingState, setLoadingState] = useState('not-loaded') 20 | 21 | let rpcEndpoint = "https://matic-mumbai.chainstacklabs.com" 22 | 23 | if (process.env.NEXT_PUBLIC_WORKSPACE_URL) { 24 | rpcEndpoint = process.env.NEXT_PUBLIC_WORKSPACE_URL 25 | } 26 | 27 | // Load Marketplace NFT List 28 | async function loadNFTs() { 29 | const provider = new ethers.providers.JsonRpcProvider(rpcEndpoint) 30 | const tokenContract = new ethers.Contract(nftaddress, NFT.abi, provider) 31 | const marketContract = new ethers.Contract(nftmarketaddress, Market.abi, provider) 32 | const data = await marketContract.fetchMarketItems() 33 | 34 | const items = await Promise.all(data.map(async i => { 35 | const tokenUri = await tokenContract.tokenURI(i.tokenId) 36 | const meta = await axios.get(tokenUri) 37 | let price = ethers.utils.formatUnits(i.price.toString(), 'ether') 38 | let item = { 39 | price, 40 | itemId: i.itemId.toNumber(), 41 | seller: i.seller, 42 | owner: i.owner, 43 | image: meta.data.image, 44 | name: meta.data.name, 45 | description: meta.data.description, 46 | } 47 | return item 48 | })) 49 | setNfts(items) 50 | setLoadingState('loaded') 51 | } 52 | 53 | // Buy NFT 54 | async function buyNft(nft) { 55 | const web3Modal = new Web3Modal() 56 | const connection = await web3Modal.connect() 57 | const provider = new ethers.providers.Web3Provider(connection) 58 | const signer = provider.getSigner() 59 | const contract = new ethers.Contract(nftmarketaddress, Market.abi, signer) 60 | 61 | const price = ethers.utils.parseUnits(nft.price.toString(), 'ether') 62 | const transaction = await contract.createMarketSale(nftaddress, nft.itemId, { 63 | value: price 64 | }) 65 | await transaction.wait() 66 | loadNFTs() 67 | } 68 | 69 | // Main 70 | useEffect(() => { 71 | loadNFTs() 72 | }, []); 73 | 74 | 75 | if (loadingState === 'loaded' && !nfts.length) return (

No items in marketplace

) 76 | return ( 77 | <> 78 |
79 |
80 |
81 | { 82 | nfts.map((nft, i) => ( 83 |
84 | {/* */} 85 | 86 | {/*temp card testing*/} 87 | {/**/} 88 | {/**/} 89 |
90 |
91 |
{nft.price} MATIC
92 |
93 | {/**/} 94 | 95 |
96 |
97 | {/**/} 98 |
99 |
{nft.name}
100 |

{nft.description}

101 |
102 | 103 | {/**/} 104 | {/* */} 105 | buyNft(nft)} 107 | className="hover:cursor-pointer font-bold inset-x-0 flex items-center justify-center px-4 py-2 mb-2 mx-2 text-sm rounded-md text-white bg-purple-800 hover:bg-purple-700 md:py-2 md:text-sm md:px-10" 108 | > 109 | Buy 110 | 111 |
112 |
113 |
114 |
115 | )) 116 | } 117 |
118 |
119 |
120 | 121 | 122 | ) 123 | } 124 | 125 | 126 | export default MarketplaceList; -------------------------------------------------------------------------------- /components/ReposList.js: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { ethers } from 'ethers' 3 | import { create as ipfsHttpClient } from 'ipfs-http-client' 4 | import { useRouter } from 'next/router' 5 | import Web3Modal from 'web3modal' 6 | import ReposModal from "./ReposModal"; 7 | import { Fragment, useState } from 'react' 8 | import { Dialog, Transition } from '@headlessui/react' 9 | import SvgPreview from './SvgPreview' 10 | 11 | import { 12 | nftaddress, nftmarketaddress 13 | } from '../config' 14 | 15 | import NFT from '../artifacts/contracts/NFT.sol/NFT.json' 16 | import Market from '../artifacts/contracts/Market.sol/NFTMarket.json' 17 | 18 | 19 | function ReposList({ reposList }) { 20 | 21 | const [fileUrl, setFileUrl] = useState(null) 22 | const [open, setOpen] = useState(false) 23 | const [priceInput, updatePriceInput] = useState({ price: '' }) 24 | const router = useRouter() 25 | 26 | const [sharedState, setSharedState] = useState({}); 27 | 28 | // Show the repos informations 29 | const [githubContent, setGithubContent] = useState({ 30 | price: '', 31 | name: '', 32 | repos_name: '', 33 | description: '' 34 | }) 35 | 36 | // Infura client 37 | const client = ipfsHttpClient('https://ipfs.infura.io:5001/api/v0') 38 | 39 | 40 | /** 41 | * Open the modal and set githubContent 42 | * @param {*} repos 43 | */ 44 | async function selectRepo(repos) { 45 | 46 | // Load the datas of the selected repos 47 | setGithubContent({ 48 | name: repos.full_name, 49 | repos_name: repos.owner.login, 50 | description: repos.description, 51 | price: '' 52 | }) 53 | 54 | // Open the modal with the svgPreview 55 | setOpen(true) 56 | } 57 | 58 | async function createMarket() { 59 | const { name, description, price } = githubContent 60 | 61 | if (!name || !description || !price || !fileUrl) return 62 | 63 | 64 | /* first, upload to IPFS */ 65 | const data = JSON.stringify({ 66 | name, description, image: fileUrl 67 | }) 68 | 69 | // CONTROL: 70 | // console.log(data) 71 | 72 | try { 73 | const added = await client.add(data) 74 | const url = `https://ipfs.infura.io/ipfs/${added.path}` 75 | 76 | /* after file is uploaded to IPFS, pass the URL to save it on Polygon */ 77 | // createSale(url) 78 | 79 | } catch (error) { 80 | console.log('Error uploading file: ', error) 81 | } 82 | } 83 | 84 | async function createSale(url) { 85 | const { name, description } = githubContent 86 | 87 | console.log("createSale =>", { 88 | url: url.sharedState, 89 | githubContent: githubContent 90 | }); 91 | 92 | // if (!name || !description || !price || !sharedState) return 93 | 94 | const data = JSON.stringify({ 95 | name, description, image: sharedState 96 | }) 97 | 98 | const added = await client.add(data) 99 | const urlIPFS = `https://ipfs.infura.io/ipfs/${added.path}` 100 | 101 | const web3Modal = new Web3Modal() 102 | const connection = await web3Modal.connect() 103 | const provider = new ethers.providers.Web3Provider(connection) 104 | const signer = provider.getSigner() 105 | 106 | /* next, create the item */ 107 | let contract = new ethers.Contract(nftaddress, NFT.abi, signer) 108 | let transaction = await contract.createToken(urlIPFS) 109 | let tx = await transaction.wait() 110 | let event = tx.events[0] 111 | let value = event.args[2] 112 | let tokenId = value.toNumber() 113 | 114 | // const price = ethers.utils.parseUnits(formInput.price, 'ether') 115 | console.log("[Price control] => ", priceInput.price) 116 | const price = ethers.utils.parseUnits(priceInput.price, 'ether') 117 | 118 | /* then list the item for sale on the marketplace */ 119 | contract = new ethers.Contract(nftmarketaddress, Market.abi, signer) 120 | let listingPrice = await contract.getListingPrice() 121 | listingPrice = listingPrice.toString() 122 | 123 | transaction = await contract.createMarketItem(nftaddress, tokenId, price, { value: listingPrice }) 124 | await transaction.wait() 125 | 126 | // Maybe we can redirect the user to a 'creation-ok' pages 127 | // or trigger an tailwind alert! 128 | // If transaction is successfull, we redirect the user to 129 | // the dashboard. 130 | router.push('/dashboard') 131 | } 132 | 133 | 134 | 135 | return ( 136 | <> 137 | {/* DIALOG MODAL : optimization -> Add it to component */} 138 | 139 | 140 |
141 | 150 | 151 | 152 | 153 | {/* This element is to trick the browser into centering the modal contents. */} 154 | 157 | 166 |
167 |
168 |
169 |
170 | 171 | {/* ==== SVG PREVIEW ==== */} 172 | 180 | {/* ==== SVG PREVIEW ==== */} 181 | 182 |
183 |
184 |
185 |
186 |
187 | 190 |
191 |
192 |
193 | updatePriceInput({ ...priceInput, price: e.target.value })} 201 | /> 202 |
203 | 204 | MATIC 205 | 206 |
207 |
208 |
209 | 216 | 223 |
224 |
225 |
226 |
227 |
228 |
229 | 230 | {/* REPOS LIST */} 231 |
232 |

Select your repos

233 |
234 | {reposList.map((repos, i) => ( 235 |
selectRepo(repos)} 237 | key={i} 238 | className="cursor-pointer relative rounded-lg border border-gray-300 bg-white px-6 py-5 shadow-sm flex items-center space-x-3 hover:border-gray-400 focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-purple-500" 239 | > 240 |
241 | 242 |
243 |
244 |
248 | 254 |
255 | ))} 256 |
257 |
258 | 259 | ) 260 | 261 | }; 262 | 263 | export default ReposList; -------------------------------------------------------------------------------- /components/ReposModal.js: -------------------------------------------------------------------------------- 1 | /* This example requires Tailwind CSS v2.0+ */ 2 | import { Fragment, useState } from 'react' 3 | import { Dialog, Transition } from '@headlessui/react' 4 | import { CheckIcon } from '@heroicons/react/outline' 5 | 6 | export default function ReposModal({ isOpen, username, reposname }) { 7 | const [open, setOpen] = useState(isOpen) 8 | 9 | return ( 10 | <> 11 | 12 | 13 |
14 | 23 | 24 | 25 | 26 | {/* This element is to trick the browser into centering the modal contents. */} 27 | 30 | 39 |
40 |
41 |
42 |
43 | {/* cou */} coucou 44 |
45 |
46 |
47 |
48 | 55 |
56 |
57 |
58 |
59 |
60 |
61 | 62 | ) 63 | } 64 | -------------------------------------------------------------------------------- /components/SvgPreview.js: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { Fragment, useState, useEffect } from 'react' 3 | import { create as ipfsHttpClient } from 'ipfs-http-client' 4 | 5 | function SvgPreview({ props, githubUsername, selectedRepos, description, setSharedState, sharedState }) { 6 | 7 | // Uncomment to debug : 8 | // console.log("svgCards username =>", githubUsername) 9 | // console.log("svgCards repos =>", selectedRepos) 10 | // console.log("svgCards description =>", description) 11 | // console.log("svgCards sharedState =>", sharedState) 12 | 13 | // infura gateway 14 | const client = ipfsHttpClient('https://ipfs.infura.io:5001/api/v0') 15 | 16 | /** 17 | * Get the SVG from the modal 18 | * @returns svgElement 19 | */ 20 | const getSvgPreview = () => { 21 | let svgElement = document.getElementById('svg_element'); 22 | 23 | if (svgElement) { 24 | return svgElement; 25 | } else { 26 | console.warning('svg_element not selectable'); 27 | } 28 | } 29 | 30 | 31 | /** 32 | * Create a blob object 33 | * @returns Blob object 34 | */ 35 | const createBlob = () => { 36 | let svgElement = getSvgPreview(); 37 | 38 | if (svgElement) { 39 | let clonedSvgElement = svgElement.cloneNode(true); 40 | let outerHTML = clonedSvgElement.outerHTML; 41 | let blob = new Blob([outerHTML], { 42 | type: 'image/svg+xml;charset=utf-8' 43 | }); 44 | 45 | // Uncomment to debug 46 | // console.log("Blob object =>", blob) 47 | 48 | if (blob) { 49 | return blob; 50 | } else { 51 | console.warning('no blob available') 52 | } 53 | } 54 | } 55 | 56 | /** 57 | * Create a blobURL 58 | * @param {*} blob 59 | * @returns blobURL 60 | */ 61 | function createBlobUrl(blob) { 62 | 63 | // Make blob url 64 | let URL = window.URL || window.webkitURL || window; 65 | let blobURL = URL.createObjectURL(blob); 66 | 67 | if (blobURL) { 68 | return blobURL 69 | } 70 | } 71 | 72 | /** 73 | * Upload a blob object 74 | * @param {*} blob 75 | */ 76 | async function uploadToIpfs(blob) { 77 | 78 | // We send a blob object instead of fileobject 79 | if (blob) { 80 | try { 81 | const added = await client.add( 82 | blob, 83 | { 84 | progress: (prog) => console.log(`received: ${prog}`) 85 | } 86 | ) 87 | 88 | const url = `https://ipfs.infura.io/ipfs/${added.path}` 89 | console.log("[IPFS URL] => ", url) 90 | 91 | // Share the state to the reposList component : 92 | setSharedState(url) 93 | 94 | } catch (error) { 95 | console.log('Error uploading file to ipfs: ', error) 96 | } 97 | } 98 | } 99 | 100 | 101 | useEffect(() => { 102 | 103 | // sharedState = DOMelement? 104 | 105 | // Load the svg preview into ipfs at the openning 106 | // Maybe we should do it after the creation. 107 | var blob = createBlob(); 108 | if (blob) { 109 | uploadToIpfs(blob); 110 | } 111 | 112 | }, []); 113 | 114 | 115 | const time = Date.now(); 116 | return ( 117 | <> 118 | 126 | 148 | 149 | 169 | 176 | {githubUsername} 177 | 178 | 179 | 180 | 181 | 201 | 202 | {description} 203 | 204 | 205 | 206 | 207 | 224 | 241 | 242 | 243 | 263 | 264 | {time} 265 | 266 | 267 | 268 | 269 | 270 | ) 271 | 272 | }; 273 | 274 | export default SvgPreview; -------------------------------------------------------------------------------- /components/landing/faq.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useEffect, useState } from 'react' 3 | 4 | 5 | function Faq() { 6 | 7 | // Faq section data 8 | const faqs = [ 9 | { 10 | question: 'What are NFTs?', 11 | answer: 12 | 'NFTs (non-fungible tokens) are blockchain-based records that uniquely represent pieces of digital media (say, a digital art piece, a tweet, or a repository 👀). In more practical terms, an NFT can be seen as a digital autograph created by the author of the piece of media the NFT represents. By signing it, the author is guaranteeing its authenticity. ', 13 | }, 14 | { 15 | question: 'What\'s DevNFT?', 16 | answer: 17 | 'The DevNFT app enable users to create NFTs of a repository via GitHub OAuth and cryptographically sign the repos with their MetaMask wallet. Then, the app creates ("mints") an NFT representation of their Repo on the Polygon/Matic blockchain.⛓️', 18 | }, 19 | { 20 | question: 'Why would I want to buy a DevNFT?', 21 | answer: 22 | 'Who knows a project becomes next linux kernel or CURL and you like to be a part of it, Owning a DevNFT you can.\nAnd by buying a DevNFT you can support the project in which you truly believe in.✅️ ', 23 | }, 24 | { 25 | question: 'How to buy a DevNFT?', 26 | answer: 27 | 'Connect your wallet, Sign in with your GitHub account then Select the Repository chose a price & Mint on Polygon. See super easy!😍️', 28 | }, 29 | { 30 | question: 'If I buy DevNFT, will I become the owner of Repo?', 31 | answer: 32 | 'DevNFT is a type of autograph by the developer or repo owner which is sold to make you feel possession or part of the project. Generally, this does not transfer ownership. But, If a developer wants, they can sell their work through the DevNFT. 🎨️', 33 | }, 34 | { 35 | question: 'What if a person forks a repo and creates an NFT?', 36 | answer: 37 | 'Malpractices of copying the others work is years old, but with DevNFT you get all repo information. A person can always visit the repo and verify', 38 | }, 39 | // More questions... 40 | ] 41 | 42 | 43 | return ( 44 | <> 45 | {/* FAQ */} 46 |
47 |
48 |
49 |
50 |

Frequently asked questions

51 |

52 | Can’t find the answer you’re looking for? Open an issue to our{' '} 53 | 54 | GitHub 55 | {' '} 56 | repository. 57 |

58 |
59 |
60 |
61 | {faqs.map((faq) => ( 62 |
63 |
{faq.question}
64 |
{faq.answer}
65 |
66 | ))} 67 |
68 |
69 |
70 |
71 |
72 | 73 | 74 | ) 75 | } 76 | 77 | 78 | export default Faq; 79 | -------------------------------------------------------------------------------- /components/landing/features.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useEffect, useState } from 'react' 3 | import { 4 | BookmarkAltIcon, 5 | CalendarIcon, 6 | ChartBarIcon, 7 | CursorClickIcon, 8 | CloudUploadIcon, 9 | MenuIcon, 10 | PhoneIcon, 11 | PlayIcon, 12 | LockClosedIcon, 13 | CogIcon, 14 | ServerIcon, 15 | RefreshIcon, 16 | ShieldCheckIcon, 17 | SupportIcon, 18 | ViewGridIcon, 19 | XIcon, 20 | LogoutIcon, 21 | FireIcon 22 | } from '@heroicons/react/outline'; 23 | 24 | 25 | 26 | function Features() { 27 | 28 | // Features section data 29 | const features = [ 30 | { name: 'Connect Wallet', description: 'We have Metamask! Enable metamask after signing up to be able to mint your repos', icon: ShieldCheckIcon }, 31 | { name: 'Connect GitHub', description: 'Login with your GitHub account to retrieve your respositories', icon: LockClosedIcon }, 32 | { name: 'Select GitHub repository', description: 'Select your favorite GitHub repository, and create an NFT ✨', icon: FireIcon }, 33 | { name: 'Mint it!', description: 'Turn your GitHub repository into a piece of history and sell it!', icon: ShieldCheckIcon }, 34 | // More features... 35 | ] 36 | 37 | return ( 38 | <> 39 | {/* Features */} 40 |
41 |
42 |

DEV-NFT

43 |

44 | Create and sell your GitHub Repos as NFTs 45 |

46 |

47 | Browse through your repositories and mint them as NFT's to sell them to the people who believe in your project! Make your repository a piece of art that will be passed on from one person to another for generations to come! 48 |

49 |
50 |
51 | {features.map((feature) => ( 52 |
53 |
54 |
55 |
56 | 57 | 59 |
60 |

{feature.name}

61 |

62 | {feature.description} 63 |

64 |
65 |
66 |
67 | ))} 68 |
69 |
70 |
71 |
72 | 73 | 74 | ) 75 | } 76 | 77 | 78 | export default Features; -------------------------------------------------------------------------------- /components/landing/footer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ethers } from 'ethers' 3 | import { useEffect, useState } from 'react' 4 | import axios from 'axios' 5 | import Web3Modal from "web3modal" 6 | 7 | import NFT from '/artifacts/contracts/NFT.sol/NFT.json' 8 | import Market from '/artifacts/contracts/Market.sol/NFTMarket.json' 9 | 10 | 11 | import { 12 | nftaddress, nftmarketaddress 13 | } from '/config' 14 | 15 | 16 | 17 | 18 | function Footer({ footerText }) { 19 | 20 | // Footer links 21 | const navigation = [ 22 | { 23 | name: 'Instagram', 24 | href: 'https://www.instagram.com/WebXDAO/', 25 | icon: (props) => ( 26 | 27 | 32 | 33 | ), 34 | }, 35 | { 36 | name: 'GitHub', 37 | href: 'https://github.com/WebXDAO/', 38 | icon: (props) => ( 39 | 40 | 45 | 46 | ), 47 | } 48 | ] 49 | 50 | return ( 51 | <> 52 | {/* Footer */} 53 | 68 | 69 | 70 | ) 71 | } 72 | 73 | 74 | export default Footer; 75 | -------------------------------------------------------------------------------- /components/landing/hero.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useEffect, useState } from 'react' 3 | import Link from 'next/link'; 4 | import { useRouter } from "next/router"; 5 | let Web3 = require('web3'); 6 | 7 | 8 | function Hero({ heroButton }) { 9 | 10 | const router = useRouter(); 11 | 12 | 13 | function connectToMetamask() { 14 | window.ethereum ? 15 | ethereum.request({ method: "eth_requestAccounts" }).then((accounts) => { 16 | setAddress(accounts[0]) 17 | 18 | let w3 = new Web3(ethereum) 19 | setWeb3(w3) 20 | 21 | // console.log("Account", accounts) 22 | // console.log("Web3", web3) 23 | // console.log(address) 24 | 25 | setHeroButton("Marketplace") 26 | router.push('/dashboard'); 27 | 28 | 29 | }).catch((err) => console.log(err)) 30 | : console.log("Please install MetaMask") 31 | } 32 | 33 | 34 | 35 | return ( 36 | <> 37 |
38 |
39 |

40 | The NFT Marketplace,{' '} 41 | for Open Source Repositories and Contributors 42 |

43 |

44 | Mint your own GitHub repositories as DEV-NFT's, and support the projects you truly believe in ! 45 |

46 |
47 |
48 | 49 | 54 | { heroButton } 55 | 56 | 57 |
58 |
59 |
60 |
61 | 62 |
63 | 68 |
69 | 70 | 71 | ) 72 | } 73 | 74 | 75 | export default Hero; 76 | -------------------------------------------------------------------------------- /components/landing/stoken.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useEffect, useState } from 'react' 3 | 4 | 5 | function SToken() { 6 | 7 | // Faq section data 8 | const faqs = [ 9 | { 10 | question: 'Question 1', 11 | answer: 12 | 'You boil the hell out of it. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas cupiditate laboriosam fugiat.', 13 | }, 14 | { 15 | question: 'Question 2', 16 | answer: 17 | 'You boil the hell out of it. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas cupiditate laboriosam fugiat.', 18 | }, 19 | // More questions... 20 | ] 21 | 22 | 23 | return ( 24 | <> 25 | {/* S-TOKEN */} 26 |
27 |
28 |
29 |

30 | About Us 31 |

32 |

33 | We are a bunch of 6 people 34 | who met on the internet a few days back and became part of a community. 35 | We all are passionate about opensource. 36 | Thus, created DevNFT to incentivize the opensource. 37 |

38 |
39 |
40 |
41 | 42 | 43 | ) 44 | } 45 | 46 | 47 | export default SToken; -------------------------------------------------------------------------------- /components/nav/dashboard-navbar.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react' 2 | import { 3 | getSession, 4 | signIn, 5 | signOut, 6 | useSession 7 | } from 'next-auth/client'; 8 | import Link from 'next/link'; 9 | import { BellIcon, MenuIcon, XIcon, LogoutIcon } from '@heroicons/react/outline' 10 | import { Disclosure, Menu, Transition } from '@headlessui/react' 11 | let Web3 = require('web3'); 12 | import { withRouter } from 'next/router' 13 | 14 | 15 | function Navbar({ router, headerName }) { 16 | 17 | const navigation = [ 18 | { name: 'Home', href: '/dashboard' }, 19 | { name: 'Generate and Sell', href: '/dashboard/create-nft' }, 20 | { name: 'My NFTs', href: '/dashboard/my-nfts' }, 21 | { name: 'My Creations', href: '/dashboard/my-creations' } 22 | ] 23 | const userNavigation = [ 24 | { name: 'Sign out', href: '#' }, 25 | ] 26 | 27 | const initSession = useSession(); 28 | const session = initSession[0]; 29 | 30 | function classNames(...classes) { 31 | return classes.filter(Boolean).join(' ') 32 | } 33 | 34 | const [address, setAddress] = useState([]) 35 | const [web3, setWeb3] = useState([]) 36 | 37 | function connectToMetamask() { 38 | window.ethereum ? 39 | ethereum.request({ method: "eth_requestAccounts" }).then((accounts) => { 40 | setAddress(accounts[0]) 41 | 42 | let w3 = new Web3(ethereum) 43 | setWeb3(w3) 44 | 45 | // console.log("Account", accounts) 46 | // console.log("Web3", web3) 47 | // console.log(address) 48 | 49 | setHeroButton("Marketplace") 50 | 51 | }).catch((err) => console.log(err)) 52 | : console.log("Please install MetaMask") 53 | } 54 | 55 | useEffect(() => { 56 | const checkConnection = async () => { 57 | 58 | // Check if browser is running Metamask 59 | let web3; 60 | if (window.ethereum) { 61 | web3 = new Web3(window.ethereum); 62 | } else if (window.web3) { 63 | web3 = new Web3(window.web3.currentProvider); 64 | }; 65 | 66 | if (web3) { 67 | // Check if User is already connected by retrieving the accounts 68 | web3.eth.getAccounts() 69 | .then(async (addr) => { 70 | 71 | // Set User account into state 72 | setAddress(addr); 73 | 74 | if (addr.length > 0) { 75 | // Code here 76 | console.log("Current metamask wallet: ", addr) 77 | } 78 | }); 79 | } 80 | 81 | }; 82 | 83 | checkConnection(); 84 | }, []) 85 | 86 | 87 | return ( 88 | <> 89 | 90 | {({ open }) => ( 91 | <> 92 |
93 |
94 |
95 |
96 | 97 | Workflow 102 | 103 |
104 |
105 |
106 | {navigation.map((item) => ( 107 | 111 | 120 | {item.name} 121 | 122 | 123 | ))} 124 |
125 |
126 |
127 |
128 |
129 | 130 | {/* Profile dropdown */} 131 | 132 | 152 | 153 | 154 | 155 | {/* Logout button */} 156 | {session && <> 157 | 164 | } 165 |
166 |
167 |
168 | {/* Mobile menu button */} 169 | 170 | Open main menu 171 | {open ? ( 172 | 177 |
178 |
179 |
180 | 181 | {/* Mobile menu */} 182 | 183 |
184 | {navigation.map((item) => ( 185 | 186 | 198 | {item.name} 199 | 200 | ))} 201 |
202 |
203 | {session && <> 204 |
205 | 206 |
{session.name}
207 |
208 | } 209 | {!session && <> 210 | signIn()} 212 | href="#" 213 | className="flex items-center justify-center px-4 py-2 text-xs rounded-md text-white bg-purple-800 hover:bg-purple-700 md:py-2 md:text-sm md:px-10" 214 | > 215 | Login to Github 216 | 217 | } 218 | {/* Logout button */} 219 | {session && <> 220 | 227 | } 228 |
229 |
230 | 231 | )} 232 |
233 | 234 |
235 |
236 |

{headerName}

237 | {address.length > 0 && <> 238 | 239 | Metamask wallet: {address} 240 | 241 | } 242 | {!address.length > 0 && <> 243 | 248 | Connect wallet 249 | 250 | } 251 |
252 |
253 | 254 | ) 255 | } 256 | 257 | export default withRouter(Navbar); -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | // deployed contract addresses 2 | export const nftmarketaddress = "0x175b59ABE0cFF79120e73987185D65CEEF1Bed77" 3 | export const nftaddress = "0xf6779aa11Addcc1A0EFC38f23D5b45F7c205Cb34" 4 | -------------------------------------------------------------------------------- /contracts/Market.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | pragma solidity ^0.8.3; 3 | 4 | import "@openzeppelin/contracts/utils/Counters.sol"; 5 | import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; 6 | import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; 7 | 8 | import "hardhat/console.sol"; 9 | 10 | contract NFTMarket is ReentrancyGuard { 11 | using Counters for Counters.Counter; 12 | Counters.Counter private _itemIds; 13 | Counters.Counter private _itemsSold; 14 | 15 | address payable owner; 16 | uint256 listingPrice = 0.025 ether; 17 | 18 | constructor() { 19 | owner = payable(msg.sender); 20 | } 21 | 22 | struct MarketItem { 23 | uint itemId; 24 | address nftContract; 25 | uint256 tokenId; 26 | address payable seller; 27 | address payable owner; 28 | uint256 price; 29 | bool sold; 30 | } 31 | 32 | mapping(uint256 => MarketItem) private idToMarketItem; 33 | 34 | event MarketItemCreated ( 35 | uint indexed itemId, 36 | address indexed nftContract, 37 | uint256 indexed tokenId, 38 | address seller, 39 | address owner, 40 | uint256 price, 41 | bool sold 42 | ); 43 | 44 | /* Returns the listing price of the contract */ 45 | function getListingPrice() public view returns (uint256) { 46 | return listingPrice; 47 | } 48 | 49 | /* Places an item for sale on the marketplace */ 50 | function createMarketItem( 51 | address nftContract, 52 | uint256 tokenId, 53 | uint256 price 54 | ) public payable nonReentrant { 55 | require(price > 0, "Price must be at least 1 wei"); 56 | require(msg.value == listingPrice, "Price must be equal to listing price"); 57 | 58 | _itemIds.increment(); 59 | uint256 itemId = _itemIds.current(); 60 | 61 | idToMarketItem[itemId] = MarketItem( 62 | itemId, 63 | nftContract, 64 | tokenId, 65 | payable(msg.sender), 66 | payable(address(0)), 67 | price, 68 | false 69 | ); 70 | 71 | IERC721(nftContract).transferFrom(msg.sender, address(this), tokenId); 72 | 73 | emit MarketItemCreated( 74 | itemId, 75 | nftContract, 76 | tokenId, 77 | msg.sender, 78 | address(0), 79 | price, 80 | false 81 | ); 82 | payable(owner).transfer(listingPrice); 83 | 84 | } 85 | 86 | /* Creates the sale of a marketplace item */ 87 | /* Transfers ownership of the item, as well as funds between parties */ 88 | function createMarketSale( 89 | address nftContract, 90 | uint256 itemId 91 | ) public payable nonReentrant { 92 | uint price = idToMarketItem[itemId].price; 93 | uint tokenId = idToMarketItem[itemId].tokenId; 94 | require(msg.value == price, "Please submit the asking price in order to complete the purchase"); 95 | 96 | idToMarketItem[itemId].seller.transfer(msg.value); 97 | IERC721(nftContract).transferFrom(address(this), msg.sender, tokenId); 98 | idToMarketItem[itemId].owner = payable(msg.sender); 99 | idToMarketItem[itemId].sold = true; 100 | _itemsSold.increment(); 101 | 102 | } 103 | 104 | /* Returns all unsold market items */ 105 | function fetchMarketItems() public view returns (MarketItem[] memory) { 106 | uint itemCount = _itemIds.current(); 107 | uint unsoldItemCount = _itemIds.current() - _itemsSold.current(); 108 | uint currentIndex = 0; 109 | 110 | MarketItem[] memory items = new MarketItem[](unsoldItemCount); 111 | for (uint i = 0; i < itemCount; i++) { 112 | if (idToMarketItem[i + 1].owner == address(0)) { 113 | uint currentId = i + 1; 114 | MarketItem memory currentItem = idToMarketItem[currentId]; 115 | items[currentIndex] = currentItem; 116 | currentIndex += 1; 117 | } 118 | } 119 | return items; 120 | } 121 | 122 | /* Returns onlyl items that a user has purchased */ 123 | function fetchMyNFTs() public view returns (MarketItem[] memory) { 124 | uint totalItemCount = _itemIds.current(); 125 | uint itemCount = 0; 126 | uint currentIndex = 0; 127 | 128 | for (uint i = 0; i < totalItemCount; i++) { 129 | if (idToMarketItem[i + 1].owner == msg.sender) { 130 | itemCount += 1; 131 | } 132 | } 133 | 134 | MarketItem[] memory items = new MarketItem[](itemCount); 135 | for (uint i = 0; i < totalItemCount; i++) { 136 | if (idToMarketItem[i + 1].owner == msg.sender) { 137 | uint currentId = i + 1; 138 | MarketItem memory currentItem = idToMarketItem[currentId]; 139 | items[currentIndex] = currentItem; 140 | currentIndex += 1; 141 | } 142 | } 143 | return items; 144 | } 145 | 146 | /* Returns only items a user has created */ 147 | function fetchItemsCreated() public view returns (MarketItem[] memory) { 148 | uint totalItemCount = _itemIds.current(); 149 | uint itemCount = 0; 150 | uint currentIndex = 0; 151 | 152 | for (uint i = 0; i < totalItemCount; i++) { 153 | if (idToMarketItem[i + 1].seller == msg.sender) { 154 | itemCount += 1; 155 | } 156 | } 157 | 158 | MarketItem[] memory items = new MarketItem[](itemCount); 159 | for (uint i = 0; i < totalItemCount; i++) { 160 | if (idToMarketItem[i + 1].seller == msg.sender) { 161 | uint currentId = i + 1; 162 | MarketItem memory currentItem = idToMarketItem[currentId]; 163 | items[currentIndex] = currentItem; 164 | currentIndex += 1; 165 | } 166 | } 167 | return items; 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /contracts/NFT.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | pragma solidity ^0.8.3; 3 | 4 | import "@openzeppelin/contracts/utils/Counters.sol"; 5 | import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; 6 | import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; 7 | 8 | import "hardhat/console.sol"; 9 | 10 | contract NFT is ERC721URIStorage { 11 | using Counters for Counters.Counter; 12 | Counters.Counter private _tokenIds; 13 | address contractAddress; 14 | 15 | constructor(address marketplaceAddress) ERC721("Metaverse", "METT") { 16 | contractAddress = marketplaceAddress; 17 | } 18 | 19 | function createToken(string memory tokenURI) public returns (uint) { 20 | _tokenIds.increment(); 21 | uint256 newItemId = _tokenIds.current(); 22 | 23 | _mint(msg.sender, newItemId); 24 | _setTokenURI(newItemId, tokenURI); 25 | setApprovalForAll(contractAddress, true); 26 | return newItemId; 27 | } 28 | } -------------------------------------------------------------------------------- /hardhat.config.js: -------------------------------------------------------------------------------- 1 | require("@nomiclabs/hardhat-waffle"); 2 | const fs = require('fs'); 3 | const privateKey = fs.readFileSync(".secret").toString().trim() || "01234567890123456789"; 4 | /* const infuraId = fs.readFileSync(".infuraid").toString().trim() || ""; */ 5 | 6 | module.exports = { 7 | defaultNetwork: "hardhat", 8 | networks: { 9 | hardhat: { 10 | chainId: 1337 11 | }, 12 | 13 | mumbai : { 14 | url : "https://matic-mumbai.chainstacklabs.com", 15 | accounts: [privateKey] 16 | } 17 | /* matic: { 18 | Infura 19 | url: `https://polygon-mainnet.infura.io/v3/${infuraId}`, 20 | url: "https://rpc-mainnet.maticvigil.com", 21 | accounts: [privateKey] 22 | } */ 23 | 24 | }, 25 | solidity: { 26 | version: "0.8.4", 27 | settings: { 28 | optimizer: { 29 | enabled: true, 30 | runs: 200 31 | } 32 | } 33 | } 34 | }; 35 | 36 | -------------------------------------------------------------------------------- /layout/Layout.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../components/nav/dashboard-navbar' 2 | 3 | 4 | function Layout({ children, headerName, metamaskAddress, session }) { 5 | 6 | return ( 7 | <> 8 | 12 | 13 |
{ children }
14 | 15 | {/* footer? */} 16 | 17 | ) 18 | 19 | } 20 | 21 | export default Layout; -------------------------------------------------------------------------------- /mkubdev-pr.md: -------------------------------------------------------------------------------- 1 | # DEV-NFT Project initialization and configuration 2 | 3 | ## Init the nextjs application with tailwind 4 | 5 | * We use `npx create-next-app -e with-tailwindcss` to generate the nextjs app with the tailwind library configured. 6 | 7 | > This command add postcss and autoprefixer packages. 8 | 9 | ## Add next-auth library 10 | 11 | * We use `npm i next-auth` to add the library to the application. 12 | 13 | ### Add API route 14 | 15 | To add NextAuth.js to a project create a file called `[...nextauth].js` in `pages/api/auth`. This contains the dynamic route handler for NextAuth.js which will also contain all of your global NextAuth.js configuration. 16 | 17 | ```js 18 | import NextAuth from "next-auth" 19 | import GithubProvider from "next-auth/providers/github" 20 | 21 | export default NextAuth({ 22 | // Configure one or more authentication providers 23 | providers: [ 24 | GithubProvider({ 25 | clientId: process.env.GITHUB_ID, 26 | clientSecret: process.env.GITHUB_SECRET, 27 | }), 28 | // ...add more providers here 29 | ], 30 | }) 31 | ``` 32 | All requests to `/api/auth/*` (`signIn`, callback, `signOut`, etc.) will automatically be handled by NextAuth.js. 33 | 34 | ### Configure session state 35 | 36 | To be able to use `useSession` first you'll need to expose the session context, ``, at the top level of our application: 37 | 38 | ```js 39 | // pages/_app.js 40 | import { Provider } from "next-auth/client" 41 | 42 | 43 | function MyApp({ Component, pageProps }) { 44 | return ( 45 | 46 | 47 | 48 | ) 49 | } 50 | 51 | export default MyApp 52 | ``` 53 | 54 | Instances of useSession will then have access to the session data and status. The `` also takes care of keeping the session updated and synced between browser tabs and windows. 55 | 56 | ## Add Web3 packages... 57 | 58 | > @Todo: add link to lib below 59 | 60 | We need somes libraries : 61 | - ethers 62 | - hardhat 63 | - @nomiclabs/hardhat-waffle 64 | - ethereum-waffle 65 | - chai 66 | - @nomiclabs/hardhat-ethers 67 | - web3modal 68 | - @openzeppelin/contracts 69 | - ipfs-http-client 70 | - axios 71 | 72 | We use `npm add ethers hardhat @nomiclabs/hardhat-waffle ethereum-waffle @nomiclabs/hardhat-ethers web3modal @openzeppelin/contracts ipfs-http-client axios` to install them. -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | publish = ".next" 3 | 4 | [[plugins]] 5 | package = "@netlify/plugin-nextjs" 6 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | images: { 3 | domains: ['ipfs.infura.io'] 4 | }, 5 | generateBuildId: () => 'build-id', 6 | } 7 | 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "next dev", 5 | "build": "next build", 6 | "start": "next start" 7 | }, 8 | "dependencies": { 9 | "@headlessui/react": "^1.4.2", 10 | "@heroicons/react": "^1.0.5", 11 | "@nomiclabs/hardhat-ethers": "^2.0.2", 12 | "@nomiclabs/hardhat-waffle": "^2.0.1", 13 | "@openzeppelin/contracts": "^4.3.3", 14 | "@tailwindcss/forms": "^0.5.0", 15 | "axios": "^0.27.2", 16 | "ethereum-waffle": "^3.4.0", 17 | "ethers": "^5.5.1", 18 | "hardhat": "^2.6.8", 19 | "ipfs-http-client": "^57.0.3", 20 | "next": "latest", 21 | "next-auth": "^4.3.3", 22 | "nft.storage": "^6.0.0", 23 | "react": "^17.0.2", 24 | "react-dom": "^17.0.2", 25 | "web3": "^1.6.1", 26 | "web3modal": "^1.9.4" 27 | }, 28 | "devDependencies": { 29 | "@netlify/plugin-nextjs": "^4.0.0-beta.11", 30 | "@next/eslint-plugin-next": "^12.0.4", 31 | "autoprefixer": "^10.2.6", 32 | "eslint": "^7.32.0", 33 | "eslint-config-standard": "^16.0.3", 34 | "postcss": "^8.3.5", 35 | "tailwindcss": "^3.0.23" 36 | }, 37 | "version": "0.2.4" 38 | } -------------------------------------------------------------------------------- /pages/_app.js: -------------------------------------------------------------------------------- 1 | import 'tailwindcss/tailwind.css' 2 | import '../styles/globals.css' 3 | import { Provider, useSession, getSession, signOut } from 'next-auth/client' 4 | import { SessionProvider } from 'next-auth/client' 5 | 6 | 7 | function MyApp({ Component, pageProps }) { 8 | 9 | // Get next-auth session 10 | const session = pageProps.session; 11 | 12 | return ( 13 | <> 14 | 15 | 16 | 17 | 18 | ) 19 | } 20 | 21 | export default MyApp 22 | -------------------------------------------------------------------------------- /pages/api/auth/[...nextauth].js: -------------------------------------------------------------------------------- 1 | import { getJsonWalletAddress } from '@ethersproject/json-wallets' 2 | import NextAuth from 'next-auth' 3 | import { session, signIn } from 'next-auth/client' 4 | import Providers from 'next-auth/providers' 5 | 6 | const options = { 7 | 8 | // Next-Auth: Github OAuth connexion 9 | providers: [ 10 | Providers.GitHub({ 11 | clientId: process.env.GITHUB_CLIENT_ID, 12 | clientSecret: process.env.GITHUB_CLIENT_SECRET, 13 | profile(profile) { 14 | // All data come from github, need to find a way to surcharge the session object 15 | // from the callbacks bellow : 16 | // console.log("profile", profile) 17 | return { 18 | id: profile.id, 19 | name: profile.name || profile.login, 20 | email: profile.email, 21 | image: profile.avatar_url, 22 | login: profile.login, 23 | company: profile.company, 24 | repos_count: profile.public_repos, 25 | followers: profile.followers 26 | } 27 | } 28 | })], 29 | 30 | // Optional SQL or MongoDB database to persist users 31 | // database: process.env.DATABASE_URL, 32 | 33 | callbacks: { 34 | jwt: async ( token, user ) => { 35 | // "user" parameter is the object received from "authorize" 36 | // "token" is being send below to "session" callback... 37 | // ...so we set "profile" param of "token" to object from "authorize"... 38 | // ...and return it... 39 | user && (token.profile = user) 40 | return token 41 | }, 42 | session: async ( session, token ) => { 43 | // "session" is current session object 44 | // below we set "user" param of "session" to value received from "jwt" callback 45 | session.user = token.user 46 | return token 47 | }, 48 | 49 | // redirect: async ( url, baseUrl ) => { 50 | // return '/creator-dashboard' 51 | // }, 52 | } 53 | } 54 | 55 | export default (req, res) => NextAuth(req, res, options); 56 | -------------------------------------------------------------------------------- /pages/api/hello.js: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | 3 | export default function helloAPI(req, res) { 4 | res.status(200).json({ name: 'John Doe' }) 5 | } 6 | -------------------------------------------------------------------------------- /pages/dashboard/create-nft.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from 'react' 2 | import { ethers } from 'ethers' 3 | import { create as ipfsHttpClient } from 'ipfs-http-client' 4 | import { useRouter } from 'next/router' 5 | import Web3Modal from 'web3modal' 6 | import { 7 | getSession, 8 | signIn, 9 | signOut, 10 | } from 'next-auth/client'; 11 | import { 12 | LoginIcon 13 | } from '@heroicons/react/outline'; 14 | import ReposList from '../../components/ReposList' 15 | 16 | import Layout from '../../layout/Layout' 17 | 18 | export default function CreateItem({ session, reposList, login }) { 19 | 20 | return ( 21 | 22 |
23 | 24 | {/* If user is connected to github, it display user's repos list */} 25 | {session && 26 | <> 27 | 28 | 29 | } 30 | 31 | {/* If user isn't connected to github, asking to connect */} 32 | {!session && 33 | <> 34 |
35 | 44 |
45 | 46 | } 47 |
48 |
49 | ) 50 | } 51 | 52 | // Get the github session at the runtime of the app 53 | export const getServerSideProps = async (context) => { 54 | 55 | // Get github login 56 | const session = await getSession(context) 57 | if (session) { 58 | var login = session.profile.login; 59 | 60 | if (login) { 61 | const res = await fetch('https://api.github.com/users/' + login + '/repos'); 62 | const reposList = await res.json(); 63 | 64 | // uncomment to see the api response 65 | // console.log(reposList) 66 | 67 | return { 68 | props: { 69 | session, 70 | reposList, 71 | login 72 | }, 73 | }; 74 | } 75 | } 76 | 77 | 78 | return { 79 | props: { 80 | session 81 | }, 82 | }; 83 | }; -------------------------------------------------------------------------------- /pages/dashboard/index.js: -------------------------------------------------------------------------------- 1 | import { ethers } from 'ethers' 2 | import axios from 'axios' 3 | import Web3Modal from "web3modal" 4 | import { useEffect, useState } from 'react' 5 | import { 6 | getSession, 7 | signIn, 8 | signOut, 9 | useSession 10 | } from 'next-auth/client'; 11 | 12 | import { 13 | nftaddress, nftmarketaddress 14 | } from '../../config' 15 | 16 | import NFT from '../../artifacts/contracts/NFT.sol/NFT.json' 17 | import Market from '../../artifacts/contracts/Market.sol/NFTMarket.json' 18 | import Layout from '../../layout/Layout' 19 | import MarketplaceList from '../../components/MarketplaceList' 20 | 21 | let rpcEndpoint = "https://matic-mumbai.chainstacklabs.com" 22 | 23 | if (process.env.NEXT_PUBLIC_WORKSPACE_URL) { 24 | rpcEndpoint = process.env.NEXT_PUBLIC_WORKSPACE_URL 25 | } 26 | 27 | export default function Home({ session }) { 28 | const [nfts, setNfts] = useState([]) 29 | const [loadingState, setLoadingState] = useState('not-loaded') 30 | useEffect(() => { 31 | loadNFTs() 32 | }, []) 33 | async function loadNFTs() { 34 | const provider = new ethers.providers.JsonRpcProvider(rpcEndpoint) 35 | const tokenContract = new ethers.Contract(nftaddress, NFT.abi, provider) 36 | const marketContract = new ethers.Contract(nftmarketaddress, Market.abi, provider) 37 | const data = await marketContract.fetchMarketItems() 38 | 39 | const items = await Promise.all(data.map(async i => { 40 | const tokenUri = await tokenContract.tokenURI(i.tokenId) 41 | const meta = await axios.get(tokenUri) 42 | let price = ethers.utils.formatUnits(i.price.toString(), 'ether') 43 | let item = { 44 | price, 45 | itemId: i.itemId.toNumber(), 46 | seller: i.seller, 47 | owner: i.owner, 48 | image: meta.data.image, 49 | name: meta.data.name, 50 | description: meta.data.description, 51 | } 52 | return item 53 | })) 54 | setNfts(items) 55 | setLoadingState('loaded') 56 | } 57 | 58 | if (loadingState === 'loaded' && !nfts.length) return (

No items in marketplace

) 59 | return ( 60 | 61 | 62 | 63 | ) 64 | } 65 | 66 | 67 | // Get the github session 68 | export const getServerSideProps = async (context) => { 69 | 70 | // Get github login 71 | const session = await getSession(context) 72 | if (session) { 73 | return { 74 | props: { 75 | session, 76 | }, 77 | }; 78 | } 79 | 80 | return { 81 | props: { 82 | session 83 | } 84 | } 85 | 86 | }; 87 | -------------------------------------------------------------------------------- /pages/dashboard/my-creations.js: -------------------------------------------------------------------------------- 1 | import { ethers } from 'ethers' 2 | import { useEffect, useState } from 'react' 3 | import axios from 'axios' 4 | import Web3Modal from "web3modal" 5 | import { 6 | getSession, 7 | } from 'next-auth/client'; 8 | 9 | import { 10 | nftmarketaddress, nftaddress 11 | } from '../../config' 12 | 13 | import Market from '../../artifacts/contracts/Market.sol/NFTMarket.json' 14 | import NFT from '../../artifacts/contracts/NFT.sol/NFT.json' 15 | import Layout from '../../layout/Layout' 16 | 17 | export default function MyCreation() { 18 | const [nfts, setNfts] = useState([]) 19 | const [sold, setSold] = useState([]) 20 | const [loadingState, setLoadingState] = useState('not-loaded') 21 | 22 | useEffect(() => { 23 | loadNFTs() 24 | }, []) 25 | 26 | async function loadNFTs() { 27 | const web3Modal = new Web3Modal({ 28 | network: "mainnet", 29 | cacheProvider: true, 30 | }) 31 | const connection = await web3Modal.connect() 32 | const provider = new ethers.providers.Web3Provider(connection) 33 | const signer = provider.getSigner() 34 | 35 | const marketContract = new ethers.Contract(nftmarketaddress, Market.abi, signer) 36 | const tokenContract = new ethers.Contract(nftaddress, NFT.abi, provider) 37 | const data = await marketContract.fetchItemsCreated() 38 | 39 | const items = await Promise.all(data.map(async i => { 40 | const tokenUri = await tokenContract.tokenURI(i.tokenId) 41 | const meta = await axios.get(tokenUri) 42 | let price = ethers.utils.formatUnits(i.price.toString(), 'ether') 43 | 44 | let item = { 45 | price, 46 | tokenId: i.tokenId.toNumber(), 47 | seller: i.seller, 48 | owner: i.owner, 49 | sold: i.sold, 50 | image: meta.data.image, 51 | description: meta.data.description, 52 | name: meta.data.name 53 | } 54 | return item 55 | })) 56 | /* create a filtered array of items that have been sold */ 57 | const soldItems = items.filter(i => i.sold) 58 | setSold(soldItems) 59 | setNfts(items) 60 | setLoadingState('loaded') 61 | } 62 | 63 | if (loadingState === 'loaded' && !nfts.length) { 64 | return ( 65 | 66 |

No assets owned

67 |
68 | ) 69 | } 70 | 71 | return ( 72 | 73 |
74 |
75 |

Items Created

76 |
77 | { 78 | // NFT card UI 79 | nfts.map((nft, i) => ( 80 |
81 |
82 |
83 |
{nft.price} MATIC
84 |
85 | 86 | {/**/} 87 | 88 |
89 |
90 | 91 | {/**/} 92 |
93 |
{nft.name}
94 |

{nft.description}

95 |
96 |
97 |
98 |
99 |
100 | )) 101 | } 102 |
103 |
104 |
105 | { 106 | Boolean(sold.length) && ( 107 |
108 |

Items sold

109 |
110 | { 111 | sold.map((nft, i) => ( 112 |
113 |
114 |
115 |
{nft.price} MATIC
116 |
117 | 118 | {/**/} 119 | 120 |
121 |
122 | 123 | {/**/} 124 |
125 |
{nft.name}
126 |

{nft.description}

127 |
128 |
129 |
130 |
131 |
132 | )) 133 | } 134 |
135 |
136 | ) 137 | } 138 |
139 |
140 |
141 | ) 142 | } 143 | 144 | // Get the github session at the runtime of the app 145 | export const getServerSideProps = async (context) => { 146 | 147 | // Get github login 148 | const session = await getSession(context) 149 | if (session) { 150 | // Do something... 151 | } 152 | 153 | return { 154 | props: { 155 | session 156 | } 157 | }; 158 | }; 159 | -------------------------------------------------------------------------------- /pages/dashboard/my-nfts.js: -------------------------------------------------------------------------------- 1 | import { ethers } from 'ethers' 2 | import { useEffect, useState } from 'react' 3 | import axios from 'axios' 4 | import Web3Modal from "web3modal" 5 | import { 6 | getSession, 7 | signIn, 8 | signOut, 9 | useSession 10 | } from 'next-auth/client'; 11 | 12 | import { 13 | nftmarketaddress, nftaddress 14 | } from '../../config' 15 | 16 | import Market from '../../artifacts/contracts/Market.sol/NFTMarket.json' 17 | import NFT from '../../artifacts/contracts/NFT.sol/NFT.json' 18 | import Layout from '../../layout/Layout' 19 | 20 | export default function MyAssets() { 21 | 22 | const [nfts, setNfts] = useState([]) 23 | const [loadingState, setLoadingState] = useState('not-loaded') 24 | 25 | useEffect(() => { 26 | loadNFTs() 27 | }, []) 28 | 29 | async function loadNFTs() { 30 | const web3Modal = new Web3Modal({ 31 | network: "mainnet", 32 | cacheProvider: true, 33 | }) 34 | const connection = await web3Modal.connect() 35 | const provider = new ethers.providers.Web3Provider(connection) 36 | const signer = provider.getSigner() 37 | 38 | const marketContract = new ethers.Contract(nftmarketaddress, Market.abi, signer) 39 | const tokenContract = new ethers.Contract(nftaddress, NFT.abi, provider) 40 | const data = await marketContract.fetchMyNFTs() 41 | 42 | const items = await Promise.all(data.map(async i => { 43 | const tokenUri = await tokenContract.tokenURI(i.tokenId) 44 | const meta = await axios.get(tokenUri) 45 | let price = ethers.utils.formatUnits(i.price.toString(), 'ether') 46 | let item = { 47 | price, 48 | tokenId: i.tokenId.toNumber(), 49 | seller: i.seller, 50 | owner: i.owner, 51 | image: meta.data.image, 52 | description: meta.data.description, 53 | name: meta.data.name 54 | } 55 | return item 56 | })) 57 | setNfts(items) 58 | setLoadingState('loaded') 59 | } 60 | 61 | if (loadingState === 'loaded' && !nfts.length) { 62 | return ( 63 | 64 |

No assets owned

65 |
66 | ) 67 | } 68 | 69 | return ( 70 | 71 |
72 |
73 |
74 | { 75 | // NFT card UI 76 | nfts.map((nft, i) => ( 77 |
78 |
79 |
80 |
{nft.price} MATIC
81 |
82 | 83 | {/**/} 84 | 85 |
86 |
87 | 88 | {/**/} 89 |
90 |
{nft.name}
91 |

{nft.description}

92 |
93 |
94 |
95 |
96 |
97 | )) 98 | } 99 |
100 |
101 |
102 |
103 | ) 104 | } 105 | 106 | // Get the github session at the runtime of the app 107 | export const getServerSideProps = async (context) => { 108 | 109 | // Get github login 110 | const session = await getSession(context) 111 | if (session) { 112 | // Do something... 113 | } 114 | 115 | return { 116 | props: { 117 | session 118 | } 119 | }; 120 | }; -------------------------------------------------------------------------------- /pages/index.js: -------------------------------------------------------------------------------- 1 | import Head from 'next/head'; 2 | import styles from '../styles/Home.module.css'; 3 | import { useRouter } from "next/router"; 4 | import Link from 'next/link'; 5 | import React, { useEffect, useState } from "react"; 6 | import { Fragment } from 'react'; 7 | import { Popover, Transition } from '@headlessui/react'; 8 | import { 9 | getSession, 10 | signIn, 11 | signOut, 12 | useSession 13 | } from 'next-auth/client'; 14 | import { 15 | BookmarkAltIcon, 16 | CalendarIcon, 17 | ChartBarIcon, 18 | CursorClickIcon, 19 | CloudUploadIcon, 20 | MenuIcon, 21 | PhoneIcon, 22 | PlayIcon, 23 | LockClosedIcon, 24 | CogIcon, 25 | ServerIcon, 26 | RefreshIcon, 27 | ShieldCheckIcon, 28 | SupportIcon, 29 | ViewGridIcon, 30 | XIcon, 31 | LogoutIcon, 32 | LoginIcon, 33 | 34 | } from '@heroicons/react/outline'; 35 | // If you need another icon, just add his name in the list below 36 | // from https://unpkg.com/browse/@heroicons/react@1.0.5/outline/ 37 | let Web3 = require('web3'); 38 | import Footer from '../components/landing/footer' 39 | import Features from '../components/landing/features'; 40 | import Faq from '../components/landing/faq'; 41 | import SToken from '../components/landing/stoken'; 42 | import Hero from '../components/landing/hero'; 43 | 44 | const home = ({ session }) => { 45 | 46 | // Mobile menu data 47 | const mobileMenu = [ 48 | { name: 'Marketplace', icon: PlayIcon, href:'/dashboard' } 49 | ] 50 | 51 | // ---- METAMASK ---- 52 | const [address, setAddress] = useState([]) 53 | const [count, setCount] = useState([0]) 54 | const [heroButton, setHeroButton] = useState('Connect Wallet'); 55 | 56 | // MetaMask injects the window.ethereum object into our browser whenever the extension 57 | // is installed and active. We do this when our page is done loading in a useEffect hook 58 | // and put it into our state for later use. 59 | useEffect(() => { 60 | 61 | 62 | const checkConnection = async () => { 63 | 64 | // Check if browser is running Metamask 65 | let web3 = null; 66 | if (window.ethereum) { 67 | web3 = new Web3(window.ethereum); 68 | setCount(1); 69 | } else if (window.web3) { 70 | web3 = new Web3(window.web3.currentProvider); 71 | }; 72 | 73 | // Check if User is already connected by retrieving the accounts 74 | if(web3===null){ 75 | setHeroButton('Please Install Metamask Wallet') 76 | } 77 | if(web3){ 78 | web3.eth.getAccounts() 79 | .then(async (addr) => { 80 | 81 | // Set User account into state 82 | setAddress(addr); 83 | 84 | if (addr.length > 0) { 85 | console.log("Current Metamask wallet: ", addr) 86 | setHeroButton("Marketplace") 87 | } 88 | }); 89 | }; 90 | } 91 | checkConnection(); 92 | 93 | }, []) 94 | 95 | console.log("Current Github session: ", session); 96 | 97 | return ( 98 |
99 | 100 | DevNFT 101 | 102 | 103 | 104 | 105 | {/* We should add this header inside a component */} 106 | 107 |
108 |
109 | 128 |
129 | 130 | Open menu 131 | 133 |
134 |
135 | {/* 140 | Connect Wallet 141 | */} 142 | 143 | {/* ------ Display if connected ------ */} 144 | {address.length > 0 && <> 145 |   146 | 🦊 147 |   148 |
{address}
149 | } 150 | {session && <> 151 | 152 | {session.name} 153 | {session.name} 154 | 155 | 156 | 157 | Marketplace 158 | 159 | 160 | 162 | signOut({ 163 | callbackUrl: `${window.location.origin}` 164 | }) 165 | } 166 | className="ml-1 whitespace-nowrap inline-flex items-center cursor-pointer justify-center px-4 py-1 border border-transparent rounded-md shadow-sm text-base font-medium text-white bg-red-800 hover:bg-red-900"> 167 | 170 | } 171 | 172 | {/* ------ Display if not connected ------ */} 173 | {!session && <> 174 | 175 | 179 | Login 180 | 181 | 182 | } 183 | 184 | 185 |
186 |
187 |
188 | 189 | 198 | 199 | {/* Menu Mobile */} 200 | 204 |
205 |
206 |
207 |
208 | {/* DEV NFT Mobile LOGO */} 209 | Workflow 214 |
215 |
216 | 217 | Close menu 218 | 220 |
221 |
222 |
223 | 261 |
262 |
263 | 264 |
265 |
266 |
267 |
268 | 269 | {/* Hero */} 270 |
271 | 272 |
273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 |
281 |
282 | ) 283 | } 284 | 285 | // Get the github session at the runtime of the app 286 | export const getServerSideProps = async (context) => { 287 | const session = await getSession(context); 288 | 289 | // Get account from web3.js (not used atm) 290 | // web3.eth.getAccounts(function(err, accounts){ 291 | // if (err != null) console.error("An error occurred: "+err); 292 | // else if (accounts.length == 0) console.log("User is not logged in to MetaMask"); 293 | // else console.log("User is logged in to MetaMask"); 294 | // }); 295 | 296 | return { 297 | props: { 298 | session, 299 | }, 300 | }; 301 | }; 302 | 303 | export default home; 304 | 305 | -------------------------------------------------------------------------------- /pages/login.js: -------------------------------------------------------------------------------- 1 | import { useRouter } from "next/router"; 2 | import { 3 | getSession, 4 | signIn, 5 | signOut, 6 | useSession 7 | } from 'next-auth/client'; 8 | import Link from 'next/link'; 9 | import { checkProperties } from "@ethersproject/properties"; 10 | import React, { useEffect, useState } from "react"; 11 | import { ethers } from "ethers"; 12 | import dynamic from "next/dynamic"; 13 | let Web3 = require('web3'); 14 | 15 | 16 | 17 | function Login({ session }) { 18 | 19 | 20 | // const [Web3, web3, setWeb3] = useState([]) 21 | const [address, setAddress] = useState([]) 22 | const [isMeta, setMeta] = useState(false) 23 | const [web3, setWeb3] = useState([]) 24 | 25 | const [heroButton, setHeroButton] = useState('Connect Wallet'); 26 | 27 | 28 | 29 | useEffect(() => { 30 | 31 | // TODO: redirect user if already logged 32 | 33 | const checkConnection = async () => { 34 | 35 | // Check if browser is running Metamask 36 | let web3; 37 | if (window.ethereum) { 38 | web3 = new Web3(window.ethereum); 39 | } else if (window.web3) { 40 | web3 = new Web3(window.web3.currentProvider); 41 | }; 42 | 43 | // Check if User is already connected by retrieving the accounts 44 | web3.eth.getAccounts() 45 | .then(async (addr) => { 46 | 47 | // Set User account into state 48 | setAddress(addr); 49 | 50 | if (addr.length > 0) { 51 | setHeroButton("Dashboard") 52 | } 53 | }); 54 | }; 55 | checkConnection(); 56 | 57 | }, []) 58 | 59 | // Generate a random number 60 | // Math.random()-based solutions do not provide good uniqueness guarantees 61 | function uuidv4() { 62 | return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => 63 | (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16) 64 | ); 65 | } 66 | 67 | const [loginState, setLoginState] = useState() 68 | const router = useRouter(); 69 | 70 | const login = async () => { 71 | setLoginState("Connecting to your wallet...") 72 | if (!window.ethereum) { 73 | setLoginState("No Metamask wallet... Please install it."); 74 | return; 75 | } 76 | 77 | const provider = new ethers.providers.Web3Provider(window.ethereum); 78 | await provider.send("eth_requestAccounts", []); 79 | const signer = provider.getSigner(); 80 | const walletAddr = await signer.getAddress(); 81 | 82 | // Set address state 83 | setAddress(walletAddr) 84 | 85 | // Set web3.js object 86 | let w3 = new Web3(ethereum) 87 | setWeb3(w3) 88 | 89 | // security: we need to fetch a backend to get a generated random uuid 90 | // const signatureNumbers = fetch(our_api_url:api_port/get_nonce) 91 | 92 | // clientside uglyhack : 93 | const signatureNumbers = uuidv4(); 94 | 95 | // Here we can make custom signature at the login popup 96 | const signature = await signer.signMessage("Welcome to the DEV-NFT Marketplace - uuid: " + signatureNumbers); 97 | 98 | // Uncomment to check signature 99 | // console.log("signature", signature) 100 | 101 | // redirect to the dashboard after loggin 102 | router.push('/dashboard'); 103 | } 104 | 105 | return ( 106 | <> 107 |
108 |
109 |
110 |
111 | Workflow 116 |

Sign in to your account

117 |

118 | Or{' '} 119 | 120 | 121 | back to home 122 | 123 | 124 |

125 |
126 | 127 | {/* Sign-in button */} 128 |
129 |
130 |
131 |

Sign in with

132 |

{loginState}

133 | 134 | 174 |
175 |
176 |
177 |
178 |
179 | 180 | {/* Image right */} 181 |
182 | 187 |
188 |
189 | 190 | ) 191 | } 192 | 193 | 194 | export async function getServerSideProps(context) { 195 | 196 | // Get github login 197 | const session = await getSession(context) 198 | 199 | if (!session) return { props: { loggedIn: false } }; 200 | 201 | if (session) { 202 | return { 203 | redirect: { 204 | destination: '/dashboard', 205 | permanent: false, 206 | }, 207 | } 208 | } 209 | 210 | 211 | 212 | // By returning { props: { reposList } }, the ReposList component 213 | // will receive `reposList` as a prop at build time 214 | return { 215 | props: { 216 | session 217 | }, 218 | } 219 | } 220 | 221 | export default Login; 222 | -------------------------------------------------------------------------------- /pages/repos-list.js: -------------------------------------------------------------------------------- 1 | import { useRouter } from "next/router"; 2 | import { 3 | getSession, 4 | signIn, 5 | signOut, 6 | useSession 7 | } from 'next-auth/client'; 8 | import Link from 'next/link'; 9 | import { checkProperties } from "@ethersproject/properties"; 10 | 11 | 12 | 13 | function ReposList({ reposList, session }) { 14 | 15 | // uncomment to see the reposList of the logged user 16 | // console.log(reposList) 17 | 18 | const router = useRouter(); 19 | if (router.isFallback) return
Loading...
; 20 | 21 | const getRepositoryList = (github_login) => { 22 | return request("/api/repos_list", { 23 | body: JSON.stringify({ github_login }), 24 | headers: { 25 | "Content-Type": "application/json", 26 | }, 27 | method: "GET", 28 | }).then((RepositoryList) => { 29 | console.log("User repository list:", ReposList); 30 | }) 31 | }; 32 | 33 | return ( 34 | <> 35 |
36 |
🚧
37 |
Repos-list
38 | 39 | {/* Cards container */} 40 |
41 | {reposList.map((repos) => ( 42 | 54 | ))} 55 |
56 | 57 | 58 | 61 | 62 |
63 | 64 | ) 65 | } 66 | 67 | 68 | export async function getServerSideProps(context) { 69 | 70 | // Get github login 71 | const session = await getSession(context) 72 | if (session.profile) { 73 | var login = session.profile.login; 74 | } 75 | 76 | const res = await fetch('https://api.github.com/users/'+ login + '/repos'); 77 | const reposList = await res.json(); 78 | 79 | // warning: reposList is 153Kb, we should optimize the list before return it. 80 | 81 | if (!reposList) { 82 | return { 83 | notFound: true, 84 | } 85 | } 86 | 87 | // By returning { props: { reposList } }, the ReposList component 88 | // will receive `reposList` as a prop at build time 89 | return { 90 | props: { 91 | reposList, 92 | session 93 | }, 94 | } 95 | } 96 | 97 | export default ReposList; 98 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | // If you want to use other PostCSS plugins, see the following: 2 | // https://tailwindcss.com/docs/using-with-preprocessors 3 | module.exports = { 4 | plugins: { 5 | tailwindcss: {}, 6 | autoprefixer: {}, 7 | }, 8 | } 9 | -------------------------------------------------------------------------------- /public/DevNFT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WebXDAO/DEV-NFT/cc204dfcf04aa03f33091a52246aafee1d6ae9bc/public/DevNFT.png -------------------------------------------------------------------------------- /public/DevNFT.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WebXDAO/DEV-NFT/cc204dfcf04aa03f33091a52246aafee1d6ae9bc/public/favicon.ico -------------------------------------------------------------------------------- /public/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WebXDAO/DEV-NFT/cc204dfcf04aa03f33091a52246aafee1d6ae9bc/public/hero.png -------------------------------------------------------------------------------- /public/metamask-fox.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 50 | 51 | 52 | 54 | 56 | 57 | 58 | 59 | 61 | 62 | -------------------------------------------------------------------------------- /public/section-media.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WebXDAO/DEV-NFT/cc204dfcf04aa03f33091a52246aafee1d6ae9bc/public/section-media.png -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /styles/Home.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | min-height: 100vh; 3 | padding: 0 0.5rem; 4 | display: flex; 5 | flex-direction: column; 6 | justify-content: center; 7 | align-items: center; 8 | } 9 | 10 | .main { 11 | padding: 5rem 0; 12 | flex: 1; 13 | display: flex; 14 | flex-direction: column; 15 | justify-content: center; 16 | align-items: center; 17 | } 18 | 19 | .footer { 20 | width: 100%; 21 | height: 100px; 22 | border-top: 1px solid #eaeaea; 23 | display: flex; 24 | justify-content: center; 25 | align-items: center; 26 | } 27 | 28 | .footer img { 29 | margin-left: 0.5rem; 30 | } 31 | 32 | .footer a { 33 | display: flex; 34 | justify-content: center; 35 | align-items: center; 36 | } 37 | 38 | .title a { 39 | color: #0070f3; 40 | text-decoration: none; 41 | } 42 | 43 | .title a:hover, 44 | .title a:focus, 45 | .title a:active { 46 | text-decoration: underline; 47 | } 48 | 49 | .title { 50 | margin: 0; 51 | line-height: 1.15; 52 | font-size: 4rem; 53 | } 54 | 55 | .title, 56 | .description { 57 | text-align: center; 58 | } 59 | 60 | .description { 61 | line-height: 1.5; 62 | font-size: 1.5rem; 63 | } 64 | 65 | .code { 66 | background: #fafafa; 67 | border-radius: 5px; 68 | padding: 0.75rem; 69 | font-size: 1.1rem; 70 | font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, 71 | Bitstream Vera Sans Mono, Courier New, monospace; 72 | } 73 | 74 | .grid { 75 | display: flex; 76 | align-items: center; 77 | justify-content: center; 78 | flex-wrap: wrap; 79 | max-width: 800px; 80 | margin-top: 3rem; 81 | } 82 | 83 | .card { 84 | margin: 1rem; 85 | flex-basis: 45%; 86 | padding: 1.5rem; 87 | text-align: left; 88 | color: inherit; 89 | text-decoration: none; 90 | border: 1px solid #eaeaea; 91 | border-radius: 10px; 92 | transition: color 0.15s ease, border-color 0.15s ease; 93 | } 94 | 95 | .card:hover, 96 | .card:focus, 97 | .card:active { 98 | color: #0070f3; 99 | border-color: #0070f3; 100 | } 101 | 102 | .card h3 { 103 | margin: 0 0 1rem 0; 104 | font-size: 1.5rem; 105 | } 106 | 107 | .card p { 108 | margin: 0; 109 | font-size: 1.25rem; 110 | line-height: 1.5; 111 | } 112 | 113 | .logo { 114 | height: 1em; 115 | } 116 | 117 | @media (max-width: 600px) { 118 | .grid { 119 | width: 100%; 120 | flex-direction: column; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /styles/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | mode: 'jit', 3 | purge: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'], 4 | darkMode: false, // or 'media' or 'class' 5 | theme: { 6 | extend: {}, 7 | }, 8 | variants: { 9 | extend: {}, 10 | }, 11 | plugins: [ 12 | require('@tailwindcss/forms') 13 | ], 14 | } 15 | --------------------------------------------------------------------------------