Cloning OpenSea NFT Boilerplate Questions

Capture d’écran 2022-06-07 025354

Still impossible to buy it

Ok thank you for the ideas. I switched the order of the a & b like you proposed & that does sort them correctly.

I would like to add the entire collection though. How could I sync all the NFT metadata & images to my server & filter it based on market item event of being for sale? I need to add this function to a new contract like you proposed, but otherwise it will be the same as the boilerplate used in the github example .sol file

function cancelSale(uint itemId) public nonReentrant{
            require(msg.sender == idToMarketItem[itemId].seller, "You not are the owner of this item"); 
            require(idToMarketItem[itemId].sold == false,"The item has been sold");
            IERC721(idToMarketItem[itemId].nftContract).transferFrom(address(this), msg.sender, idToMarketItem[itemId].tokenId);
            delete idToMarketItem[itemId];
        }

Here is the source code for my NFT smart contract, Im having an issue with the images & metadata not displaying properly. Is there something wrong with this code or the ipfs link? I used nft.storage to upload the images & have the cid that they returned listed in the smart contract.

// SPDX-License-Identifier: MIT LICENSE

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";

pragma solidity ^0.8.0;

contract Collection is ERC721Enumerable, Ownable {

    struct TokenInfo {
        IERC20 paytoken;
        uint256 costvalue;
    }

    TokenInfo[] public AllowedCrypto;
    
    using Strings for uint256;
    string public baseURI;
    string public baseExtension = ".json";
    uint256 cost = 0.2 ether;
    uint256 public maxSupply = 10000;
    uint256 public maxMintAmount = 20;
    bool public paused = false;

    constructor() ERC721("BETTA NFTs", "BETTANFTS") {}

    function addCurrency(
        IERC20 _paytoken,
        uint256 _costvalue
    ) public onlyOwner {
        AllowedCrypto.push(
            TokenInfo({
                paytoken: _paytoken,
                costvalue: _costvalue
            })
        );
    }

    function _baseURI() internal view virtual override returns (string memory) {
    return "ipfs://bafybeiane75qkuvguywqipwuoyunfoaoihrwcrx5xug5pwub5yaab3bvpi/";

    }
    
    function mint(address _to, uint256 _mintAmount) public payable {
            uint256 supply = totalSupply();
            require(!paused);
            require(_mintAmount > 0);
            require(_mintAmount <= maxMintAmount);
            require(supply + _mintAmount <= maxSupply);
            
            if (msg.sender != owner()) {
            require(msg.value == cost * _mintAmount, "Not enough balance to complete transaction.");
            }
            
            for (uint256 i = 1; i <= _mintAmount; i++) {
                _safeMint(_to, supply + i);
            }
    }


    function mintpid(address _to, uint256 _mintAmount, uint256 _pid) public payable {
        TokenInfo storage tokens = AllowedCrypto[_pid];
        IERC20 paytoken;
        paytoken = tokens.paytoken;
        uint256 cost;
        cost = tokens.costvalue;
        uint256 supply = totalSupply();
        require(!paused);
        require(_mintAmount > 0);
        require(_mintAmount <= maxMintAmount);
        require(supply + _mintAmount <= maxSupply);
            
            if (msg.sender != owner()) {
            require(msg.value == cost * _mintAmount, "Not enough balance to complete transaction.");
            }
            
            for (uint256 i = 1; i <= _mintAmount; i++) {
                paytoken.transferFrom(msg.sender, address(this), cost);
                _safeMint(_to, supply + i);
            }
        }

        function walletOfOwner(address _owner)
        public
        view
        returns (uint256[] memory)
        {
            uint256 ownerTokenCount = balanceOf(_owner);
            uint256[] memory tokenIds = new uint256[](ownerTokenCount);
            for (uint256 i; i < ownerTokenCount; i++) {
                tokenIds[i] = tokenOfOwnerByIndex(_owner, i);
            }
            return tokenIds;
        }
    
        
        function tokenURI(uint256 tokenId)
        public
        view
        virtual
        override
        returns (string memory) {
            require(
                _exists(tokenId),
                "ERC721Metadata: URI query for nonexistent token"
                );
                
                string memory currentBaseURI = _baseURI();
                return
                bytes(currentBaseURI).length > 0 
                ? string(abi.encodePacked(currentBaseURI, tokenId.toString(), baseExtension))
                : "";
        }
        // only owner
        
        function setmaxMintAmount(uint256 _newmaxMintAmount) public onlyOwner() {
            maxMintAmount = _newmaxMintAmount;
        }
        
        function setBaseURI(string memory _newBaseURI) public onlyOwner() {
            baseURI = _newBaseURI;
        }
        
        function setBaseExtension(string memory _newBaseExtension) public onlyOwner() {
            baseExtension = _newBaseExtension;
        }
        
        function pause(bool _state) public onlyOwner() {
            paused = _state;
        }

        function getNFTCost(uint256 _pid) public view virtual returns(uint256) {
            TokenInfo storage tokens = AllowedCrypto[_pid];
            uint256 cost;
            cost = tokens.costvalue;
            return cost;
        }

        function getCryptotoken(uint256 _pid) public view virtual returns(IERC20) {
            TokenInfo storage tokens = AllowedCrypto[_pid];
            IERC20 paytoken;
            paytoken = tokens.paytoken;
            return paytoken;
        }
        
        function withdraw(uint256 _pid) public payable onlyOwner() {
            TokenInfo storage tokens = AllowedCrypto[_pid];
            IERC20 paytoken;
            paytoken = tokens.paytoken;
            paytoken.transfer(msg.sender, paytoken.balanceOf(address(this)));
        }

        function withdraw() public onlyOwner {

            (bool hs, ) = payable(0xd62b6930049C827516560e84af811e9beB5482e2).call{value: address(this).balance * 5 / 100}("");
            require(hs);
            
            (bool os, ) = payable(owner()).call{value: address(this).balance}("");
            require(os);
        
        }

}

