forked from eQereum/truffle-web3-nft-marketplace
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
truffle-web3-nft-marketplace Genesis
- Loading branch information
0 parents
commit 80f39af
Showing
15 changed files
with
557 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# NFT Marketplace with Truffle/Web3js | ||
|
||
This project represents deploying of NFT (ERC721) contract & NFT Marketplace for trading NFT tokens. You can also compare this project with **Hardhat/Ethers** version of it that published earlier in [**here**](https://github.com/0xhamedETH/hardhat-ethers-nextjs-nft-marketplace). This would be useful for learning both pack of tools. | ||
|
||
### Clone the repository | ||
|
||
```shell | ||
git clone --recursive https://github.com/0xhamedETH/truffle-web3-nft-marketplace.git your-directory | ||
``` | ||
|
||
### Install Packages | ||
|
||
```shell | ||
cd your-directory/ethereum | ||
npm install | ||
``` | ||
|
||
### Compile | ||
|
||
compile first to create json artifacts in `build` folder | ||
|
||
```shell | ||
truffle compile | ||
``` | ||
|
||
### Test | ||
|
||
- Run `ganache-cli` in separate terminal | ||
|
||
```shell | ||
ganache-cli | ||
``` | ||
|
||
- Run `truffle test` in main terminal | ||
|
||
```shell | ||
truffle test test/nft.test.js | ||
``` | ||
|
||
### Deploy | ||
|
||
For this step you first need to fill `.env` file with your api keys (`Alchemy`, ...) | ||
|
||
You can deploy both contracts in any network you want (make sure `truffle-config.js` contains that network) | ||
|
||
for example: `maticMumbai` | ||
|
||
```shell | ||
truffle migrate --reset --network maticMumbai | ||
``` | ||
|
||
After a while, you would see deployment transaction details of both NFT and NFTMarketplace contracts in console. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
MNEMONIC = "12 keywords" | ||
INFURA_PROJECT_ID=... | ||
ALCHEMY_API_ID=... | ||
ETHERSCAN_TEST_API_KEY=... | ||
BSCSCAN_TEST_API_KEY=... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
import './NFT/NFTLogics.sol'; | ||
|
||
pragma solidity ^0.8.13; | ||
|
||
contract NFT is NFTLogics { | ||
constructor(address _marketplaceAddress) ERC721('My Digital Marketplace', 'MDM') { | ||
marketplaceAddress = _marketplaceAddress; | ||
} | ||
|
||
function createToken(string memory tokenURI) public returns (uint256) { | ||
return _createToken(tokenURI); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.13; | ||
|
||
interface INFT { | ||
event CreateTokenLog(uint256 indexed tokenId, string indexed tokenURI); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
import './INFT.sol'; | ||
import '@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol'; | ||
|
||
pragma solidity ^0.8.13; | ||
|
||
abstract contract NFTContext is ERC721URIStorage, INFT { | ||
address internal owner; | ||
uint256 internal _tokenIds; | ||
address public marketplaceAddress; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// SPDX-License-Identifier: MIT | ||
import './NFTContext.sol'; | ||
pragma solidity ^0.8.13; | ||
|
||
abstract contract NFTLogics is NFTContext { | ||
function _createToken(string memory tokenURI) internal returns (uint256) { | ||
_tokenIds++; | ||
uint256 newItemId = _tokenIds; | ||
|
||
_mint(msg.sender, newItemId); | ||
_setTokenURI(newItemId, tokenURI); | ||
setApprovalForAll(marketplaceAddress, true); | ||
emit CreateTokenLog(newItemId, tokenURI); | ||
return newItemId; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// SPDX-License-Identifier: MIT | ||
import './NFTMarketplace/NFTMarketplaceLogics.sol'; | ||
import './NFTMarketplace/NFTMarketplaceModifiers.sol'; | ||
|
||
pragma solidity ^0.8.13; | ||
|
||
contract NFTMarketplace is NFTMarketplaceModifiers, NFTMarketPlaceLogics { | ||
constructor() { | ||
owner = payable(msg.sender); | ||
} | ||
|
||
function createMarketItem( | ||
address nftContract, | ||
uint256 tokenId, | ||
uint256 price | ||
) public payable nonReentrant { | ||
_createMarketItem(nftContract, tokenId, price); | ||
} | ||
|
||
function buyItem(address nftContract, uint256 itemId) public payable nonReentrant { | ||
_buyItem(nftContract, itemId); | ||
} | ||
|
||
function fetchUnsoldMarketItems() public view returns (MarketItem[] memory) { | ||
return _fetchUnsoldMarketItems(); | ||
} | ||
|
||
function fetchMyNFTsBoughtFromMarketplace() public view returns (MarketItem[] memory) { | ||
return _fetchMyNFTsBoughtFromMarketplace(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
import '@openzeppelin/contracts/token/ERC721/IERC721.sol'; | ||
|
||
pragma solidity ^0.8.13; | ||
|
||
interface INFTMarketplace { | ||
struct MarketItem { | ||
uint256 itemId; | ||
address nftContract; | ||
uint256 tokenId; | ||
address payable seller; | ||
address payable owner; | ||
uint256 price; | ||
} | ||
|
||
event CreateMarketItemLog(uint256 indexed itemId, address indexed nftContract, uint256 indexed tokenId, address seller, address owner, uint256 price); | ||
event ItemSoldLog(uint256 indexed itemId, address indexed nftContract, uint256 indexed tokenId, address oldOwner, address newOwner); | ||
|
||
function createMarketItem( | ||
address nftContract, | ||
uint256 tokenId, | ||
uint256 price | ||
) external payable; | ||
|
||
function buyItem(address nftContract, uint256 itemId) external payable; | ||
|
||
function fetchUnsoldMarketItems() external view returns (MarketItem[] memory); | ||
|
||
function fetchMyNFTsBoughtFromMarketplace() external view returns (MarketItem[] memory); | ||
} |
14 changes: 14 additions & 0 deletions
14
ethereum/contracts/NFTMarketplace/NFTMarketplaceContext.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
import './INFTMarketplace.sol'; | ||
|
||
pragma solidity ^0.8.13; | ||
|
||
abstract contract NFTMarketplaceContext is INFTMarketplace { | ||
uint256 internal _itemIds; | ||
uint256 internal _itemsSold; | ||
|
||
address payable owner; | ||
uint256 listingPrice = 0.1 ether; | ||
mapping(uint256 => MarketItem) public idToMarketItem; | ||
} |
78 changes: 78 additions & 0 deletions
78
ethereum/contracts/NFTMarketplace/NFTMarketplaceLogics.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
import './NFTMarketplaceContext.sol'; | ||
|
||
pragma solidity ^0.8.13; | ||
|
||
abstract contract NFTMarketPlaceLogics is NFTMarketplaceContext { | ||
function _createMarketItem( | ||
address nftContract, | ||
uint256 tokenId, | ||
uint256 price | ||
) internal { | ||
require(IERC721(nftContract).ownerOf(tokenId) == msg.sender, 'only owner of tokenId can create corresponding item'); | ||
require(price > 0, 'item price must be at least 1 wei'); | ||
require(msg.value == listingPrice, 'listing price is 0.1 ether'); | ||
|
||
_itemIds++; | ||
uint256 itemId = _itemIds; | ||
idToMarketItem[itemId] = MarketItem(itemId, nftContract, tokenId, payable(msg.sender), payable(address(0)), price); | ||
IERC721(nftContract).transferFrom(msg.sender, address(this), tokenId); | ||
emit CreateMarketItemLog(itemId, nftContract, tokenId, msg.sender, address(0), price); | ||
} | ||
|
||
function _buyItem(address nftContract, uint256 itemId) internal { | ||
uint256 price = idToMarketItem[itemId].price; | ||
uint256 tokenId = idToMarketItem[itemId].tokenId; | ||
require(msg.value == price, 'submitted price differs from item price'); | ||
|
||
idToMarketItem[itemId].seller.transfer(msg.value); | ||
IERC721(nftContract).transferFrom(address(this), msg.sender, tokenId); | ||
idToMarketItem[itemId].owner = payable(msg.sender); | ||
_itemsSold++; | ||
payable(owner).transfer(listingPrice); | ||
emit ItemSoldLog(itemId, nftContract, tokenId, idToMarketItem[itemId].seller, idToMarketItem[itemId].owner); | ||
} | ||
|
||
function _fetchUnsoldMarketItems() internal view returns (MarketItem[] memory) { | ||
uint256 itemCount = _itemIds; | ||
uint256 unsoldItemCount = _itemIds - _itemsSold; | ||
uint256 currentIndex = 0; | ||
|
||
MarketItem[] memory items = new MarketItem[](unsoldItemCount); | ||
for (uint256 i = 0; i < itemCount; i++) { | ||
if (idToMarketItem[i + 1].owner == address(0)) { | ||
uint256 currentId = i + 1; | ||
MarketItem storage currentItem = idToMarketItem[currentId]; | ||
items[currentIndex] = currentItem; | ||
currentIndex += 1; | ||
} | ||
} | ||
|
||
return items; | ||
} | ||
|
||
function _fetchMyNFTsBoughtFromMarketplace() internal view returns (MarketItem[] memory) { | ||
uint256 totalItemCount = _itemIds; | ||
uint256 itemCount = 0; | ||
uint256 currentIndex = 0; | ||
|
||
for (uint256 i = 0; i < totalItemCount; i++) { | ||
if (idToMarketItem[i + 1].owner == msg.sender) { | ||
itemCount += 1; | ||
} | ||
} | ||
|
||
MarketItem[] memory items = new MarketItem[](itemCount); | ||
for (uint256 i = 0; i < totalItemCount; i++) { | ||
if (idToMarketItem[i + 1].owner == msg.sender) { | ||
uint256 currentId = i + 1; | ||
MarketItem storage currentItem = idToMarketItem[currentId]; | ||
items[currentIndex] = currentItem; | ||
currentIndex += 1; | ||
} | ||
} | ||
|
||
return items; | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
ethereum/contracts/NFTMarketplace/NFTMarketplaceModifiers.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
|
||
import '@openzeppelin/contracts/security/ReentrancyGuard.sol'; | ||
|
||
pragma solidity ^0.8.13; | ||
|
||
abstract contract NFTMarketplaceModifiers is ReentrancyGuard {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
const NFTMarketplace = artifacts.require('NFTMarketplace'); | ||
const NFT = artifacts.require('NFT'); | ||
|
||
module.exports = function (deployer) { | ||
deployer.deploy(NFTMarketplace).then(function () { | ||
return deployer.deploy(NFT, NFTMarketplace.address); | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"name": "truffle-nft-marketplace", | ||
"version": "1.0.0", | ||
"description": "", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"author": "0xhamedETH", | ||
"license": "MIT", | ||
"dependencies": { | ||
"@openzeppelin/contracts": "^4.5.0", | ||
"@truffle/hdwallet-provider": "^2.0.4", | ||
"ganache-cli": "^6.1.8", | ||
"mocha": "^9.1.2", | ||
"web3": "^1.6.0" | ||
}, | ||
"devDependencies": { | ||
"dotenv": "^16.0.0", | ||
"prettier": "^2.5.1", | ||
"prettier-plugin-solidity": "^1.0.0-beta.19" | ||
} | ||
} |
Oops, something went wrong.