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/contracts@4.6.0/token/ERC721/ERC721.sol"; | |
import "@openzeppelin/contracts@4.6.0/token/ERC721/extensions/ERC721URIStorage.sol"; | |
import "@openzeppelin/contracts@4.6.0/access/Ownable.sol"; | |
import "@openzeppelin/contracts@4.6.0/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/contracts@4.4.2/token/ERC721/extensions/ERC721URIStorage.sol"; | |
import "@openzeppelin/contracts@4.4.2/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