These Files will be updated for each talk. If you are looking for a past talk check the history.
Resources for live session from SmartCon Workshop
What you need
| { | |
| "name": "Friendship Seed", | |
| "description": "This seed will grow with friends", | |
| "image": "https://ipfs.io/ipfs/QmNpAiQZjkoLCb3MRR8jFJEDpw7YWcSSGMPLzyU5rvNTNg/seed.jpg", | |
| "attributes": [ | |
| { | |
| "trait-type": "FlowerStage", | |
| "value": "SEED" | |
| }, | |
| { | |
| "trait-type": "FlowerColor", | |
| "value": "UNKNOWN" | |
| } | |
| ] | |
| } |
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.4; | |
| import "@openzeppelin/[email protected]/token/ERC721/ERC721.sol"; | |
| import "@openzeppelin/[email protected]/token/ERC721/extensions/ERC721URIStorage.sol"; | |
| import "@openzeppelin/[email protected]/access/Ownable.sol"; | |
| import "@openzeppelin/[email protected]/utils/Counters.sol"; | |
| contract dynNFT is ERC721, ERC721URIStorage, Ownable { | |
| using Counters for Counters.Counter; | |
| Counters.Counter private _tokenIdCounter; | |
| string[] IpfsUri = [ | |
| "https://ipfs.io/ipfs/QmYaTsyxTDnrG4toc8721w62rL4ZBKXQTGj9c9Rpdrntou/seed.json", | |
| "https://ipfs.io/ipfs/QmYaTsyxTDnrG4toc8721w62rL4ZBKXQTGj9c9Rpdrntou/purple-sprout.json", | |
| "https://ipfs.io/ipfs/QmYaTsyxTDnrG4toc8721w62rL4ZBKXQTGj9c9Rpdrntou/purple-blooms.json" | |
| ]; | |
| constructor() ERC721("dNFTs", "dNFT") {} | |
| // Metadata information for each stage of the NFT on IPFS. | |
| function safeMint(address to) public onlyOwner { | |
| uint256 tokenId = _tokenIdCounter.current(); | |
| _tokenIdCounter.increment(); | |
| _safeMint(to, tokenId); | |
| _setTokenURI(tokenId, IpfsUri[0]); | |
| } | |
| function growFlower(uint256 _tokenId) public { | |
| if(flowerStage(_tokenId) >= 2){return;} | |
| // Get the current stage of the flower and add 1 | |
| uint256 newVal = flowerStage(_tokenId) + 1; | |
| // store the new URI | |
| string memory newUri = IpfsUri[newVal]; | |
| // Update the URI | |
| _setTokenURI(_tokenId, newUri); | |
| } | |
| // determine the stage of the flower growth | |
| function flowerStage(uint256 _tokenId) public view returns (uint256) { | |
| string memory _uri = tokenURI(_tokenId); | |
| // Seed | |
| if (compareStrings(_uri, IpfsUri[0])) { | |
| return 0; | |
| } | |
| // Sprout | |
| if ( | |
| compareStrings(_uri, IpfsUri[1]) | |
| ) { | |
| return 1; | |
| } | |
| // Must be a Bloom | |
| return 2; | |
| } | |
| /* | |
| ******************** | |
| * HELPER FUNCITONS * | |
| ******************** | |
| */ | |
| // helper function to compare strings | |
| function compareStrings(string memory a, string memory b) | |
| public | |
| pure | |
| returns (bool) | |
| { | |
| return (keccak256(abi.encodePacked((a))) == | |
| keccak256(abi.encodePacked((b)))); | |
| } | |
| // The following functions are overrides required by Solidity. | |
| function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) { | |
| super._burn(tokenId); | |
| } | |
| function tokenURI(uint256 tokenId) | |
| public | |
| view | |
| override(ERC721, ERC721URIStorage) | |
| returns (string memory) | |
| { | |
| return super.tokenURI(tokenId); | |
| } | |
| } |
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.7; | |
| import "@openzeppelin/[email protected]/token/ERC721/extensions/ERC721URIStorage.sol"; | |
| import "@openzeppelin/[email protected]/utils/Counters.sol"; | |
| contract dynBloom is ERC721, ERC721URIStorage { | |
| using Counters for Counters.Counter; | |
| Counters.Counter private _tokenIdCounter; | |
| // Metadata information for each stage of the NFT on IPFS. | |
| string[] IpfsUri = [ | |
| "https://ipfs.io/ipfs/QmYaTsyxTDnrG4toc8721w62rL4ZBKXQTGj9c9Rpdrntou/seed.json", | |
| "https://ipfs.io/ipfs/QmYaTsyxTDnrG4toc8721w62rL4ZBKXQTGj9c9Rpdrntou/purple-sprout.json", | |
| "https://ipfs.io/ipfs/QmYaTsyxTDnrG4toc8721w62rL4ZBKXQTGj9c9Rpdrntou/purple-blooms.json" | |
| ]; | |
| uint256 lastTimeStamp; | |
| uint256 interval; | |
| constructor(uint _interval) ERC721("dNFTs", "dNFT") { | |
| interval = _interval; | |
| lastTimeStamp = block.timestamp; | |
| } | |
| function checkUpkeep(bytes calldata /* checkData */) external view returns (bool upkeepNeeded, bytes memory /* performData */) { | |
| upkeepNeeded = (block.timestamp - lastTimeStamp) > interval; | |
| // We don't use the checkData in this example. The checkData is defined when the Upkeep was registered. | |
| } | |
| function performUpkeep(bytes calldata /* performData */) external { | |
| //We highly recommend revalidating the upkeep in the performUpkeep function | |
| if ((block.timestamp - lastTimeStamp) > interval ) { | |
| lastTimeStamp = block.timestamp; | |
| uint256 tokenId = tokenIdCounter.current() - 1; | |
| growFlower(tokenId); | |
| } | |
| } | |
| function safeMint(address to) public { | |
| uint256 tokenId = _tokenIdCounter.current(); | |
| _tokenIdCounter.increment(); | |
| _safeMint(to, tokenId); | |
| _setTokenURI(tokenId, IpfsUri[0]); | |
| } | |
| function growFlower(uint256 _tokenId) public { | |
| if(flowerStage(_tokenId) >= 2){return;} | |
| // Get the current stage of the flower and add 1 | |
| uint256 newVal = flowerStage(_tokenId) + 1; | |
| // store the new URI | |
| string memory newUri = IpfsUri[newVal]; | |
| // Update the URI | |
| _setTokenURI(_tokenId, newUri); | |
| } | |
| /* | |
| ******************** | |
| * HELPER FUNCITONS * | |
| ******************** | |
| */ | |
| // determine the stage of the flower growth | |
| function flowerStage(uint256 _tokenId) public view returns (uint256) { | |
| string memory _uri = tokenURI(_tokenId); | |
| // Seed | |
| if (compareStrings(_uri, IpfsUri[0])) { | |
| return 0; | |
| } | |
| // Sprout | |
| if ( | |
| compareStrings(_uri, IpfsUri[1]) | |
| ) { | |
| return 1; | |
| } | |
| // Must be a Bloom | |
| return 2; | |
| } | |
| // helper function to compare strings | |
| function compareStrings(string memory a, string memory b) | |
| public | |
| pure | |
| returns (bool) | |
| { | |
| return (keccak256(abi.encodePacked((a))) == | |
| keccak256(abi.encodePacked((b)))); | |
| } | |
| // The following functions is an override required by Solidity. | |
| function _burn(uint256 tokenId) | |
| internal | |
| override(ERC721, ERC721URIStorage) | |
| { | |
| super._burn(tokenId); | |
| } | |
| // The following functions is an override required by Solidity. | |
| function tokenURI(uint256 tokenId) | |
| public | |
| view | |
| override(ERC721, ERC721URIStorage) | |
| returns (string memory) | |
| { | |
| return super.tokenURI(tokenId); | |
| } | |
| } |
Discord Chat: http://chn.lk/chainlink-discord
Documentation: http://docs.chain.link
Starter Kits: https://github.com/smartcontractkit
Chainlink Academy: https://www.chainlink.education/
Twitter: https://twitter.com/rgottleber