Skip to content

Commit b4d9243

Browse files
authored
Merge pull request #1 from anwen/v2
V2 merge
2 parents e274053 + 7f79e22 commit b4d9243

24 files changed

+3943
-476
lines changed

.gitignore

+4-1
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,7 @@ node_modules
4343
cache
4444
artifacts
4545

46-
*_raw
46+
# contract type generation
47+
/contracts/types
48+
49+
*_raw

README_raw.md

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
## Full stack NFT marketplace built with Polygon, Solidity, IPFS, & Next.js
2+
3+
![Header](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pfofv47dooojerkmfgr4.png)
4+
5+
### Running this project
6+
7+
#### Gitpod
8+
9+
To deploy this project to Gitpod, follow these steps:
10+
11+
1. Click this link to deploy
12+
13+
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#github.com/dabit3/polygon-ethereum-nextjs-marketplace)
14+
15+
2. In __pages/index.js__, pass in the RPC address given to you by GitPod to the call to `JsonRpcProvider` function:
16+
17+
```javascript
18+
/* update this: */
19+
const provider = new ethers.providers.JsonRpcProvider()
20+
21+
/* to this: */
22+
const provider = new ethers.providers.JsonRpcProvider("https://8545-youendpoint.gitpod.io/")
23+
```
24+
25+
3. Import the RPC address given to you by GitPod into your MetaMask wallet
26+
27+
![MetaMask RPC Import](wallet.png)
28+
29+
#### Local setup
30+
31+
To run this project locally, follow these steps.
32+
33+
1. Clone the project locally, change into the directory, and install the dependencies:
34+
35+
```sh
36+
git clone https://github.com/dabit3/polygon-ethereum-nextjs-marketplace.git
37+
38+
cd polygon-ethereum-nextjs-marketplace
39+
40+
# install using NPM or Yarn
41+
npm install
42+
43+
# or
44+
45+
yarn
46+
```
47+
48+
2. Start the local Hardhat node
49+
50+
```sh
51+
npx hardhat node
52+
```
53+
54+
3. With the network running, deploy the contracts to the local network in a separate terminal window
55+
56+
```sh
57+
npx hardhat run scripts/deploy.js --network localhost
58+
```
59+
60+
4. Start the app
61+
62+
```
63+
npm run dev
64+
```
65+
66+
### Configuration
67+
68+
To deploy to Polygon test or main networks, update the configurations located in __hardhat.config.js__ to use a private key and, optionally, deploy to a private RPC like Infura.
69+
70+
```javascript
71+
require("@nomiclabs/hardhat-waffle");
72+
const fs = require('fs');
73+
const privateKey = fs.readFileSync(".secret").toString().trim() || "01234567890123456789";
74+
75+
// infuraId is optional if you are using Infura RPC
76+
const infuraId = fs.readFileSync(".infuraid").toString().trim() || "";
77+
78+
module.exports = {
79+
defaultNetwork: "hardhat",
80+
networks: {
81+
hardhat: {
82+
chainId: 1337
83+
},
84+
mumbai: {
85+
// Infura
86+
// url: `https://polygon-mumbai.infura.io/v3/${infuraId}`
87+
url: "https://rpc-mumbai.matic.today",
88+
accounts: [privateKey]
89+
},
90+
matic: {
91+
// Infura
92+
// url: `https://polygon-mainnet.infura.io/v3/${infuraId}`,
93+
url: "https://rpc-mainnet.maticvigil.com",
94+
accounts: [privateKey]
95+
}
96+
},
97+
solidity: {
98+
version: "0.8.4",
99+
settings: {
100+
optimizer: {
101+
enabled: true,
102+
runs: 200
103+
}
104+
}
105+
}
106+
};
107+
```
108+
109+
If using Infura, update __.infuraid__ with your [Infura](https://infura.io/) project ID.

contracts/Market.sol

+26-8
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,14 @@ pragma solidity ^0.8.3;
44
import "@openzeppelin/contracts/utils/Counters.sol";
55
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
66
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
7-
87
import "hardhat/console.sol";
98

109
contract NFTMarket is ReentrancyGuard {
1110
using Counters for Counters.Counter;
1211
Counters.Counter private _itemIds;
1312
Counters.Counter private _itemsSold;
14-
1513
address payable owner;
16-
// uint256 listingPrice = 0.025 ether;
17-
uint256 listingPrice = 0.001 ether;
14+
uint256 listingPrice = 0.0001 ether;
1815

1916
constructor() {
2017
owner = payable(msg.sender);
@@ -31,6 +28,7 @@ contract NFTMarket is ReentrancyGuard {
3128
}
3229

3330
mapping(uint256 => MarketItem) private idToMarketItem;
31+
mapping(uint256 => MarketItem) private tidToMarketItem;
3432

3533
event MarketItemCreated (
3634
uint indexed itemId,
@@ -56,9 +54,9 @@ contract NFTMarket is ReentrancyGuard {
5654
require(price > 0, "Price must be at least 1 wei");
5755
require(msg.value == listingPrice, "Price must be equal to listing price");
5856

59-
_itemIds.increment();
57+
_itemIds.increment(); // should not use itemid
6058
uint256 itemId = _itemIds.current();
61-
59+
6260
idToMarketItem[itemId] = MarketItem(
6361
itemId,
6462
nftContract,
@@ -68,6 +66,16 @@ contract NFTMarket is ReentrancyGuard {
6866
price,
6967
false
7068
);
69+
// fix bug, use tokenId, needed when sale
70+
tidToMarketItem[tokenId] = MarketItem(
71+
itemId,
72+
nftContract,
73+
tokenId,
74+
payable(msg.sender),
75+
payable(address(0)),
76+
price,
77+
false
78+
);
7179

7280
IERC721(nftContract).transferFrom(msg.sender, address(this), tokenId);
7381

@@ -88,14 +96,22 @@ contract NFTMarket is ReentrancyGuard {
8896
address nftContract,
8997
uint256 itemId
9098
) public payable nonReentrant {
91-
uint price = idToMarketItem[itemId].price;
92-
uint tokenId = idToMarketItem[itemId].tokenId;
99+
// Note: idToMarketItem maybe less than allItem(some item-minted-not-goto-market)
100+
// so price = allItem[itemId].price
101+
// so tokenId = allItem[itemId].tokenId // tokenId === itemId
102+
103+
// uint tokenId = idToMarketItem[itemId].tokenId;
104+
// get price by itemid
105+
uint tokenId = itemId;
106+
uint price = tidToMarketItem[itemId].price;
107+
93108
require(msg.value == price, "Please submit the asking price in order to complete the purchase");
94109

95110
idToMarketItem[itemId].seller.transfer(msg.value);
96111
IERC721(nftContract).transferFrom(address(this), msg.sender, tokenId);
97112
idToMarketItem[itemId].owner = payable(msg.sender);
98113
idToMarketItem[itemId].sold = true;
114+
// tidToMarketItem
99115
_itemsSold.increment();
100116
payable(owner).transfer(listingPrice);
101117
}
@@ -115,9 +131,11 @@ contract NFTMarket is ReentrancyGuard {
115131
currentIndex += 1;
116132
}
117133
}
134+
118135
return items;
119136
}
120137

138+
121139
/* Returns only items that a user has purchased */
122140
function fetchMyNFTs() public view returns (MarketItem[] memory) {
123141
uint totalItemCount = _itemIds.current();

contracts/NFT.sol

+5-25
Original file line numberDiff line numberDiff line change
@@ -5,47 +5,27 @@ import "@openzeppelin/contracts/utils/Counters.sol";
55
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
66
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
77
import "@openzeppelin/contracts/access/Ownable.sol";
8-
98
import "hardhat/console.sol";
109

11-
// contract DwebNFT is ERC721, Ownable {
1210
contract NFT is ERC721URIStorage {
1311
using Counters for Counters.Counter;
1412
Counters.Counter private _tokenIds;
1513
address contractAddress;
16-
17-
using Strings for uint256;
14+
using Strings for uint256; // uint256 is uint
1815
mapping (uint256 => string) private _tokenURIs;
19-
// constructor() ERC721("DwebNFT", "DNFT") {}
20-
// constructor(address marketplaceAddress) ERC721("Metaverse", "METT") {
21-
constructor(address marketplaceAddress) ERC721("DwebVerse", "DWV") {
16+
17+
constructor(address marketplaceAddress) ERC721("CC4", "CC4") {
2218
contractAddress = marketplaceAddress;
2319
}
2420

25-
// function mint
21+
// mint, uri is tokenURI
2622
function createToken(string memory uri) public returns (uint) {
2723
_tokenIds.increment();
2824
uint256 newItemId = _tokenIds.current();
29-
// recipient is msg.sender
30-
// uri is tokenURI
31-
// uint256 is uint
32-
_mint(msg.sender, newItemId);
25+
_mint(msg.sender, newItemId); // msg.sender is recipient
3326
_setTokenURI(newItemId, uri);
3427
setApprovalForAll(contractAddress, true);
3528
return newItemId;
3629
}
3730

38-
// function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
39-
// _tokenURIs[tokenId] = _tokenURI;
40-
// }
41-
42-
// function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
43-
// require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
44-
// string memory _tokenURI = _tokenURIs[tokenId];
45-
// return _tokenURI;
46-
// }
47-
48-
49-
50-
5131
}

hardhat.config.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ module.exports = {
1313
// Infura
1414
// url: `https://polygon-mumbai.infura.io/v3/${infuraId}`
1515
// url: "https://rpc-mumbai.matic.today",
16-
url: "https://rpc-mumbai.maticvigil.com",
16+
// url: "https://rpc-mumbai.maticvigil.com",
17+
url: "https://matic-mumbai.chainstacklabs.com",
18+
// url: "https://rpc-mumbai.maticvigil.com/v1/35346f853fb4496728602ff72a70eb9a8785064e",
1719
accounts: [privateKey]
1820
},
1921
matic: {

next.config.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1-
module.exports = {
2-
reactStrictMode: true,
3-
}
1+
const withTM = require("next-transpile-modules")(["react-markdown"]);
2+
3+
module.exports = withTM({
4+
reactStrictMode: true
5+
});

package.json

+12-4
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,30 @@
55
"scripts": {
66
"dev": "next dev",
77
"build": "next build",
8-
"start": "next start",
8+
"start": "export PORT=4006 next start",
99
"lint": "next lint"
1010
},
1111
"dependencies": {
12+
"@headlessui/react": "^1.4.1",
13+
"@heroicons/react": "^1.0.4",
1214
"@nomiclabs/hardhat-ethers": "^2.0.2",
1315
"@nomiclabs/hardhat-waffle": "^2.0.1",
1416
"@openzeppelin/contracts": "^4.2.0",
17+
"@textile/eth-storage": "^1.0.0",
1518
"axios": "^0.21.1",
1619
"chai": "^4.3.4",
1720
"ethereum-waffle": "^3.4.0",
1821
"ethers": "^5.4.1",
22+
"graphql-tag": "^2.12.6",
23+
"gray-matter": "^4.0.3",
1924
"hardhat": "^2.4.1",
2025
"ipfs-http-client": "^50.1.2",
21-
"next": "11.0.1",
22-
"react": "17.0.2",
23-
"react-dom": "17.0.2",
26+
"next": "^12.0.4",
27+
"next-transpile-modules": "^8.0.0",
28+
"nft.storage": "^3.3.0",
29+
"react": "^17.0.2",
30+
"react-dom": "^17.0.2",
31+
"react-markdown": "^7.1.0",
2432
"web3modal": "^1.9.3"
2533
},
2634
"devDependencies": {

0 commit comments

Comments
 (0)