├── NFTCollection.sol
├── Part2-NFT-Market-Resell-Contract
└── N2D-Market-NFT-Resell-SmartContract.sol
├── Part3-NextJS-Market-WebFrontEnd
├── _app.js
├── engine
│ ├── NFTCollection.json
│ ├── Resell.json
│ └── configuration.js
├── index.js
└── portal.js
├── Part4-RelistNFT-Buy-Sell
├── _app.js
├── engine
│ ├── NFTCollection.json
│ ├── Resell.json
│ └── configuration.js
├── footer.js
├── hardhat.config.js
├── index.js
├── portal.js
└── public
│ ├── bsc.png
│ ├── chainagnostic.png
│ ├── discord.png
│ ├── discordlogo.PNG
│ ├── ethereumlogo.png
│ ├── n2DMarket.png
│ ├── n2dr-logo.png
│ ├── polygonwhite.png
│ ├── twitter.png
│ ├── web3logo.png
│ └── youtube.png
├── Part5-Create-and-Sell-NFT-App
├── Market.json
├── N2D-Market-CreateNFT-SmartContract.sol
├── N2D-Market-SellCreatedNFT-SmartContract.sol
├── NFT.json
├── _app.js
├── create.js
├── index.js
└── portal.js
├── Part6-Final-Multichain-Integration
├── engine
│ ├── chainchange.js
│ ├── configuration.js
│ └── connectchain.js
└── pages
│ ├── _app.js
│ ├── create.js
│ ├── index.js
│ └── portal.js
├── README.md
└── n2DMarket.png
/NFTCollection.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT LICENSE
2 |
3 | /*
4 | N2D NFT ERC721 NFT Smart Contract.
5 |
6 | Follow/Subscribe Youtube, Github, IM, Tiktok
7 | for more amazing content!!
8 | @Net2Dev
9 | ███╗░░██╗███████╗████████╗██████╗░██████╗░███████╗██╗░░░██╗
10 | ████╗░██║██╔════╝╚══██╔══╝╚════██╗██╔══██╗██╔════╝██║░░░██║
11 | ██╔██╗██║█████╗░░░░░██║░░░░░███╔═╝██║░░██║█████╗░░╚██╗░██╔╝
12 | ██║╚████║██╔══╝░░░░░██║░░░██╔══╝░░██║░░██║██╔══╝░░░╚████╔╝░
13 | ██║░╚███║███████╗░░░██║░░░███████╗██████╔╝███████╗░░╚██╔╝░░
14 | ╚═╝░░╚══╝╚══════╝░░░╚═╝░░░╚══════╝╚═════╝░╚══════╝░░░╚═╝░░░
15 |
16 | THIS CONTRACT IS AVAILABLE FOR EDUCATIONAL
17 | PURPOSES ONLY. YOU ARE SOLELY REPONSIBLE
18 | FOR ITS USE. I AM NOT RESPONSIBLE FOR ANY
19 | OTHER USE. THIS IS TRAINING/EDUCATIONAL
20 | MATERIAL. ONLY USE IT IF YOU AGREE TO THE
21 | TERMS SPECIFIED ABOVE.
22 | */
23 |
24 |
25 | import "@openzeppelin/contracts/access/Ownable.sol";
26 | import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
27 |
28 | pragma solidity ^0.8.4;
29 |
30 | contract Collection is ERC721Enumerable, Ownable {
31 |
32 |
33 | using Strings for uint256;
34 | string public baseURI;
35 | string public baseExtension = ".json";
36 | uint256 public maxSupply = 1000;
37 | uint256 public maxMintAmount = 5;
38 | bool public paused = false;
39 |
40 | constructor() ERC721("Net2Dev NFT Collection", "N2D") {}
41 |
42 |
43 | function _baseURI() internal view virtual override returns (string memory) {
44 | return "ipfs://QmYB5uWZqfunBq7yWnamTqoXWBAHiQoirNLmuxMzDThHhi/";
45 |
46 | }
47 |
48 | function mint(address _to, uint256 _mintAmount) public payable {
49 | uint256 supply = totalSupply();
50 | require(!paused);
51 | require(_mintAmount > 0);
52 | require(_mintAmount <= maxMintAmount);
53 | require(supply + _mintAmount <= maxSupply);
54 |
55 | for (uint256 i = 1; i <= _mintAmount; i++) {
56 | _safeMint(_to, supply + i);
57 | }
58 | }
59 |
60 |
61 | function walletOfOwner(address _owner)
62 | public
63 | view
64 | returns (uint256[] memory)
65 | {
66 | uint256 ownerTokenCount = balanceOf(_owner);
67 | uint256[] memory tokenIds = new uint256[](ownerTokenCount);
68 | for (uint256 i; i < ownerTokenCount; i++) {
69 | tokenIds[i] = tokenOfOwnerByIndex(_owner, i);
70 | }
71 | return tokenIds;
72 | }
73 |
74 |
75 | function tokenURI(uint256 tokenId)
76 | public
77 | view
78 | virtual
79 | override
80 | returns (string memory) {
81 | require(
82 | _exists(tokenId),
83 | "ERC721Metadata: URI query for nonexistent token"
84 | );
85 |
86 | string memory currentBaseURI = _baseURI();
87 | return
88 | bytes(currentBaseURI).length > 0
89 | ? string(abi.encodePacked(currentBaseURI, tokenId.toString(), baseExtension))
90 | : "";
91 | }
92 | // only owner
93 |
94 | function setmaxMintAmount(uint256 _newmaxMintAmount) public onlyOwner() {
95 | maxMintAmount = _newmaxMintAmount;
96 | }
97 |
98 | function setBaseURI(string memory _newBaseURI) public onlyOwner() {
99 | baseURI = _newBaseURI;
100 | }
101 |
102 | function setBaseExtension(string memory _newBaseExtension) public onlyOwner() {
103 | baseExtension = _newBaseExtension;
104 | }
105 |
106 | function pause(bool _state) public onlyOwner() {
107 | paused = _state;
108 | }
109 |
110 | function withdraw() public payable onlyOwner() {
111 | require(payable(msg.sender).send(address(this).balance));
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/Part2-NFT-Market-Resell-Contract/N2D-Market-NFT-Resell-SmartContract.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT LICENSE
2 |
3 | /*
4 | Follow/Subscribe Youtube, Github, IM, Tiktok
5 | for more amazing content!!
6 | @Net2Dev
7 | ███╗░░██╗███████╗████████╗██████╗░██████╗░███████╗██╗░░░██╗
8 | ████╗░██║██╔════╝╚══██╔══╝╚════██╗██╔══██╗██╔════╝██║░░░██║
9 | ██╔██╗██║█████╗░░░░░██║░░░░░███╔═╝██║░░██║█████╗░░╚██╗░██╔╝
10 | ██║╚████║██╔══╝░░░░░██║░░░██╔══╝░░██║░░██║██╔══╝░░░╚████╔╝░
11 | ██║░╚███║███████╗░░░██║░░░███████╗██████╔╝███████╗░░╚██╔╝░░
12 | ╚═╝░░╚══╝╚══════╝░░░╚═╝░░░╚══════╝╚═════╝░╚══════╝░░░╚═╝░░░
13 | THIS CONTRACT IS AVAILABLE FOR EDUCATIONAL
14 | PURPOSES ONLY. YOU ARE SOLELY REPONSIBLE
15 | FOR ITS USE. I AM NOT RESPONSIBLE FOR ANY
16 | OTHER USE. THIS IS TRAINING/EDUCATIONAL
17 | MATERIAL. ONLY USE IT IF YOU AGREE TO THE
18 | TERMS SPECIFIED ABOVE.
19 |
20 | Revised v2
21 |
22 | - Added Cancel Sale Function
23 | - Fixed ItemId to TokenId Conflict Bug
24 | using tokenId as location in Memory in Struct
25 |
26 | Revised v3
27 |
28 | - Added Listing Fee Balance Withdraw Function
29 |
30 | */
31 |
32 |
33 |
34 | pragma solidity 0.8.4;
35 |
36 | import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
37 | import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
38 | import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
39 | import "@openzeppelin/contracts/access/Ownable.sol";
40 |
41 | contract NFTMarketResell is IERC721Receiver, ReentrancyGuard, Ownable {
42 |
43 | address payable holder;
44 | uint256 listingFee = 0.0025 ether;
45 |
46 | struct List {
47 | uint256 tokenId;
48 | address payable seller;
49 | address payable holder;
50 | uint256 price;
51 | bool sold;
52 | }
53 |
54 | mapping(uint256 => List) public vaultItems;
55 |
56 | event NFTListCreated (
57 | uint256 indexed tokenId,
58 | address seller,
59 | address holder,
60 | uint256 price,
61 | bool sold
62 | );
63 |
64 | function getListingFee() public view returns (uint256) {
65 | return listingFee;
66 | }
67 |
68 | ERC721Enumerable nft;
69 |
70 | constructor(ERC721Enumerable _nft) {
71 | holder = payable(msg.sender);
72 | nft = _nft;
73 | }
74 |
75 | function listSale(uint256 tokenId, uint256 price) public payable nonReentrant {
76 | require(nft.ownerOf(tokenId) == msg.sender, "NFT not yours");
77 | require(vaultItems[tokenId].tokenId == 0, "NFT already listed");
78 | require(price > 0, "Amount must be higher than 0");
79 | require(msg.value == listingFee, "Please transfer 0.0025 crypto to pay listing fee");
80 | vaultItems[tokenId] = List(tokenId, payable(msg.sender), payable(address(this)), price, false);
81 | nft.transferFrom(msg.sender, address(this), tokenId);
82 | emit NFTListCreated(tokenId, msg.sender, address(this), price, false);
83 | }
84 |
85 | function buyNft(uint256 tokenId) public payable nonReentrant {
86 | uint256 price = vaultItems[tokenId].price;
87 | require(msg.value == price, "Transfer Total Amount to complete transaction");
88 | vaultItems[tokenId].seller.transfer(msg.value);
89 | nft.transferFrom(address(this), msg.sender, tokenId);
90 | vaultItems[tokenId].sold = true;
91 | delete vaultItems[tokenId];
92 | }
93 |
94 | function cancelSale(uint256 tokenId) public nonReentrant {
95 | require(vaultItems[tokenId].seller == msg.sender, "NFT not yours");
96 | nft.transferFrom(address(this), msg.sender, tokenId);
97 | delete vaultItems[tokenId];
98 | }
99 |
100 | function getPrice(uint256 tokenId) public view returns (uint256) {
101 | uint256 price = vaultItems[tokenId].price;
102 | return price;
103 | }
104 |
105 | function nftListings() public view returns (List[] memory) {
106 | uint256 nftCount = nft.totalSupply();
107 | uint currentIndex = 0;
108 | List[] memory items = new List[](nftCount);
109 | for (uint i = 0; i < nftCount; i++) {
110 | if (vaultItems[i + 1].holder == address(this)) {
111 | uint currentId = i + 1;
112 | List storage currentItem = vaultItems[currentId];
113 | items[currentIndex] = currentItem;
114 | currentIndex += 1;
115 | }
116 | }
117 | return items;
118 | }
119 |
120 | function onERC721Received(
121 | address,
122 | address from,
123 | uint256,
124 | bytes calldata
125 | ) external pure override returns (bytes4) {
126 | require(from == address(0x0), "Cannot send nfts to Vault directly");
127 | return IERC721Receiver.onERC721Received.selector;
128 | }
129 |
130 | function withdraw() public payable onlyOwner() {
131 | require(payable(msg.sender).send(address(this).balance));
132 | }
133 |
134 | }
135 |
--------------------------------------------------------------------------------
/Part3-NextJS-Market-WebFrontEnd/_app.js:
--------------------------------------------------------------------------------
1 | import { createTheme, NextUIProvider } from "@nextui-org/react";
2 | import 'sf-font';
3 | import Link from 'next/link'
4 | import { Spacer, Button, Col, Row, Container, Dropdown } from '@nextui-org/react';
5 | import react from "react";
6 |
7 | const theme = createTheme({
8 | type: "dark",
9 | theme: {
10 | fontFamily:'SF Pro Display',
11 | colors: {
12 | primaryLight: '$blue200',
13 | primaryLightHover: '$blue300',
14 | primaryLightActive: '$blue400',
15 | primaryLightContrast: '$blue600',
16 | primary: '$purple500',
17 | primaryBorder: '$blue500',
18 | primaryBorderHover: '$blue600',
19 | primarySolidHover: '$blue700',
20 | primarySolidContrast: '$white',
21 | primaryShadow: '$white500',
22 | transparent: '#00000000',
23 |
24 | gradient: 'linear-gradient(112deg, $blue100 -25%, $pink500 -10%, $purple300 90%)',
25 | link: '#5E1DAD',
26 |
27 | myColor: '#00000030'
28 |
29 | },
30 | space: {},
31 | fonts: {}
32 | }
33 | })
34 |
35 | function MyApp({ Component, pageProps }) {
36 |
37 | return(
38 |
95 |
96 | )
97 |
98 |
99 | }
100 |
101 | export default MyApp
102 |
--------------------------------------------------------------------------------
/Part3-NextJS-Market-WebFrontEnd/engine/NFTCollection.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "anonymous": false,
4 | "inputs": [
5 | {
6 | "indexed": true,
7 | "internalType": "address",
8 | "name": "owner",
9 | "type": "address"
10 | },
11 | {
12 | "indexed": true,
13 | "internalType": "address",
14 | "name": "approved",
15 | "type": "address"
16 | },
17 | {
18 | "indexed": true,
19 | "internalType": "uint256",
20 | "name": "tokenId",
21 | "type": "uint256"
22 | }
23 | ],
24 | "name": "Approval",
25 | "type": "event"
26 | },
27 | {
28 | "anonymous": false,
29 | "inputs": [
30 | {
31 | "indexed": true,
32 | "internalType": "address",
33 | "name": "owner",
34 | "type": "address"
35 | },
36 | {
37 | "indexed": true,
38 | "internalType": "address",
39 | "name": "operator",
40 | "type": "address"
41 | },
42 | {
43 | "indexed": false,
44 | "internalType": "bool",
45 | "name": "approved",
46 | "type": "bool"
47 | }
48 | ],
49 | "name": "ApprovalForAll",
50 | "type": "event"
51 | },
52 | {
53 | "anonymous": false,
54 | "inputs": [
55 | {
56 | "indexed": true,
57 | "internalType": "address",
58 | "name": "previousOwner",
59 | "type": "address"
60 | },
61 | {
62 | "indexed": true,
63 | "internalType": "address",
64 | "name": "newOwner",
65 | "type": "address"
66 | }
67 | ],
68 | "name": "OwnershipTransferred",
69 | "type": "event"
70 | },
71 | {
72 | "anonymous": false,
73 | "inputs": [
74 | {
75 | "indexed": true,
76 | "internalType": "address",
77 | "name": "from",
78 | "type": "address"
79 | },
80 | {
81 | "indexed": true,
82 | "internalType": "address",
83 | "name": "to",
84 | "type": "address"
85 | },
86 | {
87 | "indexed": true,
88 | "internalType": "uint256",
89 | "name": "tokenId",
90 | "type": "uint256"
91 | }
92 | ],
93 | "name": "Transfer",
94 | "type": "event"
95 | },
96 | {
97 | "inputs": [
98 | {
99 | "internalType": "contract IERC20",
100 | "name": "_paytoken",
101 | "type": "address"
102 | },
103 | {
104 | "internalType": "uint256",
105 | "name": "_costvalue",
106 | "type": "uint256"
107 | }
108 | ],
109 | "name": "addCurrency",
110 | "outputs": [],
111 | "stateMutability": "nonpayable",
112 | "type": "function"
113 | },
114 | {
115 | "inputs": [
116 | {
117 | "internalType": "address",
118 | "name": "to",
119 | "type": "address"
120 | },
121 | {
122 | "internalType": "uint256",
123 | "name": "tokenId",
124 | "type": "uint256"
125 | }
126 | ],
127 | "name": "approve",
128 | "outputs": [],
129 | "stateMutability": "nonpayable",
130 | "type": "function"
131 | },
132 | {
133 | "inputs": [
134 | {
135 | "internalType": "address",
136 | "name": "_to",
137 | "type": "address"
138 | },
139 | {
140 | "internalType": "uint256",
141 | "name": "_mintAmount",
142 | "type": "uint256"
143 | }
144 | ],
145 | "name": "mint",
146 | "outputs": [],
147 | "stateMutability": "payable",
148 | "type": "function"
149 | },
150 | {
151 | "inputs": [
152 | {
153 | "internalType": "address",
154 | "name": "_to",
155 | "type": "address"
156 | },
157 | {
158 | "internalType": "uint256",
159 | "name": "_mintAmount",
160 | "type": "uint256"
161 | },
162 | {
163 | "internalType": "uint256",
164 | "name": "_pid",
165 | "type": "uint256"
166 | }
167 | ],
168 | "name": "mintpid",
169 | "outputs": [],
170 | "stateMutability": "payable",
171 | "type": "function"
172 | },
173 | {
174 | "inputs": [
175 | {
176 | "internalType": "bool",
177 | "name": "_state",
178 | "type": "bool"
179 | }
180 | ],
181 | "name": "pause",
182 | "outputs": [],
183 | "stateMutability": "nonpayable",
184 | "type": "function"
185 | },
186 | {
187 | "inputs": [],
188 | "name": "renounceOwnership",
189 | "outputs": [],
190 | "stateMutability": "nonpayable",
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": "string",
266 | "name": "_newBaseExtension",
267 | "type": "string"
268 | }
269 | ],
270 | "name": "setBaseExtension",
271 | "outputs": [],
272 | "stateMutability": "nonpayable",
273 | "type": "function"
274 | },
275 | {
276 | "inputs": [
277 | {
278 | "internalType": "string",
279 | "name": "_newBaseURI",
280 | "type": "string"
281 | }
282 | ],
283 | "name": "setBaseURI",
284 | "outputs": [],
285 | "stateMutability": "nonpayable",
286 | "type": "function"
287 | },
288 | {
289 | "inputs": [
290 | {
291 | "internalType": "uint256",
292 | "name": "_newmaxMintAmount",
293 | "type": "uint256"
294 | }
295 | ],
296 | "name": "setmaxMintAmount",
297 | "outputs": [],
298 | "stateMutability": "nonpayable",
299 | "type": "function"
300 | },
301 | {
302 | "inputs": [
303 | {
304 | "internalType": "address",
305 | "name": "from",
306 | "type": "address"
307 | },
308 | {
309 | "internalType": "address",
310 | "name": "to",
311 | "type": "address"
312 | },
313 | {
314 | "internalType": "uint256",
315 | "name": "tokenId",
316 | "type": "uint256"
317 | }
318 | ],
319 | "name": "transferFrom",
320 | "outputs": [],
321 | "stateMutability": "nonpayable",
322 | "type": "function"
323 | },
324 | {
325 | "inputs": [
326 | {
327 | "internalType": "address",
328 | "name": "newOwner",
329 | "type": "address"
330 | }
331 | ],
332 | "name": "transferOwnership",
333 | "outputs": [],
334 | "stateMutability": "nonpayable",
335 | "type": "function"
336 | },
337 | {
338 | "inputs": [],
339 | "name": "withdraw",
340 | "outputs": [],
341 | "stateMutability": "payable",
342 | "type": "function"
343 | },
344 | {
345 | "inputs": [
346 | {
347 | "internalType": "uint256",
348 | "name": "_pid",
349 | "type": "uint256"
350 | }
351 | ],
352 | "name": "withdrawcustom",
353 | "outputs": [],
354 | "stateMutability": "payable",
355 | "type": "function"
356 | },
357 | {
358 | "inputs": [],
359 | "stateMutability": "nonpayable",
360 | "type": "constructor"
361 | },
362 | {
363 | "inputs": [
364 | {
365 | "internalType": "uint256",
366 | "name": "",
367 | "type": "uint256"
368 | }
369 | ],
370 | "name": "AllowedCrypto",
371 | "outputs": [
372 | {
373 | "internalType": "contract IERC20",
374 | "name": "paytoken",
375 | "type": "address"
376 | },
377 | {
378 | "internalType": "uint256",
379 | "name": "costvalue",
380 | "type": "uint256"
381 | }
382 | ],
383 | "stateMutability": "view",
384 | "type": "function"
385 | },
386 | {
387 | "inputs": [
388 | {
389 | "internalType": "address",
390 | "name": "owner",
391 | "type": "address"
392 | }
393 | ],
394 | "name": "balanceOf",
395 | "outputs": [
396 | {
397 | "internalType": "uint256",
398 | "name": "",
399 | "type": "uint256"
400 | }
401 | ],
402 | "stateMutability": "view",
403 | "type": "function"
404 | },
405 | {
406 | "inputs": [],
407 | "name": "baseExtension",
408 | "outputs": [
409 | {
410 | "internalType": "string",
411 | "name": "",
412 | "type": "string"
413 | }
414 | ],
415 | "stateMutability": "view",
416 | "type": "function"
417 | },
418 | {
419 | "inputs": [],
420 | "name": "baseURI",
421 | "outputs": [
422 | {
423 | "internalType": "string",
424 | "name": "",
425 | "type": "string"
426 | }
427 | ],
428 | "stateMutability": "view",
429 | "type": "function"
430 | },
431 | {
432 | "inputs": [],
433 | "name": "cost",
434 | "outputs": [
435 | {
436 | "internalType": "uint256",
437 | "name": "",
438 | "type": "uint256"
439 | }
440 | ],
441 | "stateMutability": "view",
442 | "type": "function"
443 | },
444 | {
445 | "inputs": [
446 | {
447 | "internalType": "uint256",
448 | "name": "tokenId",
449 | "type": "uint256"
450 | }
451 | ],
452 | "name": "getApproved",
453 | "outputs": [
454 | {
455 | "internalType": "address",
456 | "name": "",
457 | "type": "address"
458 | }
459 | ],
460 | "stateMutability": "view",
461 | "type": "function"
462 | },
463 | {
464 | "inputs": [
465 | {
466 | "internalType": "uint256",
467 | "name": "_pid",
468 | "type": "uint256"
469 | }
470 | ],
471 | "name": "getCryptotoken",
472 | "outputs": [
473 | {
474 | "internalType": "contract IERC20",
475 | "name": "",
476 | "type": "address"
477 | }
478 | ],
479 | "stateMutability": "view",
480 | "type": "function"
481 | },
482 | {
483 | "inputs": [
484 | {
485 | "internalType": "uint256",
486 | "name": "_pid",
487 | "type": "uint256"
488 | }
489 | ],
490 | "name": "getNFTCost",
491 | "outputs": [
492 | {
493 | "internalType": "uint256",
494 | "name": "",
495 | "type": "uint256"
496 | }
497 | ],
498 | "stateMutability": "view",
499 | "type": "function"
500 | },
501 | {
502 | "inputs": [
503 | {
504 | "internalType": "address",
505 | "name": "owner",
506 | "type": "address"
507 | },
508 | {
509 | "internalType": "address",
510 | "name": "operator",
511 | "type": "address"
512 | }
513 | ],
514 | "name": "isApprovedForAll",
515 | "outputs": [
516 | {
517 | "internalType": "bool",
518 | "name": "",
519 | "type": "bool"
520 | }
521 | ],
522 | "stateMutability": "view",
523 | "type": "function"
524 | },
525 | {
526 | "inputs": [],
527 | "name": "maxMintAmount",
528 | "outputs": [
529 | {
530 | "internalType": "uint256",
531 | "name": "",
532 | "type": "uint256"
533 | }
534 | ],
535 | "stateMutability": "view",
536 | "type": "function"
537 | },
538 | {
539 | "inputs": [],
540 | "name": "maxSupply",
541 | "outputs": [
542 | {
543 | "internalType": "uint256",
544 | "name": "",
545 | "type": "uint256"
546 | }
547 | ],
548 | "stateMutability": "view",
549 | "type": "function"
550 | },
551 | {
552 | "inputs": [],
553 | "name": "name",
554 | "outputs": [
555 | {
556 | "internalType": "string",
557 | "name": "",
558 | "type": "string"
559 | }
560 | ],
561 | "stateMutability": "view",
562 | "type": "function"
563 | },
564 | {
565 | "inputs": [],
566 | "name": "owner",
567 | "outputs": [
568 | {
569 | "internalType": "address",
570 | "name": "",
571 | "type": "address"
572 | }
573 | ],
574 | "stateMutability": "view",
575 | "type": "function"
576 | },
577 | {
578 | "inputs": [
579 | {
580 | "internalType": "uint256",
581 | "name": "tokenId",
582 | "type": "uint256"
583 | }
584 | ],
585 | "name": "ownerOf",
586 | "outputs": [
587 | {
588 | "internalType": "address",
589 | "name": "",
590 | "type": "address"
591 | }
592 | ],
593 | "stateMutability": "view",
594 | "type": "function"
595 | },
596 | {
597 | "inputs": [],
598 | "name": "paused",
599 | "outputs": [
600 | {
601 | "internalType": "bool",
602 | "name": "",
603 | "type": "bool"
604 | }
605 | ],
606 | "stateMutability": "view",
607 | "type": "function"
608 | },
609 | {
610 | "inputs": [
611 | {
612 | "internalType": "bytes4",
613 | "name": "interfaceId",
614 | "type": "bytes4"
615 | }
616 | ],
617 | "name": "supportsInterface",
618 | "outputs": [
619 | {
620 | "internalType": "bool",
621 | "name": "",
622 | "type": "bool"
623 | }
624 | ],
625 | "stateMutability": "view",
626 | "type": "function"
627 | },
628 | {
629 | "inputs": [],
630 | "name": "symbol",
631 | "outputs": [
632 | {
633 | "internalType": "string",
634 | "name": "",
635 | "type": "string"
636 | }
637 | ],
638 | "stateMutability": "view",
639 | "type": "function"
640 | },
641 | {
642 | "inputs": [
643 | {
644 | "internalType": "uint256",
645 | "name": "index",
646 | "type": "uint256"
647 | }
648 | ],
649 | "name": "tokenByIndex",
650 | "outputs": [
651 | {
652 | "internalType": "uint256",
653 | "name": "",
654 | "type": "uint256"
655 | }
656 | ],
657 | "stateMutability": "view",
658 | "type": "function"
659 | },
660 | {
661 | "inputs": [
662 | {
663 | "internalType": "address",
664 | "name": "owner",
665 | "type": "address"
666 | },
667 | {
668 | "internalType": "uint256",
669 | "name": "index",
670 | "type": "uint256"
671 | }
672 | ],
673 | "name": "tokenOfOwnerByIndex",
674 | "outputs": [
675 | {
676 | "internalType": "uint256",
677 | "name": "",
678 | "type": "uint256"
679 | }
680 | ],
681 | "stateMutability": "view",
682 | "type": "function"
683 | },
684 | {
685 | "inputs": [
686 | {
687 | "internalType": "uint256",
688 | "name": "tokenId",
689 | "type": "uint256"
690 | }
691 | ],
692 | "name": "tokenURI",
693 | "outputs": [
694 | {
695 | "internalType": "string",
696 | "name": "",
697 | "type": "string"
698 | }
699 | ],
700 | "stateMutability": "view",
701 | "type": "function"
702 | },
703 | {
704 | "inputs": [],
705 | "name": "totalSupply",
706 | "outputs": [
707 | {
708 | "internalType": "uint256",
709 | "name": "",
710 | "type": "uint256"
711 | }
712 | ],
713 | "stateMutability": "view",
714 | "type": "function"
715 | },
716 | {
717 | "inputs": [
718 | {
719 | "internalType": "address",
720 | "name": "_owner",
721 | "type": "address"
722 | }
723 | ],
724 | "name": "walletOfOwner",
725 | "outputs": [
726 | {
727 | "internalType": "uint256[]",
728 | "name": "",
729 | "type": "uint256[]"
730 | }
731 | ],
732 | "stateMutability": "view",
733 | "type": "function"
734 | }
735 | ]
--------------------------------------------------------------------------------
/Part3-NextJS-Market-WebFrontEnd/engine/Resell.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "anonymous": false,
4 | "inputs": [
5 | {
6 | "indexed": true,
7 | "internalType": "uint256",
8 | "name": "itemId",
9 | "type": "uint256"
10 | },
11 | {
12 | "indexed": true,
13 | "internalType": "uint256",
14 | "name": "tokenId",
15 | "type": "uint256"
16 | },
17 | {
18 | "indexed": false,
19 | "internalType": "address",
20 | "name": "seller",
21 | "type": "address"
22 | },
23 | {
24 | "indexed": false,
25 | "internalType": "address",
26 | "name": "owner",
27 | "type": "address"
28 | },
29 | {
30 | "indexed": false,
31 | "internalType": "uint256",
32 | "name": "price",
33 | "type": "uint256"
34 | },
35 | {
36 | "indexed": false,
37 | "internalType": "bool",
38 | "name": "sold",
39 | "type": "bool"
40 | }
41 | ],
42 | "name": "NFTListCreated",
43 | "type": "event"
44 | },
45 | {
46 | "inputs": [
47 | {
48 | "internalType": "uint256",
49 | "name": "itemId",
50 | "type": "uint256"
51 | }
52 | ],
53 | "name": "buyNft",
54 | "outputs": [],
55 | "stateMutability": "payable",
56 | "type": "function"
57 | },
58 | {
59 | "inputs": [
60 | {
61 | "internalType": "uint256",
62 | "name": "tokenId",
63 | "type": "uint256"
64 | },
65 | {
66 | "internalType": "uint256",
67 | "name": "price",
68 | "type": "uint256"
69 | }
70 | ],
71 | "name": "listSale",
72 | "outputs": [],
73 | "stateMutability": "payable",
74 | "type": "function"
75 | },
76 | {
77 | "inputs": [
78 | {
79 | "internalType": "contract ERC721Enumerable",
80 | "name": "_nft",
81 | "type": "address"
82 | }
83 | ],
84 | "stateMutability": "nonpayable",
85 | "type": "constructor"
86 | },
87 | {
88 | "inputs": [],
89 | "name": "getListingFee",
90 | "outputs": [
91 | {
92 | "internalType": "uint256",
93 | "name": "",
94 | "type": "uint256"
95 | }
96 | ],
97 | "stateMutability": "view",
98 | "type": "function"
99 | },
100 | {
101 | "inputs": [],
102 | "name": "nftListings",
103 | "outputs": [
104 | {
105 | "components": [
106 | {
107 | "internalType": "uint256",
108 | "name": "itemId",
109 | "type": "uint256"
110 | },
111 | {
112 | "internalType": "uint256",
113 | "name": "tokenId",
114 | "type": "uint256"
115 | },
116 | {
117 | "internalType": "address payable",
118 | "name": "seller",
119 | "type": "address"
120 | },
121 | {
122 | "internalType": "address payable",
123 | "name": "owner",
124 | "type": "address"
125 | },
126 | {
127 | "internalType": "uint256",
128 | "name": "price",
129 | "type": "uint256"
130 | },
131 | {
132 | "internalType": "bool",
133 | "name": "sold",
134 | "type": "bool"
135 | }
136 | ],
137 | "internalType": "struct NFTMarketResell.List[]",
138 | "name": "",
139 | "type": "tuple[]"
140 | }
141 | ],
142 | "stateMutability": "view",
143 | "type": "function"
144 | },
145 | {
146 | "inputs": [
147 | {
148 | "internalType": "address",
149 | "name": "",
150 | "type": "address"
151 | },
152 | {
153 | "internalType": "address",
154 | "name": "from",
155 | "type": "address"
156 | },
157 | {
158 | "internalType": "uint256",
159 | "name": "",
160 | "type": "uint256"
161 | },
162 | {
163 | "internalType": "bytes",
164 | "name": "",
165 | "type": "bytes"
166 | }
167 | ],
168 | "name": "onERC721Received",
169 | "outputs": [
170 | {
171 | "internalType": "bytes4",
172 | "name": "",
173 | "type": "bytes4"
174 | }
175 | ],
176 | "stateMutability": "pure",
177 | "type": "function"
178 | },
179 | {
180 | "inputs": [
181 | {
182 | "internalType": "uint256",
183 | "name": "",
184 | "type": "uint256"
185 | }
186 | ],
187 | "name": "vaultItems",
188 | "outputs": [
189 | {
190 | "internalType": "uint256",
191 | "name": "itemId",
192 | "type": "uint256"
193 | },
194 | {
195 | "internalType": "uint256",
196 | "name": "tokenId",
197 | "type": "uint256"
198 | },
199 | {
200 | "internalType": "address payable",
201 | "name": "seller",
202 | "type": "address"
203 | },
204 | {
205 | "internalType": "address payable",
206 | "name": "owner",
207 | "type": "address"
208 | },
209 | {
210 | "internalType": "uint256",
211 | "name": "price",
212 | "type": "uint256"
213 | },
214 | {
215 | "internalType": "bool",
216 | "name": "sold",
217 | "type": "bool"
218 | }
219 | ],
220 | "stateMutability": "view",
221 | "type": "function"
222 | }
223 | ]
--------------------------------------------------------------------------------
/Part3-NextJS-Market-WebFrontEnd/engine/configuration.js:
--------------------------------------------------------------------------------
1 | /*
2 | ___ ___ _ _ ___ _____ __ __ _ _
3 | _ _ |_ )| \ | \| || __||_ _| | \/ | __ _ _ _ | |__ ___ | |_
4 | | ' \ / / | |) | | .` || _| | | | |\/| |/ _` || '_|| / // -_)| _|
5 | |_||_|/___||___/ |_|\_||_| |_| |_| |_|\__,_||_| |_\_\\___| \__|
6 |
7 | Update values accordingly
8 | xxnft is the NFT SmartContract Address
9 | xxmarket is the NFT MarketPlace Address
10 | xxresell is the NFT MarketResell Address
11 | xxnftcol is the already create NFT Collection Address
12 | */
13 |
14 | /*
15 | Private Key Encryption
16 | Replace ethraw with your private key "0xPRIVATEKEY" (Ethereum and other EVM)
17 | Replace hhraw with your private key "0xPRIVATEKEY" (Hardhat)
18 | */
19 |
20 | import SimpleCrypto from "simple-crypto-js"
21 | const cipherKey = "#ffg3$dvcv4rtkljjkh38dfkhhjgt"
22 | const ethraw = "0x8207b7bbf486039b455923a402560ed041ad4b7243e9f329d6e415c00aaa9ef2";
23 | const hhraw = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80";
24 | export const simpleCrypto = new SimpleCrypto(cipherKey)
25 | export const cipherEth = simpleCrypto.encrypt(ethraw)
26 | export const cipherHH = simpleCrypto.encrypt(hhraw)
27 |
28 | /*
29 | HardHat Testnet
30 | */
31 |
32 | export var hhresell = "0xCd55135cC103D7568056a828100D96603380DDbE";
33 | export var hhnftcol = "0x45A755B058492558351f188e4362F0546Bc3d140";
34 | var hhrpc = "http://localhost:8545";
35 |
36 | /*
37 | Global Parameters
38 | */
39 | export var mainnet = hhrpc
--------------------------------------------------------------------------------
/Part3-NextJS-Market-WebFrontEnd/index.js:
--------------------------------------------------------------------------------
1 | import Head from 'next/head'
2 | import Image from 'next/image'
3 | import styles from '../styles/Home.module.css'
4 |
5 | export default function Home() {
6 | return (
7 |
8 | )
9 | }
10 |
--------------------------------------------------------------------------------
/Part3-NextJS-Market-WebFrontEnd/portal.js:
--------------------------------------------------------------------------------
1 | import { ethers } from 'ethers';
2 | import { useState, useEffect } from 'react';
3 | import Web3Modal from "web3modal";
4 | import { useRouter } from 'next/router';
5 | import Resell from '../engine/Resell.json';
6 | import NFTCollection from '../engine/NFTCollection.json';
7 | import { Card, Button, Input, Col, Row, Spacer, Container, Text, Grid } from '@nextui-org/react';
8 | import axios from 'axios';
9 | import 'sf-font';
10 | import Web3 from 'web3';
11 | import { hhresell, hhnftcol, mainnet, cipherHH, simpleCrypto } from '../engine/configuration';
12 |
13 |
14 | export default function Sell() {
15 | const [user, getUser] = useState([])
16 | const [resalePrice, updateresalePrice] = useState({ price: ''})
17 | const [nfts, setNfts] = useState([])
18 | const [loadingState, setLoadingState] = useState('not-loaded')
19 | useEffect(() => {
20 | connectUser();
21 | getWalletNFTs()
22 | }, [setNfts,getUser])
23 | const router = useRouter()
24 |
25 | async function connectUser() {
26 | if (window.ethereum) {
27 | var web3 = new Web3(window.ethereum);
28 | await window.ethereum.send('eth_requestAccounts');
29 | var accounts = await web3.eth.getAccounts();
30 | var account = accounts[0];
31 | }
32 | getUser(account)
33 | }
34 |
35 | async function getWalletNFTs() {
36 | const provider = new ethers.providers.JsonRpcProvider(mainnet)
37 | const key = simpleCrypto.decrypt(cipherHH)
38 | const wallet = new ethers.Wallet(key, provider);
39 | const contract = new ethers.Contract(hhnftcol, NFTCollection, wallet);
40 | const itemArray = [];
41 | contract.totalSupply().then(result => {
42 | let totalSup = parseInt(result, 16)
43 | for (let i = 0; i < totalSup; i++) {
44 | var token = i + 1
45 | const owner = contract.ownerOf(token).catch(function (error) {
46 | console.log("tokens filtered");
47 | });
48 | const rawUri = contract.tokenURI(token).catch(function (error) {
49 | console.log("tokens filtered");
50 | });
51 | const Uri = Promise.resolve(rawUri)
52 | const getUri = Uri.then(value => {
53 | let str = value
54 | let cleanUri = str.replace('ipfs://', 'https://ipfs.io/ipfs/')
55 | console.log(cleanUri)
56 | let metadata = axios.get(cleanUri).catch(function (error) {
57 | console.log(error.toJSON());
58 | });
59 | return metadata;
60 | })
61 | getUri.then(value => {
62 | let rawImg = value.data.image
63 | var name = value.data.name
64 | var desc = value.data.description
65 | let image = rawImg.replace('ipfs://', 'https://ipfs.io/ipfs/')
66 | Promise.resolve(owner).then(value => {
67 | let ownerW = value;
68 | let meta = {
69 | name: name,
70 | img: image,
71 | tokenId: token,
72 | wallet: ownerW,
73 | desc,
74 | }
75 | console.log(meta)
76 | itemArray.push(meta)
77 | })
78 | })
79 | }
80 | })
81 | await new Promise(r => setTimeout(r, 3000));
82 | setNfts(itemArray)
83 | setLoadingState('loaded');
84 | }
85 |
86 | if (loadingState === 'loaded' && !nfts.length)
87 | return (
88 |
89 |
90 |
91 | No NFT's Found, Connect Wallet
92 |
93 |
94 |
95 |
96 | )
97 | return (
98 |
99 |
100 |
101 |
102 | NFT's in Wallet {user}
103 |
104 | Refresh Wallet
105 | Refresh NFTs
106 |
107 |
108 |
109 |
110 | {nfts.map((nft, i) => {
111 | var owner = user
112 | if (owner.indexOf(nft.wallet) !== -1) {
113 | async function executeRelist() {
114 | const { price } = resalePrice
115 | if (!price) return
116 | try {
117 | relistNFT()
118 | } catch (error) {
119 | console.log('Transaction Failed', error)
120 | }
121 | }
122 | async function relistNFT() {
123 | const web3Modal = new Web3Modal()
124 | const connection = await web3Modal.connect()
125 | const provider = new ethers.providers.Web3Provider(connection)
126 | const signer = provider.getSigner()
127 | const price = ethers.utils.parseUnits(resalePrice.price, 'ether')
128 | const contractnft = new ethers.Contract(hhnftcol, NFTCollection, signer);
129 | await contractnft.setApprovalForAll(hhresell, true);
130 | let contract = new ethers.Contract(hhresell, Resell, signer)
131 | let listingFee = await contract.getListingFee()
132 | listingFee = listingFee.toString()
133 | let transaction = await contract.listSale(nft.tokenId, price, { value: listingFee })
134 | await transaction.wait()
135 | router.push('/')
136 | }
137 | return (
138 |
139 |
140 |
141 |
142 |
143 | Owned by You
144 | {nft.name} Token-{nft.tokenId}
145 | {nft.desc}
146 | updateresalePrice({ ...resalePrice, price: e.target.value })}
151 | />
152 | Relist for Sale
153 |
154 |
155 |
156 |
157 | )
158 | }})}
159 |
160 |
161 |
162 | )
163 | }
--------------------------------------------------------------------------------
/Part4-RelistNFT-Buy-Sell/_app.js:
--------------------------------------------------------------------------------
1 | import { createTheme, NextUIProvider } from "@nextui-org/react";
2 | import 'sf-font';
3 | import Link from 'next/link'
4 | import { Spacer, Button, Col, Row, Container, Dropdown, Text } from '@nextui-org/react';
5 | import react from "react";
6 | import Footer from './footer';
7 |
8 | const theme = createTheme({
9 | type: "dark",
10 | theme: {
11 | fontFamily:'SF Pro Display',
12 | colors: {
13 | primaryLight: '$blue200',
14 | primaryLightHover: '$blue300',
15 | primaryLightActive: '$blue400',
16 | primaryLightContrast: '$blue600',
17 | primary: '$purple500',
18 | primaryBorder: '$blue500',
19 | primaryBorderHover: '$blue600',
20 | primarySolidHover: '$blue700',
21 | primarySolidContrast: '$white',
22 | primaryShadow: '$white500',
23 | transparent: '#00000000',
24 |
25 | gradient: 'linear-gradient(112deg, $blue100 -25%, $pink500 -10%, $purple300 90%)',
26 | link: '#5E1DAD',
27 |
28 | myColor: '#00000030'
29 |
30 | },
31 | space: {},
32 | fonts: {}
33 | }
34 | })
35 |
36 | function MyApp({ Component, pageProps }) {
37 |
38 | return(
39 |
99 |
100 | )
101 |
102 |
103 | }
104 |
105 | export default MyApp
106 |
--------------------------------------------------------------------------------
/Part4-RelistNFT-Buy-Sell/engine/NFTCollection.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "anonymous": false,
4 | "inputs": [
5 | {
6 | "indexed": true,
7 | "internalType": "address",
8 | "name": "owner",
9 | "type": "address"
10 | },
11 | {
12 | "indexed": true,
13 | "internalType": "address",
14 | "name": "approved",
15 | "type": "address"
16 | },
17 | {
18 | "indexed": true,
19 | "internalType": "uint256",
20 | "name": "tokenId",
21 | "type": "uint256"
22 | }
23 | ],
24 | "name": "Approval",
25 | "type": "event"
26 | },
27 | {
28 | "anonymous": false,
29 | "inputs": [
30 | {
31 | "indexed": true,
32 | "internalType": "address",
33 | "name": "owner",
34 | "type": "address"
35 | },
36 | {
37 | "indexed": true,
38 | "internalType": "address",
39 | "name": "operator",
40 | "type": "address"
41 | },
42 | {
43 | "indexed": false,
44 | "internalType": "bool",
45 | "name": "approved",
46 | "type": "bool"
47 | }
48 | ],
49 | "name": "ApprovalForAll",
50 | "type": "event"
51 | },
52 | {
53 | "anonymous": false,
54 | "inputs": [
55 | {
56 | "indexed": true,
57 | "internalType": "address",
58 | "name": "previousOwner",
59 | "type": "address"
60 | },
61 | {
62 | "indexed": true,
63 | "internalType": "address",
64 | "name": "newOwner",
65 | "type": "address"
66 | }
67 | ],
68 | "name": "OwnershipTransferred",
69 | "type": "event"
70 | },
71 | {
72 | "anonymous": false,
73 | "inputs": [
74 | {
75 | "indexed": true,
76 | "internalType": "address",
77 | "name": "from",
78 | "type": "address"
79 | },
80 | {
81 | "indexed": true,
82 | "internalType": "address",
83 | "name": "to",
84 | "type": "address"
85 | },
86 | {
87 | "indexed": true,
88 | "internalType": "uint256",
89 | "name": "tokenId",
90 | "type": "uint256"
91 | }
92 | ],
93 | "name": "Transfer",
94 | "type": "event"
95 | },
96 | {
97 | "inputs": [
98 | {
99 | "internalType": "contract IERC20",
100 | "name": "_paytoken",
101 | "type": "address"
102 | },
103 | {
104 | "internalType": "uint256",
105 | "name": "_costvalue",
106 | "type": "uint256"
107 | }
108 | ],
109 | "name": "addCurrency",
110 | "outputs": [],
111 | "stateMutability": "nonpayable",
112 | "type": "function"
113 | },
114 | {
115 | "inputs": [
116 | {
117 | "internalType": "address",
118 | "name": "to",
119 | "type": "address"
120 | },
121 | {
122 | "internalType": "uint256",
123 | "name": "tokenId",
124 | "type": "uint256"
125 | }
126 | ],
127 | "name": "approve",
128 | "outputs": [],
129 | "stateMutability": "nonpayable",
130 | "type": "function"
131 | },
132 | {
133 | "inputs": [
134 | {
135 | "internalType": "address",
136 | "name": "_to",
137 | "type": "address"
138 | },
139 | {
140 | "internalType": "uint256",
141 | "name": "_mintAmount",
142 | "type": "uint256"
143 | }
144 | ],
145 | "name": "mint",
146 | "outputs": [],
147 | "stateMutability": "payable",
148 | "type": "function"
149 | },
150 | {
151 | "inputs": [
152 | {
153 | "internalType": "address",
154 | "name": "_to",
155 | "type": "address"
156 | },
157 | {
158 | "internalType": "uint256",
159 | "name": "_mintAmount",
160 | "type": "uint256"
161 | },
162 | {
163 | "internalType": "uint256",
164 | "name": "_pid",
165 | "type": "uint256"
166 | }
167 | ],
168 | "name": "mintpid",
169 | "outputs": [],
170 | "stateMutability": "payable",
171 | "type": "function"
172 | },
173 | {
174 | "inputs": [
175 | {
176 | "internalType": "bool",
177 | "name": "_state",
178 | "type": "bool"
179 | }
180 | ],
181 | "name": "pause",
182 | "outputs": [],
183 | "stateMutability": "nonpayable",
184 | "type": "function"
185 | },
186 | {
187 | "inputs": [],
188 | "name": "renounceOwnership",
189 | "outputs": [],
190 | "stateMutability": "nonpayable",
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": "string",
266 | "name": "_newBaseExtension",
267 | "type": "string"
268 | }
269 | ],
270 | "name": "setBaseExtension",
271 | "outputs": [],
272 | "stateMutability": "nonpayable",
273 | "type": "function"
274 | },
275 | {
276 | "inputs": [
277 | {
278 | "internalType": "string",
279 | "name": "_newBaseURI",
280 | "type": "string"
281 | }
282 | ],
283 | "name": "setBaseURI",
284 | "outputs": [],
285 | "stateMutability": "nonpayable",
286 | "type": "function"
287 | },
288 | {
289 | "inputs": [
290 | {
291 | "internalType": "uint256",
292 | "name": "_newmaxMintAmount",
293 | "type": "uint256"
294 | }
295 | ],
296 | "name": "setmaxMintAmount",
297 | "outputs": [],
298 | "stateMutability": "nonpayable",
299 | "type": "function"
300 | },
301 | {
302 | "inputs": [
303 | {
304 | "internalType": "address",
305 | "name": "from",
306 | "type": "address"
307 | },
308 | {
309 | "internalType": "address",
310 | "name": "to",
311 | "type": "address"
312 | },
313 | {
314 | "internalType": "uint256",
315 | "name": "tokenId",
316 | "type": "uint256"
317 | }
318 | ],
319 | "name": "transferFrom",
320 | "outputs": [],
321 | "stateMutability": "nonpayable",
322 | "type": "function"
323 | },
324 | {
325 | "inputs": [
326 | {
327 | "internalType": "address",
328 | "name": "newOwner",
329 | "type": "address"
330 | }
331 | ],
332 | "name": "transferOwnership",
333 | "outputs": [],
334 | "stateMutability": "nonpayable",
335 | "type": "function"
336 | },
337 | {
338 | "inputs": [],
339 | "name": "withdraw",
340 | "outputs": [],
341 | "stateMutability": "payable",
342 | "type": "function"
343 | },
344 | {
345 | "inputs": [
346 | {
347 | "internalType": "uint256",
348 | "name": "_pid",
349 | "type": "uint256"
350 | }
351 | ],
352 | "name": "withdrawcustom",
353 | "outputs": [],
354 | "stateMutability": "payable",
355 | "type": "function"
356 | },
357 | {
358 | "inputs": [],
359 | "stateMutability": "nonpayable",
360 | "type": "constructor"
361 | },
362 | {
363 | "inputs": [
364 | {
365 | "internalType": "uint256",
366 | "name": "",
367 | "type": "uint256"
368 | }
369 | ],
370 | "name": "AllowedCrypto",
371 | "outputs": [
372 | {
373 | "internalType": "contract IERC20",
374 | "name": "paytoken",
375 | "type": "address"
376 | },
377 | {
378 | "internalType": "uint256",
379 | "name": "costvalue",
380 | "type": "uint256"
381 | }
382 | ],
383 | "stateMutability": "view",
384 | "type": "function"
385 | },
386 | {
387 | "inputs": [
388 | {
389 | "internalType": "address",
390 | "name": "owner",
391 | "type": "address"
392 | }
393 | ],
394 | "name": "balanceOf",
395 | "outputs": [
396 | {
397 | "internalType": "uint256",
398 | "name": "",
399 | "type": "uint256"
400 | }
401 | ],
402 | "stateMutability": "view",
403 | "type": "function"
404 | },
405 | {
406 | "inputs": [],
407 | "name": "baseExtension",
408 | "outputs": [
409 | {
410 | "internalType": "string",
411 | "name": "",
412 | "type": "string"
413 | }
414 | ],
415 | "stateMutability": "view",
416 | "type": "function"
417 | },
418 | {
419 | "inputs": [],
420 | "name": "baseURI",
421 | "outputs": [
422 | {
423 | "internalType": "string",
424 | "name": "",
425 | "type": "string"
426 | }
427 | ],
428 | "stateMutability": "view",
429 | "type": "function"
430 | },
431 | {
432 | "inputs": [],
433 | "name": "cost",
434 | "outputs": [
435 | {
436 | "internalType": "uint256",
437 | "name": "",
438 | "type": "uint256"
439 | }
440 | ],
441 | "stateMutability": "view",
442 | "type": "function"
443 | },
444 | {
445 | "inputs": [
446 | {
447 | "internalType": "uint256",
448 | "name": "tokenId",
449 | "type": "uint256"
450 | }
451 | ],
452 | "name": "getApproved",
453 | "outputs": [
454 | {
455 | "internalType": "address",
456 | "name": "",
457 | "type": "address"
458 | }
459 | ],
460 | "stateMutability": "view",
461 | "type": "function"
462 | },
463 | {
464 | "inputs": [
465 | {
466 | "internalType": "uint256",
467 | "name": "_pid",
468 | "type": "uint256"
469 | }
470 | ],
471 | "name": "getCryptotoken",
472 | "outputs": [
473 | {
474 | "internalType": "contract IERC20",
475 | "name": "",
476 | "type": "address"
477 | }
478 | ],
479 | "stateMutability": "view",
480 | "type": "function"
481 | },
482 | {
483 | "inputs": [
484 | {
485 | "internalType": "uint256",
486 | "name": "_pid",
487 | "type": "uint256"
488 | }
489 | ],
490 | "name": "getNFTCost",
491 | "outputs": [
492 | {
493 | "internalType": "uint256",
494 | "name": "",
495 | "type": "uint256"
496 | }
497 | ],
498 | "stateMutability": "view",
499 | "type": "function"
500 | },
501 | {
502 | "inputs": [
503 | {
504 | "internalType": "address",
505 | "name": "owner",
506 | "type": "address"
507 | },
508 | {
509 | "internalType": "address",
510 | "name": "operator",
511 | "type": "address"
512 | }
513 | ],
514 | "name": "isApprovedForAll",
515 | "outputs": [
516 | {
517 | "internalType": "bool",
518 | "name": "",
519 | "type": "bool"
520 | }
521 | ],
522 | "stateMutability": "view",
523 | "type": "function"
524 | },
525 | {
526 | "inputs": [],
527 | "name": "maxMintAmount",
528 | "outputs": [
529 | {
530 | "internalType": "uint256",
531 | "name": "",
532 | "type": "uint256"
533 | }
534 | ],
535 | "stateMutability": "view",
536 | "type": "function"
537 | },
538 | {
539 | "inputs": [],
540 | "name": "maxSupply",
541 | "outputs": [
542 | {
543 | "internalType": "uint256",
544 | "name": "",
545 | "type": "uint256"
546 | }
547 | ],
548 | "stateMutability": "view",
549 | "type": "function"
550 | },
551 | {
552 | "inputs": [],
553 | "name": "name",
554 | "outputs": [
555 | {
556 | "internalType": "string",
557 | "name": "",
558 | "type": "string"
559 | }
560 | ],
561 | "stateMutability": "view",
562 | "type": "function"
563 | },
564 | {
565 | "inputs": [],
566 | "name": "owner",
567 | "outputs": [
568 | {
569 | "internalType": "address",
570 | "name": "",
571 | "type": "address"
572 | }
573 | ],
574 | "stateMutability": "view",
575 | "type": "function"
576 | },
577 | {
578 | "inputs": [
579 | {
580 | "internalType": "uint256",
581 | "name": "tokenId",
582 | "type": "uint256"
583 | }
584 | ],
585 | "name": "ownerOf",
586 | "outputs": [
587 | {
588 | "internalType": "address",
589 | "name": "",
590 | "type": "address"
591 | }
592 | ],
593 | "stateMutability": "view",
594 | "type": "function"
595 | },
596 | {
597 | "inputs": [],
598 | "name": "paused",
599 | "outputs": [
600 | {
601 | "internalType": "bool",
602 | "name": "",
603 | "type": "bool"
604 | }
605 | ],
606 | "stateMutability": "view",
607 | "type": "function"
608 | },
609 | {
610 | "inputs": [
611 | {
612 | "internalType": "bytes4",
613 | "name": "interfaceId",
614 | "type": "bytes4"
615 | }
616 | ],
617 | "name": "supportsInterface",
618 | "outputs": [
619 | {
620 | "internalType": "bool",
621 | "name": "",
622 | "type": "bool"
623 | }
624 | ],
625 | "stateMutability": "view",
626 | "type": "function"
627 | },
628 | {
629 | "inputs": [],
630 | "name": "symbol",
631 | "outputs": [
632 | {
633 | "internalType": "string",
634 | "name": "",
635 | "type": "string"
636 | }
637 | ],
638 | "stateMutability": "view",
639 | "type": "function"
640 | },
641 | {
642 | "inputs": [
643 | {
644 | "internalType": "uint256",
645 | "name": "index",
646 | "type": "uint256"
647 | }
648 | ],
649 | "name": "tokenByIndex",
650 | "outputs": [
651 | {
652 | "internalType": "uint256",
653 | "name": "",
654 | "type": "uint256"
655 | }
656 | ],
657 | "stateMutability": "view",
658 | "type": "function"
659 | },
660 | {
661 | "inputs": [
662 | {
663 | "internalType": "address",
664 | "name": "owner",
665 | "type": "address"
666 | },
667 | {
668 | "internalType": "uint256",
669 | "name": "index",
670 | "type": "uint256"
671 | }
672 | ],
673 | "name": "tokenOfOwnerByIndex",
674 | "outputs": [
675 | {
676 | "internalType": "uint256",
677 | "name": "",
678 | "type": "uint256"
679 | }
680 | ],
681 | "stateMutability": "view",
682 | "type": "function"
683 | },
684 | {
685 | "inputs": [
686 | {
687 | "internalType": "uint256",
688 | "name": "tokenId",
689 | "type": "uint256"
690 | }
691 | ],
692 | "name": "tokenURI",
693 | "outputs": [
694 | {
695 | "internalType": "string",
696 | "name": "",
697 | "type": "string"
698 | }
699 | ],
700 | "stateMutability": "view",
701 | "type": "function"
702 | },
703 | {
704 | "inputs": [],
705 | "name": "totalSupply",
706 | "outputs": [
707 | {
708 | "internalType": "uint256",
709 | "name": "",
710 | "type": "uint256"
711 | }
712 | ],
713 | "stateMutability": "view",
714 | "type": "function"
715 | },
716 | {
717 | "inputs": [
718 | {
719 | "internalType": "address",
720 | "name": "_owner",
721 | "type": "address"
722 | }
723 | ],
724 | "name": "walletOfOwner",
725 | "outputs": [
726 | {
727 | "internalType": "uint256[]",
728 | "name": "",
729 | "type": "uint256[]"
730 | }
731 | ],
732 | "stateMutability": "view",
733 | "type": "function"
734 | }
735 | ]
--------------------------------------------------------------------------------
/Part4-RelistNFT-Buy-Sell/engine/Resell.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "anonymous": false,
4 | "inputs": [
5 | {
6 | "indexed": true,
7 | "internalType": "uint256",
8 | "name": "tokenId",
9 | "type": "uint256"
10 | },
11 | {
12 | "indexed": false,
13 | "internalType": "address",
14 | "name": "seller",
15 | "type": "address"
16 | },
17 | {
18 | "indexed": false,
19 | "internalType": "address",
20 | "name": "owner",
21 | "type": "address"
22 | },
23 | {
24 | "indexed": false,
25 | "internalType": "uint256",
26 | "name": "price",
27 | "type": "uint256"
28 | },
29 | {
30 | "indexed": false,
31 | "internalType": "bool",
32 | "name": "sold",
33 | "type": "bool"
34 | }
35 | ],
36 | "name": "NFTListCreated",
37 | "type": "event"
38 | },
39 | {
40 | "inputs": [
41 | {
42 | "internalType": "uint256",
43 | "name": "tokenId",
44 | "type": "uint256"
45 | }
46 | ],
47 | "name": "buyNft",
48 | "outputs": [],
49 | "stateMutability": "payable",
50 | "type": "function"
51 | },
52 | {
53 | "inputs": [
54 | {
55 | "internalType": "uint256",
56 | "name": "tokenId",
57 | "type": "uint256"
58 | }
59 | ],
60 | "name": "cancelSale",
61 | "outputs": [],
62 | "stateMutability": "nonpayable",
63 | "type": "function"
64 | },
65 | {
66 | "inputs": [
67 | {
68 | "internalType": "uint256",
69 | "name": "tokenId",
70 | "type": "uint256"
71 | },
72 | {
73 | "internalType": "uint256",
74 | "name": "price",
75 | "type": "uint256"
76 | }
77 | ],
78 | "name": "listSale",
79 | "outputs": [],
80 | "stateMutability": "payable",
81 | "type": "function"
82 | },
83 | {
84 | "inputs": [
85 | {
86 | "internalType": "contract ERC721Enumerable",
87 | "name": "_nft",
88 | "type": "address"
89 | }
90 | ],
91 | "stateMutability": "nonpayable",
92 | "type": "constructor"
93 | },
94 | {
95 | "inputs": [],
96 | "name": "getListingFee",
97 | "outputs": [
98 | {
99 | "internalType": "uint256",
100 | "name": "",
101 | "type": "uint256"
102 | }
103 | ],
104 | "stateMutability": "view",
105 | "type": "function"
106 | },
107 | {
108 | "inputs": [
109 | {
110 | "internalType": "uint256",
111 | "name": "tokenId",
112 | "type": "uint256"
113 | }
114 | ],
115 | "name": "getPrice",
116 | "outputs": [
117 | {
118 | "internalType": "uint256",
119 | "name": "",
120 | "type": "uint256"
121 | }
122 | ],
123 | "stateMutability": "view",
124 | "type": "function"
125 | },
126 | {
127 | "inputs": [
128 | {
129 | "internalType": "address",
130 | "name": "",
131 | "type": "address"
132 | },
133 | {
134 | "internalType": "address",
135 | "name": "from",
136 | "type": "address"
137 | },
138 | {
139 | "internalType": "uint256",
140 | "name": "",
141 | "type": "uint256"
142 | },
143 | {
144 | "internalType": "bytes",
145 | "name": "",
146 | "type": "bytes"
147 | }
148 | ],
149 | "name": "onERC721Received",
150 | "outputs": [
151 | {
152 | "internalType": "bytes4",
153 | "name": "",
154 | "type": "bytes4"
155 | }
156 | ],
157 | "stateMutability": "pure",
158 | "type": "function"
159 | },
160 | {
161 | "inputs": [
162 | {
163 | "internalType": "uint256",
164 | "name": "",
165 | "type": "uint256"
166 | }
167 | ],
168 | "name": "vaultItems",
169 | "outputs": [
170 | {
171 | "internalType": "uint256",
172 | "name": "tokenId",
173 | "type": "uint256"
174 | },
175 | {
176 | "internalType": "address payable",
177 | "name": "seller",
178 | "type": "address"
179 | },
180 | {
181 | "internalType": "address payable",
182 | "name": "owner",
183 | "type": "address"
184 | },
185 | {
186 | "internalType": "uint256",
187 | "name": "price",
188 | "type": "uint256"
189 | },
190 | {
191 | "internalType": "bool",
192 | "name": "sold",
193 | "type": "bool"
194 | }
195 | ],
196 | "stateMutability": "view",
197 | "type": "function"
198 | }
199 | ]
--------------------------------------------------------------------------------
/Part4-RelistNFT-Buy-Sell/engine/configuration.js:
--------------------------------------------------------------------------------
1 | /*
2 | ___ ___ _ _ ___ _____ __ __ _ _
3 | _ _ |_ )| \ | \| || __||_ _| | \/ | __ _ _ _ | |__ ___ | |_
4 | | ' \ / / | |) | | .` || _| | | | |\/| |/ _` || '_|| / // -_)| _|
5 | |_||_|/___||___/ |_|\_||_| |_| |_| |_|\__,_||_| |_\_\\___| \__|
6 |
7 | Update values accordingly
8 | */
9 |
10 | /*
11 | Private Key Encryption
12 | Replace hhraw with your contract
13 | owner wallet private key "0xPRIVATEKEY"
14 | */
15 |
16 | import SimpleCrypto from "simple-crypto-js"
17 | const cipherKey = "#ffg3$dvcv4rtkljjkh38dfkhhjgt"
18 | const hhraw = "0xREPLACEWITHPRIVATEKEY";
19 | export const simpleCrypto = new SimpleCrypto(cipherKey)
20 | export const cipherEth = simpleCrypto.encrypt(hhraw)
21 | export const cipherHH = simpleCrypto.encrypt(hhraw)
22 |
23 | /*
24 | MARKET AND NFT CONTRACTS
25 | */
26 | export var hhresell = "REPLACE WITH YOUR RESELL SMART CONTRACT";
27 | export var hhnftcol = "REPLACE WITH YOUR NFT COLLECTION CONTRACT";
28 |
29 | /*
30 | NETWORK RPC ADDRESSES, Choose one then
31 | change the value of "hhrpc" below.
32 | */
33 | var mumbai = 'https://matic-mumbai.chainstacklabs.com';
34 | var goerli = 'https://rpc.ankr.com/eth_goerli';
35 | var rinkeby = 'https://rpc.ankr.com/eth_rinkeby';
36 |
37 | /*
38 | CHANGE THIS TO YOUR PREFERRED TESTNET
39 | */
40 | var hhrpc = goerli;
41 | /*
42 | Global Parameters
43 | */
44 | export var mainnet = hhrpc
45 |
46 | /*
47 | DON'T FORGET TO SAVE!
48 | */
--------------------------------------------------------------------------------
/Part4-RelistNFT-Buy-Sell/footer.js:
--------------------------------------------------------------------------------
1 | import 'sf-font';
2 | import { Text, Row, Spacer, Container, Col } from '@nextui-org/react';
3 |
4 | export default function Footer() {
5 |
6 | const footer1 = [
7 | {
8 | id: 1,
9 | img: "discord.png",
10 | url: "https://discord.com/"
11 | },
12 | {
13 | id: 2,
14 | img: "youtube.png",
15 | url: "https://www.youtube.com/"
16 | },
17 | {
18 | id: 3,
19 | img: "twitter.png",
20 | url: "https://twitter.com/"
21 | }
22 | ]
23 |
24 | const footer2 = [
25 | {
26 | id: 1,
27 | img: "bsc.png"
28 | },
29 | {
30 | id: 2,
31 | img: "polygonwhite.png"
32 | },
33 | {
34 | id: 3,
35 | img: "ethereumlogo.png"
36 | }
37 | ]
38 |
39 |
40 | return (
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | n2DMarket
50 |
51 | The blockchain agnostic marketplace. The token with endless posibilities. NFT's are more than just art. Its meant to change the way humans establish ownership of an asset beyond paper.
52 |
53 |
54 |
55 |
56 | Follow Us!
57 |
58 | {footer1.map((item, idx) => {
59 | return (
60 |
61 | );
62 | })}
63 |
64 |
65 |
66 | Integrations
67 |
68 | {footer2.map((item, idx) => {
69 | return (
70 |
71 | );
72 | })}
73 |
74 |
75 |
76 | Our Partners
77 |
82 |
83 |
84 |
85 | ©2022 N2DMarket, All Rights Reserved.
86 |
87 |
88 |
89 |
90 | );
91 |
92 | }
--------------------------------------------------------------------------------
/Part4-RelistNFT-Buy-Sell/hardhat.config.js:
--------------------------------------------------------------------------------
1 | require("@nomiclabs/hardhat-waffle");
2 |
3 | module.exports = {
4 | defaultNetwork: "hardhat",
5 | networks: {
6 | hardhat: {
7 | chainId: 31337,
8 | url: "http://node.a3b.io:8545",
9 | accounts: [hhprivKey]
10 | },
11 | mumbai: {
12 | chainId: 80001,
13 | url: "https://rpc-mumbai.matic.today",
14 | accounts: [ethprivKey]
15 | },
16 | polygon: {
17 | chainId: 137,
18 | url: "https://rpc-mainnet.maticvigil.com",
19 | accounts: [ethprivKey]
20 | },
21 | ethereum: {
22 | chainId: 1,
23 | url: "https://main-rpc.linkpool.io",
24 | accounts: [ethprivKey]
25 | },
26 | binance: {
27 | chainId: 57,
28 | url: "https://bscrpc.com",
29 | accounts: [ethprivKey]
30 | },
31 | bsctest: {
32 | chainId: 97,
33 | url: "https://data-seed-prebsc-1-s3.binance.org:8545",
34 | accounts: [ethprivKey]
35 | },
36 | kovan: {
37 | chainId: 42,
38 | url: "https://kovan.infura.io/v3/3cf2d8833a2143b795b7796087fff369",
39 | accounts: [ethprivKey]
40 | }
41 | },
42 | solidity: {
43 | version: "0.8.4",
44 | settings: {
45 | optimizer: {
46 | enabled: true,
47 | runs: 200
48 | }
49 | }
50 | }
51 | };
52 |
53 |
--------------------------------------------------------------------------------
/Part4-RelistNFT-Buy-Sell/index.js:
--------------------------------------------------------------------------------
1 | import { ethers } from 'ethers';
2 | import { useEffect, useState } from 'react';
3 | import axios from 'axios';
4 | import Web3Modal from "web3modal";
5 | import { useRouter } from 'next/router';
6 | import NFTCollection from '../engine/NFTCollection.json'
7 | import Resell from '../engine/Resell.json';
8 | import { Grid, Card, Text, Button, Row, Spacer, Container } from '@nextui-org/react';
9 | import { hhresell, hhnftcol, mainnet } from '../engine/configuration';
10 | import { cipherHH, simpleCrypto } from '../engine/configuration';
11 | import confetti from 'canvas-confetti';
12 | import 'sf-font';
13 | import Carousel from "react-multi-carousel";
14 | import "react-multi-carousel/lib/styles.css";
15 |
16 | export default function Home() {
17 | const [hhlist, hhResellNfts] = useState([])
18 | useEffect(() => {
19 | loadHardHatResell()
20 | }, [hhResellNfts])
21 |
22 | const handleConfetti = () => {
23 | confetti();
24 | };
25 | const router = useRouter()
26 |
27 | async function loadHardHatResell() {
28 | const provider = new ethers.providers.JsonRpcProvider(mainnet)
29 | const key = simpleCrypto.decrypt(cipherHH)
30 | const wallet = new ethers.Wallet(key, provider);
31 | const contract = new ethers.Contract(hhnftcol, NFTCollection, wallet);
32 | const market = new ethers.Contract(hhresell, Resell, wallet);
33 | const itemArray = [];
34 | contract.totalSupply().then(result => {
35 | for (let i = 0; i < result; i++) {
36 | var token = i + 1
37 | var owner = contract.ownerOf(token)
38 | var getOwner = Promise.resolve(owner)
39 | getOwner.then(address => {
40 | if (address == hhresell) {
41 | const rawUri = contract.tokenURI(token)
42 | const Uri = Promise.resolve(rawUri)
43 | const getUri = Uri.then(value => {
44 | let str = value
45 | let cleanUri = str.replace('ipfs://', 'https://ipfs.io/ipfs/')
46 | console.log(cleanUri)
47 | let metadata = axios.get(cleanUri).catch(function (error) {
48 | console.log(error.toJSON());
49 | });
50 | return metadata;
51 | })
52 | getUri.then(value => {
53 | let rawImg = value.data.image
54 | var name = value.data.name
55 | var desc = value.data.description
56 | let image = rawImg.replace('ipfs://', 'https://ipfs.io/ipfs/')
57 | const price = market.getPrice(token)
58 | Promise.resolve(price).then(_hex => {
59 | var salePrice = Number(_hex);
60 | var txPrice = salePrice.toString()
61 | Promise.resolve(owner).then(value => {
62 | let ownerW = value;
63 | let outPrice = ethers.utils.formatUnits(salePrice.toString(), 'ether')
64 | let meta = {
65 | name: name,
66 | img: image,
67 | cost: txPrice,
68 | val: outPrice,
69 | tokenId: token,
70 | wallet: ownerW,
71 | desc
72 | }
73 | console.log(meta)
74 | itemArray.push(meta)
75 | })
76 | })
77 | })
78 | }})
79 | }})
80 | await new Promise(r => setTimeout(r, 3000));
81 | hhResellNfts(itemArray)
82 | }
83 |
84 | const responsive = {
85 | desktop: {
86 | breakpoint: { max: 3000, min: 1024 },
87 | items: 1,
88 | slidesToSlide: 1
89 | },
90 | tablet: {
91 | breakpoint: { max: 1024, min: 464 },
92 | items: 2,
93 | slidesToSlide: 2
94 | },
95 | mobile: {
96 | breakpoint: { max: 464, min: 0 },
97 | items: 1,
98 | slidesToSlide: 1
99 | }
100 | };
101 |
102 | return (
103 |
104 |
105 |
106 |
107 | Top Collections
108 |
123 | {
124 | hhlist.map((nft, i) => (
125 |
126 |
127 |
128 | ))
129 | }
130 |
131 |
132 |
133 |
134 |
135 |
136 | Latest NFT's
137 |
138 |
139 | {
140 | hhlist.slice(0, 9).map((nft, id) => {
141 | async function buylistNft() {
142 | const web3Modal = new Web3Modal()
143 | const connection = await web3Modal.connect()
144 | const provider = new ethers.providers.Web3Provider(connection)
145 | const signer = provider.getSigner()
146 | const contract = new ethers.Contract(hhresell, Resell, signer)
147 | const transaction = await contract.buyNft(nft.tokenId, { value: nft.cost })
148 | await transaction.wait()
149 | router.push('/portal')
150 | }
151 | return (
152 |
153 |
154 | {nft.name} Token-{nft.tokenId}
162 |
163 |
167 |
168 |
169 |
170 | {nft.desc}
171 | {nft.val}
172 | handleConfetti(buylistNft(nft))}>Buy
173 |
174 |
175 |
176 |
177 | )
178 | })
179 | }
180 |
181 |
182 |
183 |
184 | )
185 | }
--------------------------------------------------------------------------------
/Part4-RelistNFT-Buy-Sell/portal.js:
--------------------------------------------------------------------------------
1 | import { ethers } from 'ethers';
2 | import { useState, useEffect } from 'react';
3 | import Web3Modal from "web3modal";
4 | import { useRouter } from 'next/router';
5 | import Resell from '../engine/Resell.json';
6 | import NFTCollection from '../engine/NFTCollection.json';
7 | import { Card, Button, Input, Col, Row, Spacer, Container, Text, Grid } from '@nextui-org/react';
8 | import axios from 'axios';
9 | import 'sf-font';
10 | import Web3 from 'web3';
11 | import { hhresell, hhnftcol, mainnet, cipherHH, simpleCrypto } from '../engine/configuration';
12 |
13 |
14 | export default function Sell() {
15 | const [user, getUser] = useState([])
16 | const [resalePrice, updateresalePrice] = useState({ price: ''})
17 | const [nfts, setNfts] = useState([])
18 | const [loadingState, setLoadingState] = useState('not-loaded')
19 | useEffect(() => {
20 | connectUser();
21 | getWalletNFTs()
22 | }, [setNfts,getUser])
23 | const router = useRouter()
24 |
25 | async function connectUser() {
26 | if (window.ethereum) {
27 | var web3 = new Web3(window.ethereum);
28 | await window.ethereum.send('eth_requestAccounts');
29 | var accounts = await web3.eth.getAccounts();
30 | var account = accounts[0];
31 | }
32 | getUser(account)
33 | }
34 |
35 | async function getWalletNFTs() {
36 | const provider = new ethers.providers.JsonRpcProvider(mainnet)
37 | const key = simpleCrypto.decrypt(cipherHH)
38 | const wallet = new ethers.Wallet(key, provider);
39 | const contract = new ethers.Contract(hhnftcol, NFTCollection, wallet);
40 | const itemArray = [];
41 | contract.totalSupply().then(result => {
42 | for (let i = 0; i < result; i++) {
43 | var token = i + 1
44 | const owner = contract.ownerOf(token).catch(function (error) {
45 | console.log("tokens filtered");
46 | });
47 | const rawUri = contract.tokenURI(token).catch(function (error) {
48 | console.log("tokens filtered");
49 | });
50 | const Uri = Promise.resolve(rawUri)
51 | const getUri = Uri.then(value => {
52 | var cleanUri = value.replace('ipfs://', 'https://ipfs.io/ipfs/')
53 | let metadata = axios.get(cleanUri).catch(function (error) {
54 | console.log(error.toJSON());
55 | });
56 | return metadata;
57 | })
58 | getUri.then(value => {
59 | let rawImg = value.data.image
60 | var name = value.data.name
61 | var desc = value.data.description
62 | let image = rawImg.replace('ipfs://', 'https://ipfs.io/ipfs/')
63 | Promise.resolve(owner).then(value => {
64 | let ownerW = value;
65 | let meta = {
66 | name: name,
67 | img: image,
68 | tokenId: token,
69 | wallet: ownerW,
70 | desc,
71 | }
72 | console.log(meta)
73 | itemArray.push(meta)
74 | })
75 | })
76 | }
77 | })
78 | await new Promise(r => setTimeout(r, 3000));
79 | setNfts(itemArray)
80 | setLoadingState('loaded');
81 | }
82 |
83 | if (loadingState === 'loaded' && !nfts.length)
84 | return (
85 |
86 |
87 |
88 | No NFT's Found, Connect Wallet
89 |
90 |
91 |
92 |
93 | )
94 | return (
95 |
96 |
97 |
98 |
99 | NFT's in Wallet {user}
100 |
101 | Refresh Wallet
102 | Refresh NFTs
103 |
104 |
105 |
106 |
107 | {nfts.map((nft, i) => {
108 | var owner = user
109 | if (owner.indexOf(nft.wallet) !== -1) {
110 | async function executeRelist() {
111 | const { price } = resalePrice
112 | if (!price) return
113 | try {
114 | relistNFT()
115 | } catch (error) {
116 | console.log('Transaction Failed', error)
117 | }
118 | }
119 | async function relistNFT() {
120 | const web3Modal = new Web3Modal()
121 | const connection = await web3Modal.connect()
122 | const provider = new ethers.providers.Web3Provider(connection)
123 | const signer = provider.getSigner()
124 | const price = ethers.utils.parseUnits(resalePrice.price, 'ether')
125 | const contractnft = new ethers.Contract(hhnftcol, NFTCollection, signer);
126 | await contractnft.setApprovalForAll(hhresell, true);
127 | let contract = new ethers.Contract(hhresell, Resell, signer)
128 | let listingFee = await contract.getListingFee()
129 | listingFee = listingFee.toString()
130 | let transaction = await contract.listSale(nft.tokenId, price, { value: listingFee })
131 | await transaction.wait()
132 | router.push('/')
133 | }
134 | return (
135 |
136 |
137 |
138 |
139 |
140 | Owned by You
141 | {nft.name} Token-{nft.tokenId}
142 | {nft.desc}
143 | updateresalePrice({ ...resalePrice, price: e.target.value })}
148 | />
149 | Relist for Sale
150 |
151 |
152 |
153 |
154 | )
155 | }})}
156 |
157 |
158 |
159 | )
160 | }
--------------------------------------------------------------------------------
/Part4-RelistNFT-Buy-Sell/public/bsc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/net2devcrypto/N2D-NFT-Marketplace/a8d9ada82ef143eb3df282c3d0c7f4cf0b5bf6af/Part4-RelistNFT-Buy-Sell/public/bsc.png
--------------------------------------------------------------------------------
/Part4-RelistNFT-Buy-Sell/public/chainagnostic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/net2devcrypto/N2D-NFT-Marketplace/a8d9ada82ef143eb3df282c3d0c7f4cf0b5bf6af/Part4-RelistNFT-Buy-Sell/public/chainagnostic.png
--------------------------------------------------------------------------------
/Part4-RelistNFT-Buy-Sell/public/discord.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/net2devcrypto/N2D-NFT-Marketplace/a8d9ada82ef143eb3df282c3d0c7f4cf0b5bf6af/Part4-RelistNFT-Buy-Sell/public/discord.png
--------------------------------------------------------------------------------
/Part4-RelistNFT-Buy-Sell/public/discordlogo.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/net2devcrypto/N2D-NFT-Marketplace/a8d9ada82ef143eb3df282c3d0c7f4cf0b5bf6af/Part4-RelistNFT-Buy-Sell/public/discordlogo.PNG
--------------------------------------------------------------------------------
/Part4-RelistNFT-Buy-Sell/public/ethereumlogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/net2devcrypto/N2D-NFT-Marketplace/a8d9ada82ef143eb3df282c3d0c7f4cf0b5bf6af/Part4-RelistNFT-Buy-Sell/public/ethereumlogo.png
--------------------------------------------------------------------------------
/Part4-RelistNFT-Buy-Sell/public/n2DMarket.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/net2devcrypto/N2D-NFT-Marketplace/a8d9ada82ef143eb3df282c3d0c7f4cf0b5bf6af/Part4-RelistNFT-Buy-Sell/public/n2DMarket.png
--------------------------------------------------------------------------------
/Part4-RelistNFT-Buy-Sell/public/n2dr-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/net2devcrypto/N2D-NFT-Marketplace/a8d9ada82ef143eb3df282c3d0c7f4cf0b5bf6af/Part4-RelistNFT-Buy-Sell/public/n2dr-logo.png
--------------------------------------------------------------------------------
/Part4-RelistNFT-Buy-Sell/public/polygonwhite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/net2devcrypto/N2D-NFT-Marketplace/a8d9ada82ef143eb3df282c3d0c7f4cf0b5bf6af/Part4-RelistNFT-Buy-Sell/public/polygonwhite.png
--------------------------------------------------------------------------------
/Part4-RelistNFT-Buy-Sell/public/twitter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/net2devcrypto/N2D-NFT-Marketplace/a8d9ada82ef143eb3df282c3d0c7f4cf0b5bf6af/Part4-RelistNFT-Buy-Sell/public/twitter.png
--------------------------------------------------------------------------------
/Part4-RelistNFT-Buy-Sell/public/web3logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/net2devcrypto/N2D-NFT-Marketplace/a8d9ada82ef143eb3df282c3d0c7f4cf0b5bf6af/Part4-RelistNFT-Buy-Sell/public/web3logo.png
--------------------------------------------------------------------------------
/Part4-RelistNFT-Buy-Sell/public/youtube.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/net2devcrypto/N2D-NFT-Marketplace/a8d9ada82ef143eb3df282c3d0c7f4cf0b5bf6af/Part4-RelistNFT-Buy-Sell/public/youtube.png
--------------------------------------------------------------------------------
/Part5-Create-and-Sell-NFT-App/Market.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "anonymous": false,
4 | "inputs": [
5 | {
6 | "indexed": true,
7 | "internalType": "uint256",
8 | "name": "itemId",
9 | "type": "uint256"
10 | },
11 | {
12 | "indexed": true,
13 | "internalType": "address",
14 | "name": "nftContract",
15 | "type": "address"
16 | },
17 | {
18 | "indexed": true,
19 | "internalType": "uint256",
20 | "name": "tokenId",
21 | "type": "uint256"
22 | },
23 | {
24 | "indexed": false,
25 | "internalType": "address",
26 | "name": "seller",
27 | "type": "address"
28 | },
29 | {
30 | "indexed": false,
31 | "internalType": "address",
32 | "name": "owner",
33 | "type": "address"
34 | },
35 | {
36 | "indexed": false,
37 | "internalType": "uint256",
38 | "name": "price",
39 | "type": "uint256"
40 | },
41 | {
42 | "indexed": false,
43 | "internalType": "bool",
44 | "name": "sold",
45 | "type": "bool"
46 | }
47 | ],
48 | "name": "VaultItemCreated",
49 | "type": "event"
50 | },
51 | {
52 | "inputs": [
53 | {
54 | "internalType": "address",
55 | "name": "nftContract",
56 | "type": "address"
57 | },
58 | {
59 | "internalType": "uint256",
60 | "name": "tokenId",
61 | "type": "uint256"
62 | },
63 | {
64 | "internalType": "uint256",
65 | "name": "price",
66 | "type": "uint256"
67 | }
68 | ],
69 | "name": "createVaultItem",
70 | "outputs": [],
71 | "stateMutability": "payable",
72 | "type": "function"
73 | },
74 | {
75 | "inputs": [
76 | {
77 | "internalType": "address",
78 | "name": "nftContract",
79 | "type": "address"
80 | },
81 | {
82 | "internalType": "uint256",
83 | "name": "itemId",
84 | "type": "uint256"
85 | }
86 | ],
87 | "name": "n2DMarketSale",
88 | "outputs": [],
89 | "stateMutability": "payable",
90 | "type": "function"
91 | },
92 | {
93 | "inputs": [],
94 | "stateMutability": "nonpayable",
95 | "type": "constructor"
96 | },
97 | {
98 | "inputs": [],
99 | "name": "getAvailableNft",
100 | "outputs": [
101 | {
102 | "components": [
103 | {
104 | "internalType": "uint256",
105 | "name": "itemId",
106 | "type": "uint256"
107 | },
108 | {
109 | "internalType": "address",
110 | "name": "nftContract",
111 | "type": "address"
112 | },
113 | {
114 | "internalType": "uint256",
115 | "name": "tokenId",
116 | "type": "uint256"
117 | },
118 | {
119 | "internalType": "address payable",
120 | "name": "seller",
121 | "type": "address"
122 | },
123 | {
124 | "internalType": "address payable",
125 | "name": "owner",
126 | "type": "address"
127 | },
128 | {
129 | "internalType": "uint256",
130 | "name": "price",
131 | "type": "uint256"
132 | },
133 | {
134 | "internalType": "bool",
135 | "name": "sold",
136 | "type": "bool"
137 | }
138 | ],
139 | "internalType": "struct n2DMarket.VaultItem[]",
140 | "name": "",
141 | "type": "tuple[]"
142 | }
143 | ],
144 | "stateMutability": "view",
145 | "type": "function"
146 | },
147 | {
148 | "inputs": [],
149 | "name": "getMyMarketNfts",
150 | "outputs": [
151 | {
152 | "components": [
153 | {
154 | "internalType": "uint256",
155 | "name": "itemId",
156 | "type": "uint256"
157 | },
158 | {
159 | "internalType": "address",
160 | "name": "nftContract",
161 | "type": "address"
162 | },
163 | {
164 | "internalType": "uint256",
165 | "name": "tokenId",
166 | "type": "uint256"
167 | },
168 | {
169 | "internalType": "address payable",
170 | "name": "seller",
171 | "type": "address"
172 | },
173 | {
174 | "internalType": "address payable",
175 | "name": "owner",
176 | "type": "address"
177 | },
178 | {
179 | "internalType": "uint256",
180 | "name": "price",
181 | "type": "uint256"
182 | },
183 | {
184 | "internalType": "bool",
185 | "name": "sold",
186 | "type": "bool"
187 | }
188 | ],
189 | "internalType": "struct n2DMarket.VaultItem[]",
190 | "name": "",
191 | "type": "tuple[]"
192 | }
193 | ],
194 | "stateMutability": "view",
195 | "type": "function"
196 | },
197 | {
198 | "inputs": [],
199 | "name": "getMyNft",
200 | "outputs": [
201 | {
202 | "components": [
203 | {
204 | "internalType": "uint256",
205 | "name": "itemId",
206 | "type": "uint256"
207 | },
208 | {
209 | "internalType": "address",
210 | "name": "nftContract",
211 | "type": "address"
212 | },
213 | {
214 | "internalType": "uint256",
215 | "name": "tokenId",
216 | "type": "uint256"
217 | },
218 | {
219 | "internalType": "address payable",
220 | "name": "seller",
221 | "type": "address"
222 | },
223 | {
224 | "internalType": "address payable",
225 | "name": "owner",
226 | "type": "address"
227 | },
228 | {
229 | "internalType": "uint256",
230 | "name": "price",
231 | "type": "uint256"
232 | },
233 | {
234 | "internalType": "bool",
235 | "name": "sold",
236 | "type": "bool"
237 | }
238 | ],
239 | "internalType": "struct n2DMarket.VaultItem[]",
240 | "name": "",
241 | "type": "tuple[]"
242 | }
243 | ],
244 | "stateMutability": "view",
245 | "type": "function"
246 | },
247 | {
248 | "inputs": [],
249 | "name": "listingFee",
250 | "outputs": [
251 | {
252 | "internalType": "uint256",
253 | "name": "",
254 | "type": "uint256"
255 | }
256 | ],
257 | "stateMutability": "view",
258 | "type": "function"
259 | }
260 | ]
--------------------------------------------------------------------------------
/Part5-Create-and-Sell-NFT-App/N2D-Market-CreateNFT-SmartContract.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT OR Apache-2.0
2 |
3 | /*
4 | N2D Marketplace Create NFT Smart Contract
5 |
6 | Follow/Subscribe Youtube, Github, IM, Tiktok
7 | for more amazing content!!
8 | @Net2Dev
9 | ███╗░░██╗███████╗████████╗██████╗░██████╗░███████╗██╗░░░██╗
10 | ████╗░██║██╔════╝╚══██╔══╝╚════██╗██╔══██╗██╔════╝██║░░░██║
11 | ██╔██╗██║█████╗░░░░░██║░░░░░███╔═╝██║░░██║█████╗░░╚██╗░██╔╝
12 | ██║╚████║██╔══╝░░░░░██║░░░██╔══╝░░██║░░██║██╔══╝░░░╚████╔╝░
13 | ██║░╚███║███████╗░░░██║░░░███████╗██████╔╝███████╗░░╚██╔╝░░
14 | ╚═╝░░╚══╝╚══════╝░░░╚═╝░░░╚══════╝╚═════╝░╚══════╝░░░╚═╝░░░
15 | THIS CONTRACT IS AVAILABLE FOR EDUCATIONAL
16 | PURPOSES ONLY. YOU ARE SOLELY REPONSIBLE
17 | FOR ITS USE. I AM NOT RESPONSIBLE FOR ANY
18 | OTHER USE. THIS IS TRAINING/EDUCATIONAL
19 | MATERIAL. ONLY USE IT IF YOU AGREE TO THE
20 | TERMS SPECIFIED ABOVE.
21 |
22 | Revision v2
23 |
24 | - Added minting fee balance withdraw function
25 |
26 | */
27 |
28 | pragma solidity ^0.8.4;
29 |
30 | import "@openzeppelin/contracts/utils/Counters.sol";
31 | import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
32 | import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
33 | import "@openzeppelin/contracts/access/Ownable.sol";
34 |
35 | contract N2DNFT is ERC721URIStorage, Ownable {
36 | using Counters for Counters.Counter;
37 | Counters.Counter public _tokenIds;
38 | address contractAddress;
39 | uint256 public cost = 0.0075 ether;
40 |
41 | constructor(address marketContract) ERC721("n2DMarket", "N2DM") {
42 | contractAddress = marketContract;
43 | }
44 |
45 | function createNFT(string memory tokenURI) public returns (uint) {
46 | _tokenIds.increment();
47 | uint256 newItemId = _tokenIds.current();
48 | _mint(msg.sender, newItemId);
49 | _setTokenURI(newItemId, tokenURI);
50 | setApprovalForAll(contractAddress, true);
51 | return newItemId;
52 | }
53 |
54 | function mintNFT(string memory tokenURI) public payable returns (uint) {
55 | require(msg.value == cost, "Need to send 0.075 ether!");
56 | _tokenIds.increment();
57 | uint256 newItemId = _tokenIds.current();
58 | _mint(msg.sender, newItemId);
59 | _setTokenURI(newItemId, tokenURI);
60 | setApprovalForAll(contractAddress, true);
61 | return newItemId;
62 | }
63 |
64 | function withdraw() public payable onlyOwner() {
65 | require(payable(msg.sender).send(address(this).balance));
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/Part5-Create-and-Sell-NFT-App/N2D-Market-SellCreatedNFT-SmartContract.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT LICENSE
2 |
3 | /*
4 | N2D Marketplace Sell Created NFT Smart Contract
5 |
6 | Follow/Subscribe Youtube, Github, IM, Tiktok
7 | for more amazing content!!
8 | @Net2Dev
9 | ███╗░░██╗███████╗████████╗██████╗░██████╗░███████╗██╗░░░██╗
10 | ████╗░██║██╔════╝╚══██╔══╝╚════██╗██╔══██╗██╔════╝██║░░░██║
11 | ██╔██╗██║█████╗░░░░░██║░░░░░███╔═╝██║░░██║█████╗░░╚██╗░██╔╝
12 | ██║╚████║██╔══╝░░░░░██║░░░██╔══╝░░██║░░██║██╔══╝░░░╚████╔╝░
13 | ██║░╚███║███████╗░░░██║░░░███████╗██████╔╝███████╗░░╚██╔╝░░
14 | ╚═╝░░╚══╝╚══════╝░░░╚═╝░░░╚══════╝╚═════╝░╚══════╝░░░╚═╝░░░
15 | THIS CONTRACT IS AVAILABLE FOR EDUCATIONAL
16 | PURPOSES ONLY. YOU ARE SOLELY REPONSIBLE
17 | FOR ITS USE. I AM NOT RESPONSIBLE FOR ANY
18 | OTHER USE. THIS IS TRAINING/EDUCATIONAL
19 | MATERIAL. ONLY USE IT IF YOU AGREE TO THE
20 | TERMS SPECIFIED ABOVE.
21 |
22 | Revision v2
23 |
24 | - Added listing and minting fee balance
25 | withdraw function.
26 | */
27 |
28 | pragma solidity ^0.8.4;
29 |
30 | import "@openzeppelin/contracts/utils/Counters.sol";
31 | import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
32 | import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
33 | import "@openzeppelin/contracts/access/Ownable.sol";
34 |
35 |
36 | contract n2DMarket is ReentrancyGuard, Ownable {
37 | using Counters for Counters.Counter;
38 | Counters.Counter private _itemIds;
39 | Counters.Counter private _itemsSold;
40 |
41 | address payable holder;
42 | uint256 listingFee = 0.0025 ether;
43 | uint256 mintingFee = 0.0075 ether;
44 |
45 | constructor() {
46 | holder = payable(msg.sender);
47 | }
48 |
49 | struct VaultItem {
50 | uint itemId;
51 | address nftContract;
52 | uint256 tokenId;
53 | address payable seller;
54 | address payable holder;
55 | uint256 price;
56 | bool sold;
57 | }
58 |
59 | mapping(uint256 => VaultItem) private idToVaultItem;
60 |
61 | event VaultItemCreated (
62 | uint indexed itemId,
63 | address indexed nftContract,
64 | uint256 indexed tokenId,
65 | address seller,
66 | address holder,
67 | uint256 price,
68 | bool sold
69 | );
70 |
71 | function getListingFee() public view returns (uint256) {
72 | return listingFee;
73 | }
74 |
75 | function createVaultItem(address nftContract,uint256 tokenId,uint256 price) public payable nonReentrant {
76 | require(price > 0, "Price cannot be zero");
77 | require(msg.value == listingFee, "Price cannot be listing fee");
78 | _itemIds.increment();
79 | uint256 itemId = _itemIds.current();
80 | idToVaultItem[itemId] = VaultItem(itemId,nftContract,tokenId,payable(msg.sender),payable(address(0)),price,false);
81 | IERC721(nftContract).transferFrom(msg.sender, address(this), tokenId);
82 | emit VaultItemCreated(itemId,nftContract,tokenId,msg.sender,address(0),price,false);}
83 |
84 | function n2DMarketSale(
85 | address nftContract,uint256 itemId) public payable nonReentrant {
86 | uint price = idToVaultItem[itemId].price;
87 | uint tokenId = idToVaultItem[itemId].tokenId;
88 | require(msg.value == price, "Not enough balance to complete transaction");
89 | idToVaultItem[itemId].seller.transfer(msg.value);
90 | IERC721(nftContract).transferFrom(address(this), msg.sender, tokenId);
91 | idToVaultItem[itemId].holder = payable(msg.sender);
92 | idToVaultItem[itemId].sold = true;
93 | _itemsSold.increment();
94 | payable(holder).transfer(listingFee);
95 | }
96 |
97 | function getAvailableNft() public view returns (VaultItem[] memory) {
98 | uint itemCount = _itemIds.current();
99 | uint unsoldItemCount = _itemIds.current() - _itemsSold.current();
100 | uint currentIndex = 0;
101 |
102 | VaultItem[] memory items = new VaultItem[](unsoldItemCount);
103 | for (uint i = 0; i < itemCount; i++) {
104 | if (idToVaultItem[i + 1].holder == address(0)) {
105 | uint currentId = i + 1;
106 | VaultItem storage currentItem = idToVaultItem[currentId];
107 | items[currentIndex] = currentItem;
108 | currentIndex += 1;
109 | }
110 | }
111 | return items;
112 | }
113 |
114 | function getMyNft() public view returns (VaultItem[] memory) {
115 | uint totalItemCount = _itemIds.current();
116 | uint itemCount = 0;
117 | uint currentIndex = 0;
118 |
119 | for (uint i = 0; i < totalItemCount; i++) {
120 | if (idToVaultItem[i + 1].holder == msg.sender) {
121 | itemCount += 1;
122 | }
123 | }
124 |
125 | VaultItem[] memory items = new VaultItem[](itemCount);
126 | for (uint i = 0; i < totalItemCount; i++) {
127 | if (idToVaultItem[i + 1].holder == msg.sender) {
128 | uint currentId = i + 1;
129 | VaultItem storage currentItem = idToVaultItem[currentId];
130 | items[currentIndex] = currentItem;
131 | currentIndex += 1;
132 | }
133 | }
134 | return items;
135 | }
136 |
137 | function getMyMarketNfts() public view returns (VaultItem[] memory) {
138 | uint totalItemCount = _itemIds.current();
139 | uint itemCount = 0;
140 | uint currentIndex = 0;
141 |
142 | for (uint i = 0; i < totalItemCount; i++) {
143 | if (idToVaultItem[i + 1].seller == msg.sender) {
144 | itemCount += 1;
145 | }
146 | }
147 |
148 | VaultItem[] memory items = new VaultItem[](itemCount);
149 | for (uint i = 0; i < totalItemCount; i++) {
150 | if (idToVaultItem[i + 1].seller == msg.sender) {
151 | uint currentId = i + 1;
152 | VaultItem storage currentItem = idToVaultItem[currentId];
153 | items[currentIndex] = currentItem;
154 | currentIndex += 1;
155 | }
156 | }
157 | return items;
158 | }
159 |
160 | function withdraw() public payable onlyOwner() {
161 | require(payable(msg.sender).send(address(this).balance));
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/Part5-Create-and-Sell-NFT-App/NFT.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "anonymous": false,
4 | "inputs": [
5 | {
6 | "indexed": true,
7 | "internalType": "address",
8 | "name": "owner",
9 | "type": "address"
10 | },
11 | {
12 | "indexed": true,
13 | "internalType": "address",
14 | "name": "approved",
15 | "type": "address"
16 | },
17 | {
18 | "indexed": true,
19 | "internalType": "uint256",
20 | "name": "tokenId",
21 | "type": "uint256"
22 | }
23 | ],
24 | "name": "Approval",
25 | "type": "event"
26 | },
27 | {
28 | "anonymous": false,
29 | "inputs": [
30 | {
31 | "indexed": true,
32 | "internalType": "address",
33 | "name": "owner",
34 | "type": "address"
35 | },
36 | {
37 | "indexed": true,
38 | "internalType": "address",
39 | "name": "operator",
40 | "type": "address"
41 | },
42 | {
43 | "indexed": false,
44 | "internalType": "bool",
45 | "name": "approved",
46 | "type": "bool"
47 | }
48 | ],
49 | "name": "ApprovalForAll",
50 | "type": "event"
51 | },
52 | {
53 | "anonymous": false,
54 | "inputs": [
55 | {
56 | "indexed": true,
57 | "internalType": "address",
58 | "name": "from",
59 | "type": "address"
60 | },
61 | {
62 | "indexed": true,
63 | "internalType": "address",
64 | "name": "to",
65 | "type": "address"
66 | },
67 | {
68 | "indexed": true,
69 | "internalType": "uint256",
70 | "name": "tokenId",
71 | "type": "uint256"
72 | }
73 | ],
74 | "name": "Transfer",
75 | "type": "event"
76 | },
77 | {
78 | "inputs": [
79 | {
80 | "internalType": "address",
81 | "name": "to",
82 | "type": "address"
83 | },
84 | {
85 | "internalType": "uint256",
86 | "name": "tokenId",
87 | "type": "uint256"
88 | }
89 | ],
90 | "name": "approve",
91 | "outputs": [],
92 | "stateMutability": "nonpayable",
93 | "type": "function"
94 | },
95 | {
96 | "inputs": [
97 | {
98 | "internalType": "string",
99 | "name": "tokenURI",
100 | "type": "string"
101 | }
102 | ],
103 | "name": "createNFT",
104 | "outputs": [
105 | {
106 | "internalType": "uint256",
107 | "name": "",
108 | "type": "uint256"
109 | }
110 | ],
111 | "stateMutability": "nonpayable",
112 | "type": "function"
113 | },
114 | {
115 | "inputs": [
116 | {
117 | "internalType": "string",
118 | "name": "tokenURI",
119 | "type": "string"
120 | }
121 | ],
122 | "name": "mintNFT",
123 | "outputs": [
124 | {
125 | "internalType": "uint256",
126 | "name": "",
127 | "type": "uint256"
128 | }
129 | ],
130 | "stateMutability": "payable",
131 | "type": "function"
132 | },
133 | {
134 | "inputs": [
135 | {
136 | "internalType": "address",
137 | "name": "from",
138 | "type": "address"
139 | },
140 | {
141 | "internalType": "address",
142 | "name": "to",
143 | "type": "address"
144 | },
145 | {
146 | "internalType": "uint256",
147 | "name": "tokenId",
148 | "type": "uint256"
149 | }
150 | ],
151 | "name": "safeTransferFrom",
152 | "outputs": [],
153 | "stateMutability": "nonpayable",
154 | "type": "function"
155 | },
156 | {
157 | "inputs": [
158 | {
159 | "internalType": "address",
160 | "name": "from",
161 | "type": "address"
162 | },
163 | {
164 | "internalType": "address",
165 | "name": "to",
166 | "type": "address"
167 | },
168 | {
169 | "internalType": "uint256",
170 | "name": "tokenId",
171 | "type": "uint256"
172 | },
173 | {
174 | "internalType": "bytes",
175 | "name": "data",
176 | "type": "bytes"
177 | }
178 | ],
179 | "name": "safeTransferFrom",
180 | "outputs": [],
181 | "stateMutability": "nonpayable",
182 | "type": "function"
183 | },
184 | {
185 | "inputs": [
186 | {
187 | "internalType": "address",
188 | "name": "operator",
189 | "type": "address"
190 | },
191 | {
192 | "internalType": "bool",
193 | "name": "approved",
194 | "type": "bool"
195 | }
196 | ],
197 | "name": "setApprovalForAll",
198 | "outputs": [],
199 | "stateMutability": "nonpayable",
200 | "type": "function"
201 | },
202 | {
203 | "inputs": [
204 | {
205 | "internalType": "address",
206 | "name": "from",
207 | "type": "address"
208 | },
209 | {
210 | "internalType": "address",
211 | "name": "to",
212 | "type": "address"
213 | },
214 | {
215 | "internalType": "uint256",
216 | "name": "tokenId",
217 | "type": "uint256"
218 | }
219 | ],
220 | "name": "transferFrom",
221 | "outputs": [],
222 | "stateMutability": "nonpayable",
223 | "type": "function"
224 | },
225 | {
226 | "inputs": [
227 | {
228 | "internalType": "address",
229 | "name": "marketContract",
230 | "type": "address"
231 | }
232 | ],
233 | "stateMutability": "nonpayable",
234 | "type": "constructor"
235 | },
236 | {
237 | "inputs": [],
238 | "name": "_tokenIds",
239 | "outputs": [
240 | {
241 | "internalType": "uint256",
242 | "name": "_value",
243 | "type": "uint256"
244 | }
245 | ],
246 | "stateMutability": "view",
247 | "type": "function"
248 | },
249 | {
250 | "inputs": [
251 | {
252 | "internalType": "address",
253 | "name": "owner",
254 | "type": "address"
255 | }
256 | ],
257 | "name": "balanceOf",
258 | "outputs": [
259 | {
260 | "internalType": "uint256",
261 | "name": "",
262 | "type": "uint256"
263 | }
264 | ],
265 | "stateMutability": "view",
266 | "type": "function"
267 | },
268 | {
269 | "inputs": [],
270 | "name": "cost",
271 | "outputs": [
272 | {
273 | "internalType": "uint256",
274 | "name": "",
275 | "type": "uint256"
276 | }
277 | ],
278 | "stateMutability": "view",
279 | "type": "function"
280 | },
281 | {
282 | "inputs": [
283 | {
284 | "internalType": "uint256",
285 | "name": "tokenId",
286 | "type": "uint256"
287 | }
288 | ],
289 | "name": "getApproved",
290 | "outputs": [
291 | {
292 | "internalType": "address",
293 | "name": "",
294 | "type": "address"
295 | }
296 | ],
297 | "stateMutability": "view",
298 | "type": "function"
299 | },
300 | {
301 | "inputs": [
302 | {
303 | "internalType": "address",
304 | "name": "owner",
305 | "type": "address"
306 | },
307 | {
308 | "internalType": "address",
309 | "name": "operator",
310 | "type": "address"
311 | }
312 | ],
313 | "name": "isApprovedForAll",
314 | "outputs": [
315 | {
316 | "internalType": "bool",
317 | "name": "",
318 | "type": "bool"
319 | }
320 | ],
321 | "stateMutability": "view",
322 | "type": "function"
323 | },
324 | {
325 | "inputs": [],
326 | "name": "name",
327 | "outputs": [
328 | {
329 | "internalType": "string",
330 | "name": "",
331 | "type": "string"
332 | }
333 | ],
334 | "stateMutability": "view",
335 | "type": "function"
336 | },
337 | {
338 | "inputs": [
339 | {
340 | "internalType": "uint256",
341 | "name": "tokenId",
342 | "type": "uint256"
343 | }
344 | ],
345 | "name": "ownerOf",
346 | "outputs": [
347 | {
348 | "internalType": "address",
349 | "name": "",
350 | "type": "address"
351 | }
352 | ],
353 | "stateMutability": "view",
354 | "type": "function"
355 | },
356 | {
357 | "inputs": [
358 | {
359 | "internalType": "bytes4",
360 | "name": "interfaceId",
361 | "type": "bytes4"
362 | }
363 | ],
364 | "name": "supportsInterface",
365 | "outputs": [
366 | {
367 | "internalType": "bool",
368 | "name": "",
369 | "type": "bool"
370 | }
371 | ],
372 | "stateMutability": "view",
373 | "type": "function"
374 | },
375 | {
376 | "inputs": [],
377 | "name": "symbol",
378 | "outputs": [
379 | {
380 | "internalType": "string",
381 | "name": "",
382 | "type": "string"
383 | }
384 | ],
385 | "stateMutability": "view",
386 | "type": "function"
387 | },
388 | {
389 | "inputs": [
390 | {
391 | "internalType": "uint256",
392 | "name": "tokenId",
393 | "type": "uint256"
394 | }
395 | ],
396 | "name": "tokenURI",
397 | "outputs": [
398 | {
399 | "internalType": "string",
400 | "name": "",
401 | "type": "string"
402 | }
403 | ],
404 | "stateMutability": "view",
405 | "type": "function"
406 | }
407 | ]
--------------------------------------------------------------------------------
/Part5-Create-and-Sell-NFT-App/_app.js:
--------------------------------------------------------------------------------
1 | import { createTheme, NextUIProvider } from "@nextui-org/react";
2 | import 'sf-font';
3 | import Link from 'next/link'
4 | import { Spacer, Button, Col, Row, Container, Dropdown, Text } from '@nextui-org/react';
5 | import react from "react";
6 | import Footer from './footer';
7 |
8 | const theme = createTheme({
9 | type: "dark",
10 | theme: {
11 | fontFamily:'SF Pro Display',
12 | colors: {
13 | primaryLight: '$blue200',
14 | primaryLightHover: '$blue300',
15 | primaryLightActive: '$blue400',
16 | primaryLightContrast: '$blue600',
17 | primary: '$purple500',
18 | primaryBorder: '$blue500',
19 | primaryBorderHover: '$blue600',
20 | primarySolidHover: '$blue700',
21 | primarySolidContrast: '$white',
22 | primaryShadow: '$white500',
23 | transparent: '#00000000',
24 |
25 | gradient: 'linear-gradient(112deg, $blue100 -25%, $pink500 -10%, $purple300 90%)',
26 | link: '#5E1DAD',
27 |
28 | myColor: '#00000030'
29 |
30 | },
31 | space: {},
32 | fonts: {}
33 | }
34 | })
35 |
36 | function MyApp({ Component, pageProps }) {
37 |
38 | return(
39 |
114 |
115 | )
116 |
117 |
118 | }
119 |
120 | export default MyApp
121 |
--------------------------------------------------------------------------------
/Part5-Create-and-Sell-NFT-App/create.js:
--------------------------------------------------------------------------------
1 | import { ethers } from 'ethers';
2 | import { useState } from 'react';
3 | import { useRouter } from 'next/router';
4 | import Web3Modal from "web3modal";
5 | import NFT from '../engine/NFT.json';
6 | import Market from '../engine/Market.json';
7 | import { hhnft, hhmarket } from '../engine/configuration';
8 | import { Card, Button, Input, Col, Row, Spacer, Container, Text, Grid } from '@nextui-org/react';
9 | import { client } from '../engine/configuration';
10 | import 'sf-font';
11 |
12 | export default function createMarket() {
13 | const [fileUrl, setFileUrl] = useState(null)
14 | const [formInput, updateFormInput] = useState({ price: '', name: '', description: '' })
15 | const router = useRouter()
16 |
17 | async function onChange(e) {
18 | const file = e.target.files[0]
19 | try {
20 | const added = await client.add(
21 | file,
22 | {
23 | progress: (prog) => console.log(`received: ${prog}`)
24 | }
25 | )
26 | const url = `https://ipfs.infura.io/ipfs/${added.path}`
27 | setFileUrl(url)
28 | } catch (error) {
29 | console.log('Error uploading file: ', error)
30 | }
31 | }
32 |
33 | async function createMarket() {
34 | const { name, description, price } = formInput
35 | if (!name || !description || !price || !fileUrl) return
36 | const data = JSON.stringify({
37 | name, description, image: fileUrl
38 | })
39 | try {
40 | const added = await client.add(data)
41 | const url = `https://ipfs.infura.io/ipfs/${added.path}`
42 | createNFT(url)
43 | } catch (error) {
44 | console.log('Error uploading file: ', error)
45 | }
46 | }
47 |
48 | async function createNFT(url) {
49 | const web3Modal = new Web3Modal()
50 | const connection = await web3Modal.connect()
51 | const provider = new ethers.providers.Web3Provider(connection)
52 | const signer = provider.getSigner()
53 | let contract = new ethers.Contract(hhnft, NFT, signer)
54 | let transaction = await contract.createNFT(url)
55 | let tx = await transaction.wait()
56 | let event = tx.events[0]
57 | let value = event.args[2]
58 | let tokenId = value.toNumber()
59 | const price = ethers.utils.parseUnits(formInput.price, 'ether')
60 | contract = new ethers.Contract(hhmarket, Market, signer)
61 | let listingFee = await contract.listingFee()
62 | listingFee = listingFee.toString()
63 | transaction = await contract.createVaultItem(hhnft, tokenId, price, { value: listingFee })
64 | await transaction.wait()
65 | router.push('/')
66 | }
67 |
68 | async function buyNFT() {
69 | const { name, description } = formInput
70 | if (!name || !description || !fileUrl) return
71 | const data = JSON.stringify({
72 | name, description, image: fileUrl
73 | })
74 | try {
75 | const added = await client.add(data)
76 | const url = `https://ipfs.infura.io/ipfs/${added.path}`
77 | mintNFT(url)
78 | } catch (error) {
79 | console.log('Error uploading file: ', error)
80 | }
81 | }
82 |
83 | async function mintNFT(url) {
84 | const web3Modal = new Web3Modal()
85 | const connection = await web3Modal.connect()
86 | const provider = new ethers.providers.Web3Provider(connection)
87 | const signer = provider.getSigner()
88 | let contract = new ethers.Contract(hhnft, NFT, signer)
89 | let cost = await contract.cost()
90 | let transaction = await contract.mintNFT(url, { value: cost })
91 | await transaction.wait()
92 | router.push('/portal')
93 | }
94 |
95 | return (
96 |
176 | )
177 | }
178 |
--------------------------------------------------------------------------------
/Part5-Create-and-Sell-NFT-App/index.js:
--------------------------------------------------------------------------------
1 | import { ethers } from 'ethers';
2 | import { useEffect, useState } from 'react';
3 | import axios from 'axios';
4 | import Web3Modal from "web3modal";
5 | import { useRouter } from 'next/router';
6 | import NFTCollection from '../engine/NFTCollection.json'
7 | import Resell from '../engine/Resell.json';
8 | import Market from '../engine/Market.json';
9 | import NFT from '../engine/NFT.json';
10 | import { Grid, Card, Text, Button, Row, Spacer, Container } from '@nextui-org/react';
11 | import { hhnft, hhmarket, hhresell, hhnftcol, mainnet } from '../engine/configuration';
12 | import { cipherHH, simpleCrypto } from '../engine/configuration';
13 | import confetti from 'canvas-confetti';
14 | import 'sf-font';
15 | import Carousel from "react-multi-carousel";
16 | import "react-multi-carousel/lib/styles.css";
17 |
18 | export default function Home() {
19 | const [hhlist, hhResellNfts] = useState([])
20 | const [hhnfts, hhsetNfts] = useState([])
21 |
22 | useEffect(() => {
23 | loadHardHatResell()
24 | loadNewSaleNFTs()
25 | }, [hhResellNfts, hhsetNfts])
26 |
27 | const handleConfetti = () => {
28 | confetti();
29 | };
30 | const router = useRouter()
31 |
32 | async function loadHardHatResell() {
33 | const provider = new ethers.providers.JsonRpcProvider(mainnet)
34 | const key = simpleCrypto.decrypt(cipherHH)
35 | const wallet = new ethers.Wallet(key, provider);
36 | const contract = new ethers.Contract(hhnftcol, NFTCollection, wallet);
37 | const market = new ethers.Contract(hhresell, Resell, wallet);
38 | const itemArray = [];
39 | contract.totalSupply().then(result => {
40 | for (let i = 0; i < result; i++) {
41 | var token = i + 1
42 | var owner = contract.ownerOf(token)
43 | var getOwner = Promise.resolve(owner)
44 | getOwner.then(address => {
45 | if (address == hhresell) {
46 | const rawUri = contract.tokenURI(token)
47 | const Uri = Promise.resolve(rawUri)
48 | const getUri = Uri.then(value => {
49 | let str = value
50 | let cleanUri = str.replace('ipfs://', 'https://ipfs.io/ipfs/')
51 | console.log(cleanUri)
52 | let metadata = axios.get(cleanUri).catch(function (error) {
53 | console.log(error.toJSON());
54 | });
55 | return metadata;
56 | })
57 | getUri.then(value => {
58 | let rawImg = value.data.image
59 | var name = value.data.name
60 | var desc = value.data.description
61 | let image = rawImg.replace('ipfs://', 'https://ipfs.io/ipfs/')
62 | const price = market.getPrice(token)
63 | Promise.resolve(price).then(_hex => {
64 | var salePrice = Number(_hex);
65 | var txPrice = salePrice.toString()
66 | Promise.resolve(owner).then(value => {
67 | let ownerW = value;
68 | let outPrice = ethers.utils.formatUnits(salePrice.toString(), 'ether')
69 | let meta = {
70 | name: name,
71 | img: image,
72 | cost: txPrice,
73 | val: outPrice,
74 | tokenId: token,
75 | wallet: ownerW,
76 | desc
77 | }
78 | console.log(meta)
79 | itemArray.push(meta)
80 | })
81 | })
82 | })
83 | }})
84 | }})
85 | await new Promise(r => setTimeout(r, 3000));
86 | hhResellNfts(itemArray)
87 | }
88 |
89 | async function loadNewSaleNFTs() {
90 | const hhPrivkey = simpleCrypto.decrypt(cipherHH)
91 | const provider = new ethers.providers.JsonRpcProvider(mainnet)
92 | const wallet = new ethers.Wallet(hhPrivkey, provider);
93 | const tokenContract = new ethers.Contract(hhnft, NFT, wallet)
94 | const marketContract = new ethers.Contract(hhmarket, Market, wallet)
95 | const data = await marketContract.getAvailableNft()
96 | const items = await Promise.all(data.map(async i => {
97 | const tokenUri = await tokenContract.tokenURI(i.tokenId)
98 | const meta = await axios.get(tokenUri)
99 | let price = ethers.utils.formatUnits(i.price.toString(), 'ether')
100 | let item = {
101 | price,
102 | tokenId: i.tokenId.toNumber(),
103 | seller: i.seller,
104 | owner: i.owner,
105 | image: meta.data.image,
106 | name: meta.data.name,
107 | description: meta.data.description,
108 | }
109 | return item
110 | }))
111 | hhsetNfts(items)
112 | }
113 |
114 | async function buyNewNft(nft) {
115 | const web3Modal = new Web3Modal()
116 | const connection = await web3Modal.connect()
117 | const provider = new ethers.providers.Web3Provider(connection)
118 | const signer = provider.getSigner()
119 | const contract = new ethers.Contract(hhmarket, Market, signer)
120 | const price = ethers.utils.parseUnits(nft.price.toString(), 'ether')
121 | const transaction = await contract.n2DMarketSale(hhnft, nft.tokenId, {
122 | value: price
123 | })
124 | await transaction.wait()
125 | loadNewSaleNFTs()
126 | }
127 |
128 | const responsive = {
129 | desktop: {
130 | breakpoint: { max: 3000, min: 1024 },
131 | items: 1,
132 | slidesToSlide: 1
133 | },
134 | tablet: {
135 | breakpoint: { max: 1024, min: 464 },
136 | items: 2,
137 | slidesToSlide: 2
138 | },
139 | mobile: {
140 | breakpoint: { max: 464, min: 0 },
141 | items: 1,
142 | slidesToSlide: 1
143 | }
144 | };
145 |
146 | return (
147 |
148 |
149 |
150 |
151 | Top Collections
152 |
167 | {
168 | hhlist.map((nft, i) => (
169 |
170 |
171 |
172 | ))
173 | }
174 |
175 |
176 |
177 |
178 |
179 |
180 | Latest NFT's
181 |
182 |
183 | {
184 | hhlist.slice(0, 9).map((nft, id) => {
185 | async function buylistNft() {
186 | const web3Modal = new Web3Modal()
187 | const connection = await web3Modal.connect()
188 | const provider = new ethers.providers.Web3Provider(connection)
189 | const signer = provider.getSigner()
190 | const contract = new ethers.Contract(hhresell, Resell, signer)
191 | const transaction = await contract.buyNft(nft.tokenId, { value: nft.cost })
192 | await transaction.wait()
193 | router.push('/portal')
194 | }
195 | return (
196 |
197 |
198 | {nft.name} Token-{nft.tokenId}
206 |
207 |
211 |
212 |
213 |
214 | {nft.desc}
215 | {nft.val}
216 | handleConfetti(buylistNft(nft))}>Buy
217 |
218 |
219 |
220 |
221 | )
222 | })
223 | }
224 |
225 |
226 |
227 |
228 |
229 | Latest NFT's on
230 |
231 |
232 | {
233 | hhnfts.slice(0, 4).map((nft, i) => (
234 |
235 |
236 | {nft.name}
244 |
245 |
249 |
250 |
251 |
252 | {nft.description}
253 | {nft.price}
254 | handleConfetti(buyNewNft(nft))}>Buy
255 |
256 |
257 |
258 |
259 | ))
260 | }
261 |
262 |
263 |
264 | )
265 | }
--------------------------------------------------------------------------------
/Part5-Create-and-Sell-NFT-App/portal.js:
--------------------------------------------------------------------------------
1 | import { ethers } from 'ethers';
2 | import { useState, useEffect } from 'react';
3 | import Web3Modal from "web3modal";
4 | import { useRouter } from 'next/router';
5 | import Resell from '../engine/Resell.json';
6 | import NFTCollection from '../engine/NFTCollection.json';
7 | import NFT from '../engine/NFT.json';
8 | import { Card, Button, Input, Col, Row, Spacer, Container, Text, Grid } from '@nextui-org/react';
9 | import axios from 'axios';
10 | import 'sf-font';
11 | import Web3 from 'web3';
12 | import { hhnft, hhresell, hhnftcol, mainnet, cipherHH, simpleCrypto } from '../engine/configuration';
13 |
14 | export default function Sell() {
15 | const [user, getUser] = useState([])
16 | const [created, getCreated] = useState([])
17 | const [resalePrice, updateresalePrice] = useState({ price: ''})
18 | const [nfts, setNfts] = useState([])
19 | const [loadingState, setLoadingState] = useState('not-loaded')
20 | useEffect(() => {
21 | connectUser();
22 | getWalletNFTs();
23 | getCreatedNFTs();
24 | }, [setNfts,getUser, getCreated])
25 | const router = useRouter()
26 |
27 | async function connectUser() {
28 | if (window.ethereum) {
29 | var web3 = new Web3(window.ethereum);
30 | await window.ethereum.send('eth_requestAccounts');
31 | var accounts = await web3.eth.getAccounts();
32 | var account = accounts[0];
33 | }
34 | getUser(account)
35 | }
36 |
37 | async function getWalletNFTs() {
38 | const provider = new ethers.providers.JsonRpcProvider(mainnet)
39 | const key = simpleCrypto.decrypt(cipherHH)
40 | const wallet = new ethers.Wallet(key, provider);
41 | const contract = new ethers.Contract(hhnftcol, NFTCollection, wallet);
42 | const itemArray = [];
43 | contract.totalSupply().then(result => {
44 | for (let i = 0; i < result; i++) {
45 | var token = i + 1
46 | const owner = contract.ownerOf(token).catch(function (error) {
47 | console.log("tokens filtered");
48 | });
49 | const rawUri = contract.tokenURI(token).catch(function (error) {
50 | console.log("tokens filtered");
51 | });
52 | const Uri = Promise.resolve(rawUri)
53 | const getUri = Uri.then(value => {
54 | var cleanUri = value.replace('ipfs://', 'https://ipfs.io/ipfs/')
55 | let metadata = axios.get(cleanUri).catch(function (error) {
56 | console.log(error.toJSON());
57 | });
58 | return metadata;
59 | })
60 | getUri.then(value => {
61 | let rawImg = value.data.image
62 | var name = value.data.name
63 | var desc = value.data.description
64 | let image = rawImg.replace('ipfs://', 'https://ipfs.io/ipfs/')
65 | Promise.resolve(owner).then(value => {
66 | let ownerW = value;
67 | let meta = {
68 | name: name,
69 | img: image,
70 | tokenId: token,
71 | wallet: ownerW,
72 | desc,
73 | }
74 | console.log(meta)
75 | itemArray.push(meta)
76 | })
77 | })
78 | }
79 | })
80 | await new Promise(r => setTimeout(r, 3000));
81 | setNfts(itemArray)
82 | setLoadingState('loaded');
83 | }
84 |
85 | async function getCreatedNFTs() {
86 | const provider = new ethers.providers.JsonRpcProvider(mainnet)
87 | const key = simpleCrypto.decrypt(cipherHH)
88 | const wallet = new ethers.Wallet(key, provider);
89 | const contract = new ethers.Contract(hhnft, NFT, wallet);
90 | const itemArray = [];
91 | contract._tokenIds().then(result => {
92 | for (let i = 0; i < result; i++) {
93 | var token = i + 1
94 | const owner = contract.ownerOf(token).catch(function (error) {
95 | console.log("tokens filtered");
96 | });
97 | const rawUri = contract.tokenURI(token).catch(function (error) {
98 | console.log("tokens filtered");
99 | });
100 | const Uri = Promise.resolve(rawUri)
101 | const getUri = Uri.then(value => {
102 | var cleanUri = value.replace('ipfs://', 'https://ipfs.io/ipfs/')
103 | let metadata = axios.get(cleanUri).catch(function (error) {
104 | console.log(error.toJSON());
105 | });
106 | return metadata;
107 | })
108 | getUri.then(value => {
109 | let rawImg = value.data.image
110 | var name = value.data.name
111 | var desc = value.data.description
112 | let image = rawImg.replace('ipfs://', 'https://ipfs.io/ipfs/')
113 | Promise.resolve(owner).then(value => {
114 | let ownerW = value;
115 | let meta = {
116 | name: name,
117 | img: image,
118 | tokenId: token,
119 | wallet: ownerW,
120 | desc,
121 | }
122 | console.log(meta)
123 | itemArray.push(meta)
124 | })
125 | })
126 | }
127 | })
128 | await new Promise(r => setTimeout(r, 3000));
129 | getCreated(itemArray)
130 | setLoadingState('loaded');
131 | }
132 |
133 | if (loadingState === 'loaded' && !nfts.length)
134 | return (
135 |
136 |
137 |
138 | No NFT's Found, Connect Wallet
139 |
140 |
141 |
142 |
143 | )
144 | return (
145 |
146 |
147 |
148 |
149 | NFT's in Wallet {user}
150 |
151 | Refresh Wallet
152 | Refresh NFTs
153 |
154 |
155 |
156 |
157 |
158 | {nfts.map((nft, i) => {
159 | var owner = user
160 | if (owner.indexOf(nft.wallet) !== -1) {
161 | async function executeRelist() {
162 | const { price } = resalePrice
163 | if (!price) return
164 | try {
165 | relistNFT()
166 | } catch (error) {
167 | console.log('Transaction Failed', error)
168 | }
169 | }
170 | async function relistNFT() {
171 | const web3Modal = new Web3Modal()
172 | const connection = await web3Modal.connect()
173 | const provider = new ethers.providers.Web3Provider(connection)
174 | const signer = provider.getSigner()
175 | const price = ethers.utils.parseUnits(resalePrice.price, 'ether')
176 | const contractnft = new ethers.Contract(hhnftcol, NFTCollection, signer);
177 | await contractnft.setApprovalForAll(hhresell, true);
178 | let contract = new ethers.Contract(hhresell, Resell, signer)
179 | let listingFee = await contract.getListingFee()
180 | listingFee = listingFee.toString()
181 | let transaction = await contract.listSale(nft.tokenId, price, { value: listingFee })
182 | await transaction.wait()
183 | router.push('/')
184 | }
185 | return (
186 |
187 |
188 |
189 |
190 |
191 | Owned by You
192 | {nft.name} Token-{nft.tokenId}
193 | {nft.desc}
194 | updateresalePrice({ ...resalePrice, price: e.target.value })}
199 | />
200 | Relist for Sale
201 |
202 |
203 |
204 |
205 | )
206 | }})}
207 |
208 |
209 |
210 |
211 |
212 | Created NFT's in Wallet
213 |
214 |
215 | {created.map((nft, i) => {
216 | var owner = user
217 | if (owner.indexOf(nft.wallet) !== -1) {
218 | return (
219 |
220 |
221 |
222 |
223 |
224 | Owned by You
225 | {nft.name} Token-{nft.tokenId}
226 | {nft.desc}
227 |
228 |
229 |
230 |
231 | )
232 | }})}
233 |
234 |
235 |
236 |
237 | )
238 | }
--------------------------------------------------------------------------------
/Part6-Final-Multichain-Integration/engine/chainchange.js:
--------------------------------------------------------------------------------
1 | export async function bscChain() {
2 | try {
3 | await ethereum.request({
4 | method: 'wallet_switchEthereumChain',
5 | params: [{ chainId: '0x38' }],
6 | });
7 | } catch (switchError) {
8 | if (switchError.code === 4902) {
9 | try {
10 | await window.ethereum.request({
11 | method: 'wallet_addEthereumChain',
12 | params: [{
13 | chainId: '0x38',
14 | chainName: 'Binance Smart Chain',
15 | nativeCurrency: {
16 | name: 'BNB',
17 | symbol: 'BNB',
18 | decimals: 18,
19 | },
20 | rpcUrls: ['https://bsc-dataseed2.defibit.io'],
21 | blockExplorerUrls: ['https://bscscan.com/'],
22 | }]
23 | })
24 | } catch (addError) {
25 | console.log('Error adding Chain');
26 | }
27 | }
28 | }
29 | }
30 | export async function polyChain() {
31 | try {
32 | await ethereum.request({
33 | method: 'wallet_switchEthereumChain',
34 | params: [{ chainId: '0x89' }],
35 | });
36 | } catch (switchError) {
37 | if (switchError.code === 4902) {
38 | try {
39 | await window.ethereum.request({
40 | method: 'wallet_addEthereumChain',
41 | params: [{
42 | chainId: '0x89',
43 | chainName: 'Polygon',
44 | nativeCurrency: {
45 | name: 'MATIC',
46 | symbol: 'MATIC',
47 | decimals: 18,
48 | },
49 | rpcUrls: ['https://matic-mainnet.chainstacklabs.com'],
50 | blockExplorerUrls: ['https://polygonscan.com/'],
51 | }]
52 | })
53 | } catch (addError) {
54 | console.log('Error adding Chain');
55 | }
56 | }
57 | }
58 | }
59 |
60 | export async function ethChain() {
61 | try {
62 | await ethereum.request({
63 | method: 'wallet_switchEthereumChain',
64 | params: [{ chainId: '0x1' }],
65 | });
66 | } catch (switchError) {
67 | console.log('Wallet Not Connected')
68 | }
69 | }
70 |
71 | export async function hardChain() {
72 | try {
73 | await ethereum.request({
74 | method: 'wallet_switchEthereumChain',
75 | params: [{ chainId: '0x7A69' }],
76 | });
77 | } catch (switchError) {
78 | if (switchError.code === 4902) {
79 | try {
80 | await window.ethereum.request({
81 | method: 'wallet_addEthereumChain',
82 | params: [{
83 | chainId: '0x7A69',
84 | chainName: 'HardHat',
85 | nativeCurrency: {
86 | name: 'ETH',
87 | symbol: 'ETH',
88 | decimals: 18,
89 | },
90 | rpcUrls: ['http://node.a3b.io:8545'],
91 | blockExplorerUrls: [''],
92 | }]
93 | })
94 | } catch (addError) {
95 | console.log('Error adding Chain');
96 | }
97 | }
98 | }
99 | }
100 |
101 | export async function bscTest() {
102 | try {
103 | await ethereum.request({
104 | method: 'wallet_switchEthereumChain',
105 | params: [{ chainId: '0x61' }],
106 | });
107 | } catch (switchError) {
108 | if (switchError.code === 4902) {
109 | try {
110 | await window.ethereum.request({
111 | method: 'wallet_addEthereumChain',
112 | params: [{
113 | chainId: '0x61',
114 | chainName: 'BSC Testnet',
115 | nativeCurrency: {
116 | name: 'tBNB',
117 | symbol: 'tBNB',
118 | decimals: 18,
119 | },
120 | rpcUrls: ['https://data-seed-prebsc-1-s3.binance.org:8545'],
121 | blockExplorerUrls: ['https://testnet.bscscan.com/'],
122 | }]
123 | })
124 | } catch (addError) {
125 | console.log('Error adding Chain');
126 | }
127 | }
128 | }
129 | }
130 |
131 | export async function ethTest() {
132 | try {
133 | await ethereum.request({
134 | method: 'wallet_switchEthereumChain',
135 | params: [{ chainId: '0x5' }],
136 | });
137 | } catch (switchError) {
138 | console.log('Wallet Not Connected')
139 | }
140 | }
141 |
142 | export async function polyTest() {
143 | try {
144 | await ethereum.request({
145 | method: 'wallet_switchEthereumChain',
146 | params: [{ chainId: '0x13881' }],
147 | });
148 | } catch (switchError) {
149 | if (switchError.code === 4902) {
150 | try {
151 | await window.ethereum.request({
152 | method: 'wallet_addEthereumChain',
153 | params: [{
154 | chainId: '0x13881',
155 | chainName: 'Polygon Mumbai',
156 | nativeCurrency: {
157 | name: 'MATIC',
158 | symbol: 'MATIC',
159 | decimals: 18,
160 | },
161 | rpcUrls: ['https://matic-mumbai.chainstacklabs.com'],
162 | blockExplorerUrls: ['https://mumbai.polygonscan.com/'],
163 | }]
164 | })
165 | } catch (addError) {
166 | console.log('Error adding Chain');
167 | }
168 | }
169 | }
170 | }
--------------------------------------------------------------------------------
/Part6-Final-Multichain-Integration/engine/configuration.js:
--------------------------------------------------------------------------------
1 | /*
2 | ___ ___ _ _ ___ _____ __ __ _ _
3 | _ _ |_ )| \ | \| || __||_ _| | \/ | __ _ _ _ | |__ ___ | |_
4 | | ' \ / / | |) | | .` || _| | | | |\/| |/ _` || '_|| / // -_)| _|
5 | |_||_|/___||___/ |_|\_||_| |_| |_| |_|\__,_||_| |_\_\\___| \__|
6 |
7 | Update values accordingly
8 | xxnft is the NFT Creator Contract Address
9 | xxmarket is the NFT MarketPlace Contract Address to sell created nfts.
10 | xxresell is the NFT MarketResell Contract Address for existing nfts.
11 | xxnftcol is the existing NFT Collection Address
12 | */
13 |
14 | /*
15 | Private Key Encryption
16 | Replace ethraw with your private key "0xPRIVATEKEY" (Ethereum and other EVM)
17 | Replace hhraw with your private key "0xPRIVATEKEY" (Hardhat)
18 | */
19 | import SimpleCrypto from "simple-crypto-js"
20 | const cipherKey = "#ffg3$dvcv4rtkljjkh38dfkhhjgt"
21 | const ethraw = "0x8207b7bbf486039b455923a402560ed041ad4b7243e9f329d6e415c00aaa9ef2";
22 | const hhraw = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80";
23 | export const simpleCrypto = new SimpleCrypto(cipherKey)
24 | export const cipherEth = simpleCrypto.encrypt(ethraw)
25 | export const cipherHH = simpleCrypto.encrypt(hhraw)
26 |
27 | /*
28 | IPFS API DETAILS
29 | */
30 | import { create as ipfsHttpClient } from 'ipfs-http-client';
31 | export const client = ipfsHttpClient('https://ipfs.infura.io:5001/api/v0');
32 |
33 | /*
34 | HardHat Testnet
35 | */
36 | export var hhresell = "YOUR CONTRACT ADDRESS";
37 | export var hhnftcol = "YOUR CONTRACT ADDRESS";
38 | export var hhnft = "YOUR CONTRACT ADDRESS";
39 | export var hhmarket = "YOUR CONTRACT ADDRESS";
40 | export var hhrpc = "http://localhost:8545";
41 |
42 | /*
43 | Goerli Testnet
44 | */
45 | export var goeresell = "YOUR CONTRACT ADDRESS";
46 | export var goenftcol = "YOUR CONTRACT ADDRESS";
47 | export var goenft = "YOUR CONTRACT ADDRESS";
48 | export var goemarket = "YOUR CONTRACT ADDRESS";
49 | export var goerpc = "https://rpc.ankr.com/eth_goerli";
50 |
51 | /*
52 | BSC Testnet
53 | */
54 | export var bsctresell = "YOUR CONTRACT ADDRESS";
55 | export var bsctnftcol = "YOUR CONTRACT ADDRESS";
56 | export var bsctnft = "YOUR CONTRACT ADDRESS";
57 | export var bsctmarket = "YOUR CONTRACT ADDRESS";
58 | export var bsctrpc = "https://data-seed-prebsc-2-s3.binance.org:8545";
59 |
60 | /*
61 | Mumbai Testnet
62 | */
63 | export var mmresell = "YOUR CONTRACT ADDRESS";
64 | export var mmnftcol = "YOUR CONTRACT ADDRESS";
65 | export var mmnft = "YOUR CONTRACT ADDRESS";
66 | export var mmmarket = "YOUR CONTRACT ADDRESS";
67 | export var mmrpc = "https://matic-testnet-archive-rpc.bwarelabs.com";
68 |
--------------------------------------------------------------------------------
/Part6-Final-Multichain-Integration/engine/connectchain.js:
--------------------------------------------------------------------------------
1 | import { bscChain, polyChain, ethChain, hardChain, bscTest, ethTest, polyTest } from '../engine/chainchange';
2 | import 'sf-font';
3 | import { Col, Dropdown } from '@nextui-org/react';
4 | import React from 'react';
5 | import { useEffect } from 'react';
6 |
7 | export default function ConnectChain() {
8 | const [selected, setSelected] = React.useState(new Set(["Set Network"]));
9 | const selectedValue = React.useMemo(
10 | () => Array.from(selected).join(", ").replaceAll("_", " "),
11 | [selected]
12 | );
13 |
14 | const blockImage = React.useMemo(() => {
15 | var eth = "Ethereum";
16 | var bsc = "Binance Smart Chain";
17 | var pol = "Polygon";
18 | var mum = "Mumbai";
19 | var bsct = "Bsctest";
20 | var goe = "Goerli";
21 | var hard = "Hardhat";
22 | var init = "Set Network";
23 | if (selectedValue == eth) {
24 | return(
25 |
26 | )
27 | }
28 | else if (selectedValue == bsc) {
29 | return(
30 |
31 | )
32 | }
33 | else if (selectedValue == pol) {
34 | return(
35 |
36 | )
37 | }
38 | else if (selectedValue == mum) {
39 | return(
40 | Mumbai Testnet
41 | )
42 | }
43 | else if (selectedValue == bsct) {
44 | return(
45 | BSC Testnet
46 | )
47 | }
48 | else if (selectedValue == goe) {
49 | return(
50 | Goerli Testnet
51 | )
52 | }
53 | else if (selectedValue == hard) {
54 | return(
55 | Hardhat Node
56 | )
57 | }
58 | else if (selectedValue == init) {
59 | return(
60 |
61 |
Select Network
62 |
63 | )
64 | }
65 | })
66 |
67 | async function enableChain() {
68 | var bsc = "Binance Smart Chain";
69 | var poly = "Polygon";
70 | var eth = "Ethereum";
71 | var mum = "Mumbai";
72 | var bsct = "Bsctest";
73 | var goe = "Goerli";
74 | var hard = "Hardhat";
75 | if (bsc == selectedValue) {
76 | bscChain();
77 | } else if (poly == selectedValue) {
78 | polyChain();
79 | } else if (eth == selectedValue) {
80 | ethChain();
81 | } else if (hard == selectedValue) {
82 | hardChain();
83 | } else if (bsct == selectedValue) {
84 | bscTest();
85 | } else if (goe == selectedValue) {
86 | ethTest();
87 | } else if (mum == selectedValue) {
88 | polyTest();
89 | }
90 | }
91 | useEffect(() => {
92 | enableChain();
93 | }, [selected]);
94 |
95 |
96 | return (
97 |
98 |
99 |
112 | {blockImage}
113 |
114 |
126 |
127 |
128 |
129 |
133 |
134 |
135 |
136 |
137 |
138 |
139 | HardHat Node
140 |
141 |
142 | Goerli TestNet
143 |
144 |
145 | BSC TestNet
146 |
147 |
148 | Mumbai TestNet
149 |
150 |
151 |
152 |
153 | );
154 | }
--------------------------------------------------------------------------------
/Part6-Final-Multichain-Integration/pages/_app.js:
--------------------------------------------------------------------------------
1 | import { createTheme, NextUIProvider } from "@nextui-org/react";
2 | import 'sf-font';
3 | import Link from 'next/link'
4 | import { Button, Col, Row, Container } from '@nextui-org/react';
5 | import Footer from './footer';
6 | import Connectchain from "../engine/connectchain";
7 |
8 | const theme = createTheme({
9 | type: "dark",
10 | theme: {
11 | fontFamily:'SF Pro Display',
12 | colors: {
13 | primaryLight: '$blue200',
14 | primaryLightHover: '$blue300',
15 | primaryLightActive: '$blue400',
16 | primaryLightContrast: '$blue600',
17 | primary: '$purple500',
18 | primaryBorder: '$blue500',
19 | primaryBorderHover: '$blue600',
20 | primarySolidHover: '$blue700',
21 | primarySolidContrast: '$white',
22 | primaryShadow: '$white500',
23 | transparent: '#00000000',
24 |
25 | gradient: 'linear-gradient(112deg, $blue100 -25%, $pink500 -10%, $purple300 90%)',
26 | link: '#5E1DAD',
27 |
28 | myColor: '#00000030'
29 |
30 | },
31 | space: {},
32 | fonts: {}
33 | }
34 | })
35 |
36 | function MyApp({ Component, pageProps }) {
37 |
38 | return(
39 |
115 |
116 | )
117 |
118 |
119 | }
120 |
121 | export default MyApp
122 |
--------------------------------------------------------------------------------
/Part6-Final-Multichain-Integration/pages/create.js:
--------------------------------------------------------------------------------
1 | import { ethers } from 'ethers';
2 | import { useState, useEffect } from 'react';
3 | import { useRouter } from 'next/router';
4 | import Web3Modal from "web3modal";
5 | import NFT from '../engine/NFT.json';
6 | import Market from '../engine/Market.json';
7 | import { mmnft, mmmarket } from '../engine/configuration';
8 | import { goenft, goemarket } from '../engine/configuration';
9 | import { hhnft, hhmarket } from '../engine/configuration';
10 | import { bsctnft, bsctmarket } from '../engine/configuration';
11 | import detectEthereumProvider from '@metamask/detect-provider';
12 | import { Card, Button, Input, Col, Row, Spacer, Container, Text } from '@nextui-org/react';
13 | import { client } from '../engine/configuration';
14 | import 'sf-font';
15 |
16 | export default function createMarket() {
17 | const [fileUrl, setFileUrl] = useState(null)
18 | const [nftcontract, getNft] = useState([])
19 | const [market, getMarket] = useState([])
20 |
21 | const [formInput, updateFormInput] = useState({ price: '', name: '', description: '' })
22 |
23 | useEffect(() => {
24 | setNft();
25 | }, [getNft, getMarket])
26 |
27 | const router = useRouter()
28 |
29 | async function onChange(e) {
30 | const file = e.target.files[0]
31 | try {
32 | const added = await client.add(
33 | file,
34 | {
35 | progress: (prog) => console.log(`received: ${prog}`)
36 | }
37 | )
38 | const url = `https://ipfs.infura.io/ipfs/${added.path}`
39 | setFileUrl(url)
40 | } catch (error) {
41 | console.log('Error uploading file: ', error)
42 | }
43 | }
44 |
45 | async function createMarket() {
46 | const { name, description, price } = formInput
47 | if (!name || !description || !price || !fileUrl) return
48 | const data = JSON.stringify({
49 | name, description, image: fileUrl
50 | })
51 | try {
52 | const added = await client.add(data)
53 | const url = `https://ipfs.infura.io/ipfs/${added.path}`
54 | createNFT(url)
55 | } catch (error) {
56 | console.log('Error uploading file: ', error)
57 | }
58 | }
59 |
60 | async function setNft(){
61 | const web3Modal = new Web3Modal()
62 | await web3Modal.connect();
63 | var hh = "0x7a69";
64 | var goe = "0x5";
65 | var mm = "0x13881";
66 | var bsct = "0x61";
67 | const connected = await detectEthereumProvider();
68 | if (connected.chainId == hh) {
69 | var nftcontract = hhnft
70 | }
71 | else if (connected.chainId == goe) {
72 | var nftcontract = goenft
73 | }
74 | else if (connected.chainId == mm) {
75 | var nftcontract = mmnft
76 | }
77 | else if (connected.chainId == bsct) {
78 | var nftcontract = bsctnft
79 | }
80 | getNft(nftcontract);
81 | console.log(nftcontract)
82 | setMarket();
83 | }
84 |
85 | async function setMarket(){
86 | var hh = "0x7a69";
87 | var goe = "0x5";
88 | var mm = "0x13881";
89 | var bsct = "0x61";
90 | const connected = await detectEthereumProvider();
91 | if (connected.chainId == hh) {
92 | var market = hhmarket
93 | }
94 | else if (connected.chainId == goe) {
95 | var market = goemarket
96 | }
97 | else if (connected.chainId == mm) {
98 | var market = mmmarket
99 | }
100 | else if (connected.chainId == bsct) {
101 | var market = bsctmarket
102 | }
103 | getMarket(market);
104 | console.log(market)
105 | }
106 |
107 | async function createNFT(url) {
108 | const web3Modal = new Web3Modal()
109 | const connection = await web3Modal.connect()
110 | const provider = new ethers.providers.Web3Provider(connection)
111 | const signer = provider.getSigner()
112 | let contract = new ethers.Contract(nftcontract, NFT, signer)
113 | let transaction = await contract.createNFT(url)
114 | let tx = await transaction.wait()
115 | let event = tx.events[0]
116 | let value = event.args[2]
117 | let tokenId = value.toNumber()
118 | const price = ethers.utils.parseUnits(formInput.price, 'ether')
119 | contract = new ethers.Contract(market, Market, signer)
120 | let listingFee = await contract.listingFee()
121 | listingFee = listingFee.toString()
122 | transaction = await contract.createVaultItem(nftcontract, tokenId, price, { value: listingFee })
123 | await transaction.wait()
124 | router.push('/')
125 | }
126 |
127 | async function buyNFT() {
128 | const { name, description } = formInput
129 | if (!name || !description || !fileUrl) return
130 | const data = JSON.stringify({
131 | name, description, image: fileUrl
132 | })
133 | try {
134 | const added = await client.add(data)
135 | const url = `https://ipfs.infura.io/ipfs/${added.path}`
136 | mintNFT(url)
137 | } catch (error) {
138 | console.log('Error uploading file: ', error)
139 | }
140 | }
141 |
142 | async function mintNFT(url) {
143 | const web3Modal = new Web3Modal()
144 | const connection = await web3Modal.connect()
145 | const provider = new ethers.providers.Web3Provider(connection)
146 | const signer = provider.getSigner()
147 | let contract = new ethers.Contract(nftcontract, NFT, signer)
148 | let cost = await contract.cost()
149 | let transaction = await contract.mintNFT(url, { value: cost })
150 | await transaction.wait()
151 | router.push('/portal')
152 | }
153 |
154 | return (
155 |
235 | )
236 | }
237 |
--------------------------------------------------------------------------------
/Part6-Final-Multichain-Integration/pages/portal.js:
--------------------------------------------------------------------------------
1 | import { ethers } from 'ethers';
2 | import { useState, useEffect } from 'react';
3 | import Web3Modal from "web3modal";
4 | import { useRouter } from 'next/router';
5 | import Resell from '../engine/Resell.json';
6 | import NFTCollection from '../engine/NFTCollection.json';
7 | import NFT from '../engine/NFT.json';
8 | import { polyTest, ethTest, bscTest } from '../engine/chainchange';
9 | import { Card, Button, Input, Col, Row, Spacer, Container, Text, Grid } from '@nextui-org/react';
10 | import axios from 'axios';
11 | import 'sf-font';
12 | import Web3 from 'web3';
13 | import detectEthereumProvider from '@metamask/detect-provider';
14 | import { mmnft, mmresell, mmnftcol, mmrpc } from '../engine/configuration';
15 | import { goenft, goeresell, goenftcol, goerpc } from '../engine/configuration';
16 | import { hhnft, hhresell, hhnftcol, hhrpc } from '../engine/configuration';
17 | import { bsctnft, bsctresell, bsctnftcol, bsctrpc } from '../engine/configuration';
18 | import { cipherEth, simpleCrypto } from '../engine/configuration';
19 |
20 | export default function Sell() {
21 | const [user, getUser] = useState([])
22 | const [chain, getChainName] = useState([])
23 | const [rpc, getRpc] = useState([])
24 | const [nftcol, getNftCol] = useState([])
25 | const [nftcustom, getNftCustom] = useState([])
26 | const [nftresell, getNftResell] = useState([])
27 | const [created, getCreated] = useState([])
28 | const [resalePrice, updateresalePrice] = useState({ price: ''})
29 | const [nfts, setNfts] = useState([])
30 | const [loadingState, setLoadingState] = useState('not-loaded')
31 | useEffect(() => {
32 | getChain();
33 | setRpc();
34 | }, [setNfts,getUser, getCreated])
35 | const router = useRouter()
36 |
37 | async function setRpc(){
38 | var hh = "0x7a69";
39 | var goe = "0x5";
40 | var mm = "0x13881";
41 | var bsct = "0x61";
42 | const connected = await detectEthereumProvider();
43 | if (connected.chainId == hh) {
44 | var mainnet = hhrpc
45 | }
46 | else if (connected.chainId == goe) {
47 | var mainnet = goerpc
48 | }
49 | else if (connected.chainId == mm) {
50 | var mainnet = mmrpc
51 | }
52 | else if (connected.chainId == bsct) {
53 | var mainnet = bsctrpc
54 | }
55 | getRpc(mainnet);
56 | console.log(mainnet)
57 | setNftCol();
58 | }
59 |
60 | async function setNftCol(){
61 | var hh = "0x7a69";
62 | var goe = "0x5";
63 | var mm = "0x13881";
64 | var bsct = "0x61";
65 | const connected = await detectEthereumProvider();
66 | if (connected.chainId == hh) {
67 | var nftcol = hhnftcol
68 | }
69 | else if (connected.chainId == goe) {
70 | var nftcol = goenftcol
71 | }
72 | else if (connected.chainId == mm) {
73 | var nftcol = mmnftcol
74 | }
75 | else if (connected.chainId == bsct) {
76 | var nftcol = bsctnftcol
77 | }
78 | getNftCol(nftcol);
79 | console.log(nftcol)
80 | setNftCustom();
81 | }
82 |
83 | async function setNftCustom(){
84 | var hh = "0x7a69";
85 | var goe = "0x5";
86 | var mm = "0x13881";
87 | var bsct = "0x61";
88 | const connected = await detectEthereumProvider();
89 | if (connected.chainId == hh) {
90 | var nft = hhnft
91 | }
92 | else if (connected.chainId == goe) {
93 | var nft = goenft
94 | }
95 | else if (connected.chainId == mm) {
96 | var nft = mmnft
97 | }
98 | else if (connected.chainId == bsct) {
99 | var nft = bsctnft
100 | }
101 | getNftCustom(nft);
102 | console.log(nft)
103 | setNftResell();
104 | }
105 |
106 | async function setNftResell(){
107 | var hh = "0x7a69";
108 | var goe = "0x5";
109 | var mm = "0x13881";
110 | var bsct = "0x61";
111 | const connected = await detectEthereumProvider();
112 | if (connected.chainId == hh) {
113 | var nftresell = hhresell
114 | }
115 | else if (connected.chainId == goe) {
116 | var nftresell = goeresell
117 | }
118 | else if (connected.chainId == mm) {
119 | var nftresell = mmresell
120 | }
121 | else if (connected.chainId == bsct) {
122 | var nftresell = bsctresell
123 | }
124 | getNftResell(nftresell);
125 | console.log(nftresell)
126 | }
127 |
128 | async function getChain(){
129 | var hh = "0x7a69";
130 | var goe = "0x5";
131 | var mm = "0x13881";
132 | var bsct = "0x61";
133 | const connected = await detectEthereumProvider();
134 | if (connected.chainId == hh) {
135 | var chainname = "HardHat"
136 | }
137 | else if (connected.chainId == goe) {
138 | var chainname = "Goerli Testnet"
139 | }
140 | else if (connected.chainId == mm) {
141 | var chainname = "Mumbai Testnet"
142 | }
143 | else if (connected.chainId == bsct) {
144 | var chainname = "BSC Testnet"
145 | }
146 | getChainName(chainname);
147 | console.log(chainname)
148 | }
149 |
150 | async function connectUser() {
151 | const web3Modal = new Web3Modal()
152 | const connection = await web3Modal.connect()
153 | const provider = new ethers.providers.Web3Provider(connection);
154 | const signer = provider.getSigner();
155 | console.log(signer);
156 | if (window.ethereum) {
157 | var web3 = new Web3(window.ethereum);
158 | await window.ethereum.send("eth_requestAccounts");
159 | var accounts = await web3.eth.getAccounts();
160 | var account = accounts[0];
161 | }
162 | getUser(account);
163 | }
164 |
165 | async function getWalletNFTs() {
166 | var address = nftcol
167 | var network = rpc
168 | console.log(address)
169 | const provider = new ethers.providers.JsonRpcProvider(network)
170 | const key = simpleCrypto.decrypt(cipherEth)
171 | const wallet = new ethers.Wallet(key, provider);
172 | const contract = new ethers.Contract(address, NFTCollection, wallet)
173 | const itemArray = [];
174 | contract.totalSupply().then(result => {
175 | for (let i = 0; i < result; i++) {
176 | var token = i + 1
177 | const owner = contract.ownerOf(token).catch(function (error) {
178 | console.log("tokens filtered");
179 | });
180 | const rawUri = contract.tokenURI(token).catch(function (error) {
181 | console.log("tokens filtered");
182 | });
183 | const Uri = Promise.resolve(rawUri)
184 | const getUri = Uri.then(value => {
185 | var cleanUri = value.replace('ipfs://', 'https://ipfs.io/ipfs/')
186 | let metadata = axios.get(cleanUri).catch(function (error) {
187 | console.log(error.toJSON());
188 | });
189 | return metadata;
190 | })
191 | getUri.then(value => {
192 | let rawImg = value.data.image
193 | var name = value.data.name
194 | var desc = value.data.description
195 | let image = rawImg.replace('ipfs://', 'https://ipfs.io/ipfs/')
196 | Promise.resolve(owner).then(value => {
197 | let ownerW = value;
198 | let meta = {
199 | name: name,
200 | img: image,
201 | tokenId: token,
202 | wallet: ownerW,
203 | desc,
204 | }
205 | console.log(meta)
206 | itemArray.push(meta)
207 | })
208 | })
209 | }
210 | })
211 | await new Promise(r => setTimeout(r, 2000));
212 | setNfts(itemArray)
213 | setLoadingState('loaded');
214 | }
215 |
216 |
217 | async function getCreatedNFTs() {
218 | var address = nftcustom
219 | var network = rpc
220 | const provider = new ethers.providers.JsonRpcProvider(network)
221 | const key = simpleCrypto.decrypt(cipherEth)
222 | const wallet = new ethers.Wallet(key, provider);
223 | const contract = new ethers.Contract(address, NFT, wallet)
224 | const itemArray = [];
225 | contract._tokenIds().then(result => {
226 | for (let i = 0; i < result; i++) {
227 | var token = i + 1
228 | const owner = contract.ownerOf(token).catch(function (error) {
229 | console.log("tokens filtered");
230 | });
231 | const rawUri = contract.tokenURI(token).catch(function (error) {
232 | console.log("tokens filtered");
233 | });
234 | const Uri = Promise.resolve(rawUri)
235 | const getUri = Uri.then(value => {
236 | var cleanUri = value.replace('ipfs://', 'https://ipfs.io/ipfs/')
237 | let metadata = axios.get(cleanUri).catch(function (error) {
238 | console.log(error.toJSON());
239 | });
240 | return metadata;
241 | })
242 | getUri.then(value => {
243 | let rawImg = value.data.image
244 | var name = value.data.name
245 | var desc = value.data.description
246 | let image = rawImg.replace('ipfs://', 'https://ipfs.io/ipfs/')
247 | Promise.resolve(owner).then(value => {
248 | let ownerW = value;
249 | let meta = {
250 | name: name,
251 | img: image,
252 | tokenId: token,
253 | wallet: ownerW,
254 | desc,
255 | }
256 | console.log(meta)
257 | itemArray.push(meta)
258 | })
259 | })
260 | }
261 | })
262 | await new Promise(r => setTimeout(r, 2000));
263 | getCreated(itemArray)
264 | setLoadingState('loaded');
265 | }
266 |
267 | async function refreshNFTs(){
268 | connectUser();
269 | setRpc();
270 | getCreatedNFTs();
271 | getWalletNFTs();
272 | getChain();
273 | }
274 |
275 | async function connectWallet(){
276 | connectUser();
277 | setRpc();
278 | getChain();
279 | }
280 |
281 |
282 |
283 | if (loadingState === 'loaded' && !nfts.length)
284 | return (
285 |
286 |
287 |
288 | No NFT's Found, Connect Wallet
289 |
295 | Refresh
296 |
297 |
298 |
299 |
300 |
301 | )
302 | return (
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 | Switch Blockchain
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 | Wallet
325 |
326 | {user}
327 |
328 |
329 | Selected Chain: {chain}
330 |
331 |
337 | Connect
338 |
339 |
345 | Refresh
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 | {nfts.map((nft, i) => {
355 | var owner = user;
356 | if (owner.indexOf(nft.wallet) !== -1) {
357 | async function executeRelist() {
358 | const { price } = resalePrice;
359 | if (!price) return;
360 | try {
361 | relistNFT();
362 | } catch (error) {
363 | console.log("Transaction Failed", error);
364 | }
365 | }
366 | async function relistNFT() {
367 | var resell = nftresell
368 | const web3Modal = new Web3Modal();
369 | const connection = await web3Modal.connect();
370 | const provider = new ethers.providers.Web3Provider(connection);
371 | const signer = provider.getSigner();
372 | const price = ethers.utils.parseUnits(
373 | resalePrice.price,
374 | "ether"
375 | );
376 | const contractnft = new ethers.Contract(
377 | nftcol,
378 | NFTCollection,
379 | signer
380 | );
381 | await contractnft.setApprovalForAll(resell, true);
382 | let contract = new ethers.Contract(resell, Resell, signer);
383 | let listingFee = await contract.getListingFee();
384 | listingFee = listingFee.toString();
385 | let transaction = await contract.listSale(nft.tokenId, price, {
386 | value: listingFee,
387 | });
388 | await transaction.wait();
389 | router.push("/");
390 | }
391 | return (
392 |
393 |
394 |
400 |
401 |
402 |
408 | Owned by You
409 |
410 |
411 | {nft.name} Token-{nft.tokenId}
412 |
413 | {nft.desc}
414 |
430 | updateresalePrice({
431 | ...resalePrice,
432 | price: e.target.value,
433 | })
434 | }
435 | />
436 |
442 | Relist for Sale
443 |
444 |
445 |
446 |
447 |
448 | );
449 | }
450 | })}
451 |
452 |
453 |
454 |
455 |
456 | Personal NFTs
457 |
458 |
459 | {created.map((nft, i) => {
460 | var owner = user;
461 | if (owner.indexOf(nft.wallet) !== -1) {
462 | return (
463 |
464 |
465 |
471 |
472 |
473 |
479 | Owned by You
480 |
481 |
482 | {nft.name} Token-{nft.tokenId}
483 |
484 | {nft.desc}
485 |
486 |
487 |
488 |
489 | );
490 | }
491 | })}
492 |
493 |
494 |
495 |
496 | )
497 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | Multi-Chain NFT Marketplace
3 | ##
4 | 🚀👩🚀This repo contains all the files to follow along and implement a MultiChain NFT MarketPlace! Be sure to watch my Youtube tutorials so you can learn and follow along!
5 |
6 | ** THE FILES ATTACHED TO THIS REPO ARE FOR EDUCATIONAL PURPOSES ONLY **
7 |
8 | ** NOT FINANCIAL ADVISE **
9 |
10 | ** USE IT AT YOUR OWN RISK** **I'M NOT RESPONSIBLE FOR ANY USE, ISSUES ETC.. **
11 |
12 | Please follow instructions for the video tutorial you are watching.
13 |
14 | ## Part-1 Hardhat and EthersJS
15 |
16 | Click for video:
17 |
18 |
19 |
20 | Steps:
21 |
22 | 1-Create an new NextJS app:
23 |
24 | ```shell
25 | npx create-next-app n2dmarket
26 | ```
27 |
28 | 2- Install hardhat in the n2dmarket project folder.
29 |
30 | ```shell
31 | npm i hardhat
32 | ```
33 |
34 | 3- Create a hardhat environment.
35 |
36 | ```shell
37 | npx hardhat
38 | ```
39 |
40 | 4- Refer to the Hardhat and EthersJS knowledge base and
41 | practice some info gathering using the hardhat console:
42 |
43 | ```shell
44 | npx hardhat console
45 | ```
46 |
47 | Hardhat Knowledge Base : https://hardhat.org/tutorial
48 |
49 | EthersJS Knowledge Base: https://docs.ethers.io/v5/
50 |
51 | ## Part-2 NFT Market Resell Smart Contract
52 |
53 | Click for video:
54 |
55 |
56 |
57 |
58 | 1-Retrieve the NFT Collection Smart Contract Address.
59 |
60 | 2-Deploy the NFT Market Resell Smart Contract located in Part2 Folder.
61 |
62 | Add the NFT Collection Address when deploying the smart contract.
63 |
64 | ## Part-3 Deploy a NextJS WebFront End
65 |
66 | Click for video:
67 |
68 |
69 |
70 | Steps:
71 |
72 | 1- Navigate to your n2dmarket project folder and install the remaining dependencies:
73 |
74 | ```shell
75 | npm i --save-dev "@types/react"
76 |
77 | npm i axios @nextui-org/react sf-font
78 |
79 | npm i simple-crypto-js web3modal
80 |
81 | npm i @metamask/detect-provider
82 |
83 | npm i ipfs-http-client
84 |
85 | npm i web3
86 |
87 | npm i --save-dev @types/canvas-confetti
88 | ```
89 |
90 | 2- Proceed to replace the files in your n2dmarket folder with each respective
91 |
92 | file attached in the Part-3 Folder, Add the "engine" folder to the project root folder.
93 |
94 |
95 | 3- Deploy your test NFT Collection and NFT Market Resell Smart Contracts (refer to Part2 Vid)
96 |
97 | and go to /engine/configuration and update the values accordingly:
98 |
99 | ```shell
100 |
101 | export var hhresell = "YOUR NFT RESELL MARKET SMART CONTRACT";
102 |
103 | export var hhnftcol = "YOUR NFT COLLECTION SMART CONTRACT";
104 |
105 | var hhrpc = "YOUR MAINNET OR TESTNET RPC ADDRESS";
106 | ```
107 |
108 | List of RPC Address to use depending on which testnet the contracts have been deployed:
109 |
110 | Polygon Mumbai: https://matic-mumbai.chainstacklabs.com
111 |
112 | BSC Testnet: https://data-seed-prebsc-1-s3.binance.org:8545
113 |
114 | ETH Goerli: https://rpc.ankr.com/eth_goerli
115 |
116 | CTRL + S to save configs
117 |
118 | Run the web server and validate:
119 |
120 | ```shell
121 | npm run dev
122 | ```
123 |
124 | Watch part 3 vid for more details.
125 |
126 | ## Part-4 Relist and Buy NFTs!
127 |
128 | Click for video:
129 |
130 |
131 |
132 | Steps:
133 |
134 | 1- New changes have been performed on the Resell SmartContract.
135 | Redeploy it on your favorite testnet and save the address.
136 |
137 | Contract link:
138 |
139 | https://github.com/net2devcrypto/N2D-NFT-Marketplace/tree/main/Part2-NFT-Market-Resell-Contract
140 |
141 | 2- Install NFT Carousel Dependency:
142 |
143 | ```shell
144 | npm i --save-dev react-multi-carousel
145 | ```
146 |
147 | 3- Proceed to replace the files in your market project folder with each respective
148 |
149 | file attached in the Part-4 Folder, Replace "engine" and "public" folder with all files as well.
150 |
151 |
152 | 4- Obtain your Resell Smart Contract Owner Wallet Private Key. (Wallet used to deploy contract)
153 |
154 | Go to /engine/configuration and update the values accordingly:
155 |
156 | Replace with your Private key in "hhraw":
157 |
158 | ```shell
159 | const hhraw = "0xREPLACEWITHPRIVATEKEY";
160 | ```
161 |
162 | Add your smart contract addresses here:
163 |
164 | ```shell
165 | export var hhresell = "YOUR NFT RESELL MARKET SMART CONTRACT";
166 |
167 | export var hhnftcol = "YOUR NFT COLLECTION SMART CONTRACT";
168 |
169 | var hhrpc = "REPLACE WITH THE TESTNET RPC";
170 | ```
171 |
172 | CTRL + S to save configs
173 |
174 | Run the web server and validate:
175 |
176 | ```shell
177 | npm run dev
178 | ```
179 | Watch part 4 vid for more details.
180 |
181 | ## Part-5 Create The NFT Marketplace Contract and App to upload Art and mint NFTs.
182 |
183 | Click for video:
184 |
185 |
186 |
187 |
188 | 1-Deploy the Marketplace Contract to sell created NFTs located in Part5 Folder repo. Copy the contract address.
189 |
190 | https://github.com/net2devcrypto/N2D-NFT-Marketplace/blob/main/Part5-Create-and-Sell-NFT-App/N2D-Market-SellCreatedNFT-SmartContract.sol
191 |
192 | 2-Deploy the NFT Smart Contract to create NFTs located in Part5 Folder, add the NFT Market smart contract to sell created NFTs when deploying and copy the contract address once deployed.
193 |
194 | https://github.com/net2devcrypto/N2D-NFT-Marketplace/blob/main/Part5-Create-and-Sell-NFT-App/N2D-Market-CreateNFT-SmartContract.sol
195 |
196 | 3- Go to /engine/configuration and add the additional contracts accordingly:
197 |
198 | ```shell
199 |
200 | export var hhnft = "YOUR CREATE NFT SMART CONTRACT";
201 |
202 | export var hhmarket = "YOUR SELL CREATED NFT MARKETPLACE SMART CONTRACT";
203 |
204 | ```
205 |
206 | 4- From Part5 Folder, Proceed to add the NFT and Market ABI files to the engine folder. Proceed to replace the files in your project with the ones provided in the Part5 folder. Test and practice. Time to learn more!
207 |
208 | Watch Part 5 video for more info.
209 |
210 | ## Part-6 Final Video - Enable Multichain Integration!
211 |
212 | Click for video:
213 |
214 |
215 |
216 |
217 | 1- Stop NextJS Server and Replace all files in your project with the files attached on this repo to their respective folders.
218 |
219 | 2-Deploy all required smart contracts for all networks and update the contract address in the configuration.js file located in the "engine" folder.
220 |
221 | Deploy the contracts on all required testnets. The "nftcol" is an existing nft collection smartcontract.
222 |
223 | resell smartcontract : https://github.com/net2devcrypto/N2D-NFT-Marketplace/blob/main/Part2-NFT-Market-Resell-Contract/N2D-Market-NFT-Resell-SmartContract.sol
224 |
225 | nft smartcontract: https://github.com/net2devcrypto/N2D-NFT-Marketplace/blob/main/Part5-Create-and-Sell-NFT-App/N2D-Market-CreateNFT-SmartContract.sol
226 |
227 | market smartcontract: https://github.com/net2devcrypto/N2D-NFT-Marketplace/blob/main/Part5-Create-and-Sell-NFT-App/N2D-Market-SellCreatedNFT-SmartContract.sol
228 |
229 | Example for Goerli Testnet
230 |
231 | ```shell
232 | export var goeresell = "YOUR CONTRACT ADDRESS";
233 | export var goenftcol = "YOUR CONTRACT ADDRESS";
234 | export var goenft = "YOUR CONTRACT ADDRESS";
235 | export var goemarket = "YOUR CONTRACT ADDRESS";
236 | ```
237 |
238 | Save your changes!
239 |
240 | 3- Install Metamask detect provider dependency in your project folder.
241 |
242 | ```shell
243 | npm i @metamask/detect-provider
244 | ```
245 |
246 | 4- Start NextJS server and follow the video for additional testing and practice steps.
247 |
248 |
249 |
--------------------------------------------------------------------------------
/n2DMarket.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/net2devcrypto/N2D-NFT-Marketplace/a8d9ada82ef143eb3df282c3d0c7f4cf0b5bf6af/n2DMarket.png
--------------------------------------------------------------------------------