I think a good way to think about it (and to think about NFTs in general) is that the token is just an abstraction. The same way an ERC20 token or a Bitcoin is an abstraction of value, the NFT is an abstraction of something unique - in this case a unique combination of CSS elements. The token itself is just a way to store the data that is rendered (the DNA), and the contract is the way to store that data (and ownership) on the blockchain.
yo @kenn.eth I am trying to make the “Browse” button show up the metamask notification which requests to see your possessions and open marketplace contract? as seen in Filip´s video, but it´s not opening anything. Only the “Breed NFT” button brings you to a page which opens a metamask request. Image below and updated github aswell (node_modules missing since I couldnt upload them there)
what file html fil is the bowse button in ill have a look
Ah yes, the browse button is in the “components.js”, I connected the components.js to every page because it serves as the menu providing code for every page. The page that is supposed to give you the metamask authorization popup is the one that appears once you click browse, which is catalogue.html This catalogue.html is the one dealing with marketplace contract and marketplace side metamask authorization
<li class="nav-item">
<button class="btn red-btn ml-4">Browse</button>
</li>
you need to give your button an id or something and in your JS use document.getEkementById(“buttonId”) and use this to enable an onclick event listener to execute your function that u want to execute onclick
Hi this is my project ( a little different) is not yet complete but is a good start.
-Home
-Buy STK
-Mint NFT (I did not want to find new img)
- Wallet
-Market Section ( miss section for set offer of buy update in next day)
and this is gitHub link
https://github.com/LELUK911/StikiEco/tree/main1
i would want try my skills in this exercise. i hope will be sufficient good.
PS i want create a little game with this nft . but i havent time in this week for work on this
and my style front end, is a very terrible
What a challenging but incredible course! Thoroughly enjoyed it
I’ve deployed to Ropsten testnet and uploaded the files here: https://mkrasne2.github.io/kitties.html
(I’ve allowed public minting for the first 1,000 cats)
Good Evening @thecil
I am on final stages of finishing this amazing project but trying to compile and keep getting the following errors:
-
ParserError: Expected pragma, import directive or contract/interface/library definition."
-
project:/contracts/KittyMarketplace.sol:73:5: ParserError: Expected pragma, import directive or contract/interface/library definition.
function _ownsKitty(address _address, uint256 _tokenId)
^------^ -
project:/contracts/Kittycontract.sol:29:5: ParserError: Expected pragma, import directive or contract/interface/library definition.
struct Kitty {
^----^
Code for Marketplace.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
import "./Kittycontract.sol";
import "./Ownable.sol";
import "./IKittyMarketplace.sol";
contract KittyMarketplace is Ownable, IKittyMarketPlace {
Kittycontract private _kittyContract;
struct Offer {
address payable seller;
uint256 price;
uint256 index;
uint256 tokenId;
bool active;
}
Offer[] offers;
event MarketTransaction(string TxType, address owner, uint256);
mapping(uint256 => Offer) tokenIdToOffer;
function setKittyContract(address _kittyContractAddress) public onlyowner {
_kittyContract = kittycontract(_kittyContractAddress);
}
constructor(address _kittyContractAddress) public {
setKittyContract(_kittyContractAddress);
}
function getOffer(uint256 _tokenId)
public
view
returns
(
address seller,
uint256 price,
uint256 index,
uint256 tokenId,
bool active
) {
Offer storage offer = tokenIdToOffer[_tokenId];
return (
offer.seller,
offer.price,
offer.index,
offer.tokenId,
offer.active
);
}
function getAllTokenOnSale() public returns(uint256[] memory listOfOffers) {
uint256 totalOffers = offers.lenght;
if (totalOffers == 0){
return new uint256[](0);
}else
uint256[] memory result = new uint256[](totalOffers);
uint256 offerId;
for(offerId = 0; offerId < totalOffers; offerId++){
if (offers[offerId].active == true){
result[offerId] = offers[offerId].tokenId;
}
}
return result;
}
}
function _ownsKitty(address _address, uint256 _tokenId)
internal
view
returns (bool)
{
return (_kittyContract.ownerOf(tokenId) == _address);
}
/*
* create a new offer based for the given tokenId and price
*/
function setOffer(uint256 _price, uint256 _tokenId) public {
require (
_ownsKitty(msg.sender, _tokenId),
"You are not the true owner of the kitty"
);
require(tokenIdToOffer[_tokenId].active == false, "You can't sell twice the same offers");
require(_kittyContract.isApprovedForAll(msg.sender, address(this)), "Contract needs to be approved to transfer the kitty in the future");
Offer memory _offer = Offer ({
seller: msg.sender,
price: _price,
active: true,
tokenId: _tokenId,
index: offers.length
});
tokenIdToOffer[_tokenId] = _offer;
offers.push(_offer);
emit MarketTransaction("Create offer", msg.sender, _tokenId);
}
/*
* Remove an existing offers
*/
function removeOffer(uint256 _tokenId) public {
Offer memory offer = tokenIdToOffer[_tokenId];
require(
offer.seller == msg.sender,
"You are not the seller of that kitty"
);
delete tokenIdToOffer[_tokenId];
offers[tokenIdToOffer[_tokenId].index].active = false;
emit MarketTransaction("Rmove offer", msg.sender, _tokenId);
}
/*
* Accept an offer and buy the kitty
*/
function buyKitty(uint256 _tokenId) public payable {
Offer memory offer = tokenIdToOffer[_tokenId];
require(msg.value == offer.price, "The price is incorrect");
require(tokenIdToOffer[_tokenId].active == true, "No active order present");
//Important: delete the kitty from the mapping BEFORE paying out to prevent reentry attacks
delete tokenIdToOffer[_tokenId];
offers[offer.index].active = false;
//Transfer the funds to the seller
// To do: make this logic pull instead of push
if(offer.price> 0) {
offer.seller.transfer(offer.price);
}
//Transfer ownership of the kitty
_kittyContract.transferFrom(offer.seller, msg.sender, _tokenId);
emit MarketTransaction("Buy", msg.sender, _tokenId);
}
kittycontract.sol code
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
import "./IERC721.sol";
import "./IERC721Receiver";
import "./Ownable.sol";
contract Kittycontract is IERC721, Ownable {
uint256 public constant CREATION_LIMIT_GEN0 = 10;
string public constant name = "KittyCrypto";
string public constant symbol = "KC";
bytes4 internal constant MAGIC_ERC721_RECEIVED = bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"));
bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
bytes4 private constant _INTERFACE_ID_ER165 = 0x01ffc9a7;
event Birth(
address owner,
uint256 kittenId,
uint256 mumId,
uint256 dadId,
uint256 genes
);
}
struct Kitty {
uint256 genes;
uint64 birthTime;
uint32 mumId;
uint32 dadId;
uint16 generation;
}
//Arrays of token Ids
Kitty[] kitties;
mapping (uint256 => address) public kittyIndexToOwner;
mapping (address => uint256) ownershipTokenCount;
mapping (uint256 => address) public kittyIndexToApproved;
//MyADDR => OperatorAddress => ture/false. two adresses instead of one
mapping (address => mapping (address => bool)) private _operatorApprovals;
mapping(address => uint256[]) ownerToCats;
uint256 public gen0Counter;
constructor() public {
_create(0, 0, 0, uint256(-1), address(0));
}
function breed(uint256 _dadId, uint256 _mumId) public returns (uint256){
//check ownership
//You got the DNA
//figure out the Generation
//Creat a new cat with the new properties, give it to the msg.sender
require(_owns(msg.sender, _dadId), "The user doesn't own the token");
require(_owns(msg.sender, _mumId), "The user doesn't own the token");
( uint256 dadDna,,,,uint256 DadGeneration ) = getKitty(_dadId);
( uint256 mumDna,,,,uint256 MumGeneration ) = getKitty(_mumId);
uint256 newDna = _mixDna(dadDna, mumDna);
uint256 kidGen = 0;
if(DadGeneration < MumGeneration){
kidGen = MumGeneration + 1;
kidGen /=2
}else if (DadGeneration > MumGeneration) {
kidGen = DadGeneration + 1;
KidGen /= 2;
}else{
KidGen = MumGeneration + 1;
}
_createKitty(_mumId, _dadId, kidGen, newDna, msg.sender);
}
function supportsInterface(bytes4 _interfaceId) external view returns (bool){
return (_interfaceId == _INTERFACE_ID_ERC721 || _interfaceId == _INTERFACE_ID_ERC165)
}
function safeTransferFrom(address _from, address _to, uint256 _tokenId) public {
safeTransferFrom(_from, _to, _tokenId "");
}
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes memory _data) public {
require( _isApprovedOrOwner(msg.sender, _from, _to, _tokenId));
_safeTransfer(_from, _to, _tokenId, _data);
}
function _safeTransfer (address _from, address _to, uint256 _tokenId, bytes memory _data) internal {
_transfer(_from, _to, _tokenId);
require(_checkERC721Support(_from, _to, _tokenId, _data));
}
function transferFrom(address _from, address _to, uint256 _tokenId) public {
require( _isApprovedOrOwner(msg.sender, _from, _to, _tokenId ));
_transfer(_from, _to, _tokenId);
}
function approve(address _approved, uint256 _tokenId) public {
require(_owns(msg.sender, _tokenId));
_approve(_tokenId, _approved);
emit Approval(msg.sender, _approved, _tokenId);
}
function setApprovalForAll(address operator, bool approved) public {
require(operator != msg.sender);
_operatorApprovals[msg.sender] [operator] = _approved;
emit ApprovalForAll(msg.sender, operator, _approved);
}
function getApproved(uint256 _tokenId) public view returns (address) {
require(_tokenId < kitties.length); //token must exist
return kittyIndexToApproved[_tokenId];
}
function isApprovedForAll(address _owner, address _operator) public view returns (bool) {
return _operatorApprovals[_owner] [_operator];
}
function createKittyGen0(uint256 _genes) public onlyOwner returns (uint256) {
require(gen0Counter < CREATION_LIMIT_GEN0);
gen0Counter++;
return _createKitty(0, 0, 0, _genes, msg.sender);
}
function _createKitty(
uint256 _mumId,
uint256 _dadId,
uint256 _generation,
uint256 _genes,
address owner
) private returns (uint256) {
Kitty memory _kitty = Kitty({
genes: uint64(_genes),
birthTime: uint64(block.timestamp),
mumId: uint32(_mumId),
dadId: uint32(_dadId),
generation: uint16(_generation)
});
kitties.push(_kitty);
uint256 newKittenId = kitties.length -1;
emit Birth(owner, newKittenId, _mumId, _dadId, _genes);
_transfer(address(0), owner, newKittenId);
return newKittenId;
}
function getKitty(uint256 kittyId) public view returns(uint256, uint64, uint32, uint32, uint16) {
return
(
kitties[kittyId].genes,
kitties[kittyId].birthTime,
kitties[kittyId].mumId,
kitties[kittyId].dadId,
kitties[kittyId].generation
);
}
function balanceOf(address owner) external override view returns (uint256 balance) {
return ownershipTokenCount[owner];
}
function totalSupply() external view returns (uint) {
return kitties.length;
}
function ownerOf(uint256 _tokenId) external view returns (address) {
require(kittyIndexToOwner[_tokenId] != address(0), "ownerOf: zero address");
return kittyIndexToOwner[_tokenId];
}
function transfer(address _to, uint256 _tokenId) external override {
require (_to != address(0));
require (_to != address(this));
require (_owns(msg.sender,_tokenId));
_transfer(msg.sender, _to, _tokenId);
}
function _transfer(address _from, address _to, uint256 _tokenId) internal {
ownershipTokenCount[_to]++;
kittyIndexToOwner[_tokenId] = _to;
if (_from != address (0)) {
ownershipTokenCount[_from]--;
delete kittyIndexToApproved[_tokenId];
}
//Emit the transfer events
emit Transfer(_from, _to, _tokenId);
}
function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) {
return kittyIndexToOwner[_tokenId] == _claimant;
}
function _approve(uint256 _tokenId, address _approved) internal {
kittyIndexToApproved[_tokenId] = _approved;
}
function _approvedFor(address _claimnat, uint256 _tokenId) internal view returns (bool) {
return kittyIndexToApproved[_tokenId] == _claimant;
}
function _checkERC721Support(address _from, address _to, uint256 _tokenId, bytes memory _data) internal returns (bool) {
if (!_isContract(_to)){
return true;
}
//Call onERC721Received in the _to contract
bytes4 returnData =IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data);
return returnData == MAGIC_ERC721_RECEIVED;
//check return value
}
function _isContract(address _to) view internal returns (bool) {
uint32 size;
assembly{
size := extcodesize(_to);
}
return size > 0;
}
function _isApprovedOrOwner(address _spender, address _from, address _to, uint256 _tokenId) internal view returns (bool) {
require(tokenId < Kitties.length); //Token must exist
require(_to != address(0));//To address is not zero address
require(_owns(_from, _tokenId));//from owns the token
//spender is from or spender is approved for tokenId or Spender is operator for from
return (_spender == _from || _approvedFor(_spender, _tokenId) || isApprovedForAll(_from, _spender));
}
function _mixDna(uint256 _dadDna, uint256 _mumDna) internal view returns (uint256) {
uint[8] memory geneArray;
uint8 random = uint8(block.timestamp % 255 );
uint256 i = 1;
uint256 index = 7;
for (i = 1; i <= 128; i=i*2) {
if(random & i != 0) {
geneArray[index] = uint8( _mumDna % 100);
}
esle {
geneArray[index] = uint8(_dadDna % 100);
}
_mumDna = / 100;
_dadDna = / 100;
index = index - 1;
}
uint256 newGene;
for (i = 0; i <8; i++) {
newGene = newGene + geneArray[i];
if (i != 7) {
newGene = newGene * 100;
}
}
return newGene;
}
Good Evening @HRMS2021, hope your having a great day!
Try to change all your contracts (ownable, kyttycontract, ikyttymarketplace…) to a single solidity version, try with pragma solidity ^0.5.17;
.
Remember to also change the version of truffle so you can compile all of them properly (^0.5.17
), in your truffle-config.js
.
Carlos Z
Hello @thecil Carlos,
Thanks so much for your reply and suggestions🤩
I tried using pragma solidity ^0.5.17; and also changed the truffle-config.js
but is not working.
I get the following messages:
Source file requires different compiler version (current compiler is 0.8.16+commit.07a7930e.Emscripten.clang) - note that nightly builds are considered to be strictly less than the released version
ParserError: Expected identifier but got 'public'
--> project:/contracts/Kittycontract.sol:41:34:
|
41 | mapping (uint256 => address) public kittyIndexToOwner;
| ^^^^^^
Compilation failed. See above.
Truffle v5.4.29 (core: 5.4.29)
Node v12.0.0
Also tried using suggested compiler version from the machine, but it doesn’t work.
Let me know what would be the next best option. Thanks a million!
your getting this error here because public
is a solididyt keyword identifier used to declare the scope of a function or variable. but your using it incorrectly here you dont make mappings public mappings have no visibility as they are a datastructure. you need to remove the public keyoword
cool sounds good. and of course anytime
Hi HRMS2021, how are you doing with this project “Cat Factory-Ethereum Dapp”? Some video instructions are missing to complete the project, could you get them? Let me know if you are interested in trying to solve it together.
Thank you!
VdSR
Hello @valleria, nice to meet you virtually and thanks for your msg.
I finished the project, but it still has a few buggs😩. Few things are working but other key elements of the project is not working properly.
I took a few days off to enjoy the last few days of summer, let me know the best time to meet up online and work on this, I am on EDT time zone.
Talk soon😃
Sadly I am still a bit stuck in completing the frontend and currently still looking for the errors present. After those are cleared I will add the last pages. In the meantime every critique of my work is appreciated.
https://github.com/paulsimroth/nft_marketplace
Hi I´m still stuck in place. More precisely I have problems figuring out how to make the Tokens show up. If anyone has some feedback and help, thanks in advance. You can look at my code on my github. I have linked it in a prior post.
Hey @PaulS96, would you please give me more details on what your trying to do? and on which file in your repo
Carlos Z
@thecil I am currently stuck with getting ym bears to show up. My guess is the issue lies inside render.js at the way I structured inventoryRender. I just have weird behavior with the tokens. For example, currently i have some showing up but not the correct number and the appearance is also not really what I minted.
EDIT: The correct number of bears now show up, also the correct dna is logged in the console but they are shown wrong.
Ok, I have started your repo, started a fresh deployment of contracts with truffle, update contracts addresses, mint 1 bear with deployer, which is the one on the img, events are working fine.
Getting the tokenId 1 from contract does work (check console getBear
), at catalog, the parameters looks fine.
Now i think the problem resides on the way you are rendering each bear body, your sending string
values to the renderBear
function instead of number
.
Now that could be part of the problem, the other issue is that your assigning the attributes directly to a class, which is general to all other bears, you might want to prefer to set the CSS directly to each ID, instead of the class, it can go for example tokenId 1 will have id="#head1"
.
You can also give a look on my old project, which could help you to figure out how to apply the colors into each bear on the catalog, im applying the css to id’s with tokenId number instead of the class. (buildAlien.js)
https://github.com/thecil/cryptoaliens
Overall your project is almost ready, contract is working, factory is working, getting the data from contract its also working, now the only issue is the representation of each bear in the catalog.
Carlos Z