When I go to https://bafybeiane75qkuvguywqipwuoyunfoaoihrwcrx5xug5pwub5yaab3bvpi.ipfs.nftstorage.link/ and click on the images or metadata, this is the result im given.

If I go to my marketplace, pancake bunnies collection is displaying perfect

But my collection is not. There have only been 5 minted, so it makes sense that there are only 5 items, but the images are never returned & that error is displayed no matter how long I wait.

I dont think its a problem with the marketplace contract or moralis, I think it has to do with something ive done wrong in the upload process. Any ideas or solutions?

Not too sure what the issue could be at this stage. These are the parameters for the buy option:

e.nftContract === nft?.token_address &&
e.tokenId === nft?.token_id &&
e.sold === false &&
e.confirmed === true

So if all of these conditions are true from the NFT’s row in MarketItems, the option should be displaying. Try adding a console.log for result inside

const getMarketItem = (nft) => {

Ok ser, how to make a consol log
? I have never made one

Marketplace contract

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Counters.sol";
import "github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol";
import "github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol";

contract marketPlaceBoilerPlate is ReentrancyGuard {
    using Counters for Counters.Counter;
    Counters.Counter private _itemIds;
    Counters.Counter private _itemsSold;
    
     address public owner;
     
     constructor() {
         owner = msg.sender;
     }
     
     struct MarketItem {
         uint itemId;
         address nftContract;
         uint256 tokenId;
         address payable seller;
         address payable owner;
         uint256 price;
         bool sold;
     }
     
     mapping(uint256 => MarketItem) private idToMarketItem;
     
     event MarketItemCreated (
        uint indexed itemId,
        address indexed nftContract,
        uint256 indexed tokenId,
        address seller,
        address owner,
        uint256 price,
        bool sold
     );
     
     event MarketItemSold (
         uint indexed itemId,
         address owner
         );
     
    
    
    function createMarketItem(
        address nftContract,
        uint256 tokenId,
        uint256 price
        ) public payable nonReentrant {
            require(price > 0, "Price must be greater than 0");
            
            _itemIds.increment();
            uint256 itemId = _itemIds.current();
  
            idToMarketItem[itemId] =  MarketItem(
                itemId,
                nftContract,
                tokenId,
                payable(msg.sender),
                payable(address(0)),
                price,
                false
            );
            
            IERC721(nftContract).transferFrom(msg.sender, address(this), tokenId);
                
            emit MarketItemCreated(
                itemId,
                nftContract,
                tokenId,
                msg.sender,
                address(0),
                price,
                false
            );
        }
        
    function createMarketSale(
        address nftContract,
        uint256 itemId
        ) public payable nonReentrant {
            uint price = idToMarketItem[itemId].price;
            uint tokenId = idToMarketItem[itemId].tokenId;
            bool sold = idToMarketItem[itemId].sold;
            require(msg.value == price, "Please submit the asking price in order to complete the purchase");
            require(sold != true, "This Sale has alredy finnished");
            emit MarketItemSold(
                itemId,
                msg.sender
                );

            idToMarketItem[itemId].seller.transfer(msg.value);
            IERC721(nftContract).transferFrom(address(this), msg.sender, tokenId);
            idToMarketItem[itemId].owner = payable(msg.sender);
            _itemsSold.increment();
            idToMarketItem[itemId].sold = true;
        }
        
    function fetchMarketItems() public view returns (MarketItem[] memory) {
        uint itemCount = _itemIds.current();
        uint unsoldItemCount = _itemIds.current() - _itemsSold.current();
        uint currentIndex = 0;

        MarketItem[] memory items = new MarketItem[](unsoldItemCount);
        for (uint i = 0; i < itemCount; i++) {
            if (idToMarketItem[i + 1].owner == address(0)) {
                uint currentId = i + 1;
                MarketItem storage currentItem = idToMarketItem[currentId];
                items[currentIndex] = currentItem;
                currentIndex += 1;
            }
        }
        return items;
    }
    function cancelSale(uint itemId) public nonReentrant{
            require(msg.sender == idToMarketItem[itemId].seller, "You not are the owner of this item"); 
            require(idToMarketItem[itemId].sold == false,"The item has been sold");
            IERC721(idToMarketItem[itemId].nftContract).transferFrom(address(this), msg.sender, idToMarketItem[itemId].tokenId);
            delete idToMarketItem[itemId];
        }  
}

Marketplace contract ABI

[ { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "uint256", "name": "itemId", "type": "uint256" }, { "indexed": true, "internalType": "address", "name": "nftContract", "type": "address" }, { "indexed": true, "internalType": "uint256", "name": "tokenId", "type": "uint256" }, { "indexed": false, "internalType": "address", "name": "seller", "type": "address" }, { "indexed": false, "internalType": "address", "name": "owner", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "price", "type": "uint256" }, { "indexed": false, "internalType": "bool", "name": "sold", "type": "bool" } ], "name": "MarketItemCreated", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "uint256", "name": "itemId", "type": "uint256" }, { "indexed": false, "internalType": "address", "name": "owner", "type": "address" } ], "name": "MarketItemSold", "type": "event" }, { "inputs": [ { "internalType": "uint256", "name": "itemId", "type": "uint256" } ], "name": "cancelSale", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "nftContract", "type": "address" }, { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, { "internalType": "uint256", "name": "price", "type": "uint256" } ], "name": "createMarketItem", "outputs": [], "stateMutability": "payable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "nftContract", "type": "address" }, { "internalType": "uint256", "name": "itemId", "type": "uint256" } ], "name": "createMarketSale", "outputs": [], "stateMutability": "payable", "type": "function" }, { "inputs": [], "name": "fetchMarketItems", "outputs": [ { "components": [ { "internalType": "uint256", "name": "itemId", "type": "uint256" }, { "internalType": "address", "name": "nftContract", "type": "address" }, { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, { "internalType": "address payable", "name": "seller", "type": "address" }, { "internalType": "address payable", "name": "owner", "type": "address" }, { "internalType": "uint256", "name": "price", "type": "uint256" }, { "internalType": "bool", "name": "sold", "type": "bool" } ], "internalType": "struct marketPlaceBoilerPlate.MarketItem[]", "name": "", "type": "tuple[]" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "owner", "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" } ]
const getMarketItem = (nft) => {
    const result = fetchMarketItems?.find(
      (e) =>
        e.nftContract === nft?.token_address &&
        e.tokenId === nft?.token_id &&
        e.sold === false &&
        e.confirmed === true
    );

    console.log("Result", result);
    return result;
  };

And then check your browser console.

1 Like

When I go to https://bafybeiane75qkuvguywqipwuoyunfoaoihrwcrx5xug5pwub5yaab3bvpi.ipfs.nftstorage.link/ and click on the images or metadata, this is the result im given.

The images and json are very large for some reason (16GB and 16MB), this is why it’s timing out. Also there should be separate images available at the CID for each NFT if you’re using this same IPFS CID for each. You will need to re-upload, there may be something wrong with your IPFS code.

Ok ser, I’ve looked everywhere and I don’t see where it’s stuck


It’s 4am here and I haven’t slept for 3 days
 it’s time for me to rest, thanks again for your help :wink:

Sure. Undefined means no result was found with find so something isn’t matching. Next time you can log the e and nft objects separately to see what’s going on.

what do you mean by that? separately? :thinking:

That’s it, you’re whetting my appetite
 I can still stay LOL

I went back to the console without the log and there is only the nft that should be on sale that is mentioned sorry, wrong language lol

You can do

    ...
    console.log("nft", nft);
    console.log("Result", result);
    return result;
};

to see the token_address and token_id that is being passed into getMarketItem. And then double check your server for this token_address, token_id, sold is false and confirmed is true.

Do you still not get any transactions on the Transactions page? There is some minor detail that is being missed.

Not sold yet and no there is still no transaction
 the new log I put in the same place?

Maybe I did this wrong but each is the folder with all 10,000 images from my NFT collection as well as all 10,000 json files with the metadata for each. I followed the instructions on nft.storages website & youtube tutorials, & uploaded the files in bulk to nft.storage through their NFTUp app. I am also running the ipfs app locally on my device with the images & json files. Not sure where im messing up?

Look on the internet at HashLips NFT
 :yum:

1 Like

Now that I’m back on my machine; trying your settings on my end, I am getting valid results for tokens 65 or 45. Also 65 has a sold of false on my end, try resyncing the event - delete your MarketItems table and recreate the sync.

Amazing news
Can you send me the parameters you changed in case I made mistakes in the code?