NFT/ERC-721/Collectible END-TO-END TUTORIAL | Deploy, List on Opensea, Host Metadata on IPFS

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's up everybody so i've been getting a ton of feedback on the nft's demos that we've done so far and people said hey we want more so this is going to be the ultimate nft video right here we're going to go everything end to end building deploying viewing on openc selling the whole shebang metadata ipfs everything in this video so this is going to be the ultimate nft video so if you want to see a little bit more modularized version of this information go check out my other videos links are in the description of deploying a simple nft and advanced nft and then all about nfts as well to start off we're going to use the easy way of deploying an nft we're going to be using the nft mix from the brownie repositories and then we're going to do everything from scratch we're going to be deploying some super adorable puppies and then of course tattoo reveal at 10k subs so be sure to smash that like button hit the subscribe button do all that youtube subs because i'm going to be showing you guys one of my tattoos at 10k subs so hit the like hit the subscribe easy way hard way let's jump into it [Music] all right so here is the repository that we're going to be working with we're going to be working with the nft mix this is an official brownie mix we can go to the brownie nft mixes here go in here we can see nft mix right at the top and boom this is this is the mix that we're working with here this is using the brownie framework obviously brownies with python if you guys want to see a truffle one again definitely go check out the dungeons and dragons nft uh for using uh yarn node.js and uh truffle uh this one's great as well they have really cool uh really cool characters in that too but let's get started with this let's do this so we are in our code editor here and we're going to be starting because we have brownie installed we're going to again pip install f brownie let's get it going you do obviously need python installed and now we're going to do brownie bake nft mix brownie bake nft mix i should spell it right and great now we have this nft thing in here and it has all the boilerplate code for us now we're going to be doing this the easy way first and the easy way is us just doing exactly what the readme tells us do right so let's follow the readme so we just brownie baked we need node.js in python we've installed brownie already great we've cloned this repo great we've already installed ganache right so you do need node js right node.v and pm sv dude node or you can also use yarn or whatever you want but you do need uh ganache and if you're watching this in the future they will probably be an update to have this hard hat compatible uh which will make it run even faster but great there are two main environment variables that we need we're gonna need our web oops we're gonna need our our web three inferior project id and our private key environment variables now if you don't know anything about environment variables environment variables are basically variables that live in the shell we can do export you know web 3 infera project id equals whatever right and so we can get a web three and fewer project id we can go to infuro this is a way for us to connect to the blockchain we can get started for free and sign up once you've signed up there's a little project id that you're going to get and then you're just going to copy and paste that in here now what you can also do if there's a dot env and you can put it you can uncomment this out and put it in here and this is going to be the same thing as if um you had no idea what environment variables are put both of them in here so whatever your your your web3 infuria is and then also your private key so this is going to be found in your metamask so you're going to go to metamask account details export private key right and so for our demo we do need a wrinkby link excuse me and for our demo here we are gonna need test net ring b uh and test net ring be eth you can always find those in the chain link documentation link token contracts rink b test net link test net rink b we can get them from these faucets uh so that we have some in our contracts to uh to actually use it and i have another video link in the description to actually setting up metamask and getting that sorted if you have no idea what the hell i'm talking about so once we have these two things set you can do uh what's what's called source dot env and this is gonna execute this file in our current shell right so it's gonna be the same as if we wrote you know export private keek was this and export web3 equals that uh and those environment variables will now be in our shell again if you don't know what environment variables are uh link in the description to learn more but i'm not going to do it because i already have my variables set now great what do we do next we got those once you have those set so let's jump into it now if you ever get lost or you ever get confused always refer to the readme here right the readme is going to give you exactly step by step what you need to do to be successful here so if you get lost always refer back to the readme if a step doesn't work that we do in this video refer to the readme or also leave a comment and we will update either the readme or update the description so that uh these tutorials stay fresh and they still work we have two main types of nfts in here we have simple collectibles and advanced collectibles and you can find those in the contracts folder this is where all of our contracts are so we have an advanced collectibles we have a simple collectibles let's do both great we're going to deploy this simple version this is going to be your simple entity we're not going to go into what that means or what that even is but let's go ahead and grab this and we're going to run it so this is actually going to be deploying our contract to the rinkby testnet chain and we're going to actually be able to view it on chain and actually create the collectible here so anytime you deploy these nfts right these erc721s you're actually almost deploying what's called like a token factory there's one main contract and every time you you run a create collectable function which we'll run in a second you actually create a new nft of that class right so our nfts are going to be classes of dogs right these are going to be dog nfts but each nft is going to be unique now we also have one other parameter again this is optional if you want in our dot env if we want to be able to view these on ether scan we can also do this export ether scan token equals this either scan obviously being a method to view things on chain you know once we actually have deployed it if we have that environment variable set we can actually go to ether scan and view and verify the contract right so these are interacting with that contract on chain we can see that we've deployed our dog we can see everything about the contract right so so that is something else to look at if we want to view these on etherscan make the export your etherscan token again you can just go to etherscan go to apis and sign up for your own api key here anyways so we've deployed a simple nft and now we're going to deploy an advanced nft we're going to deploy we're going to create a collectible we can go check it out on rink b yay hooray huzzah right so so if we want to just just get like the bare bones done that simple nft bit is going to get it done now we will have to wait a little bit for both these transactions to complete and for ether scan to verify our contracts if we've chosen to do so so we can check out this contract we can do whatever we want actually just redeployed but anyways we can do whatever we want we can read and we can interact with it now now again i'm not going to talk about what these functions are doing or what's really going on here we'll get into that after we go past this fast easy version but we can also see like the owner of different token id and right now the owner id of token id 0 is going to be nobody right it's going to errors what are you talking about it's not a real token right because when we deploy this nft contract we're actually deploying a factory contract to create a lot of collectibles now we could have you know made our contract in a way that automatically deploys the collectible but we didn't so now we're going to call this create collectible function and this is actually going to mint our new nft it's going to create a simple unique nft and we can actually view that i am the owner of the first one on ether scan so it looks like that func uh that has gone through now if i hit query 0 we can see that this this is my test net address that i am the owner of this collectible so great if you want to get just the bare bones done you've just done it congratulations but i'm quite sure that's not what you're here for right so we are going to go into what these functions are doing and what's going on here in a little bit but let's do the more interesting stuff now let's get some stuff on openc let's get you selling some stuff let's get some images up let's get these entities to be really really cool okay so let's continue to follow along in the readme right this is why we have readmes this is why we have documentation to make our lives easier ready to make some puppies so same thing first step now that we have all those environment variables set we are going to deploy our uh we're going to deploy our nft contract right and we're actually going to be using a different contract this is our advanced collectible contract what this one is going to be doing i'm going to talk about it while it's deploying is it's going to deploy a contract that's going to give us a random puppy every time we create a new collectible it's either going to be a shiva in you a pug or a saint bernard and they are adorable right so this again is going to be that factory contract right and this one actually the the ether scan verifying is a little touchy so this one this one doesn't work on each scan yet but um i highly recommend anybody who wants to help out and join the project to uh to help out verifying these advanced ones but it doesn't not a big deal because we're gonna see them on open c anyways now we're gonna do the same thing we're gonna to create collectible now i do wanna talk about this function a little bit as we're going through this fast version when we create collectable we are actually going to kick off a chain link vrf call right and to do this we need to fund our contract with link so behind the scenes that's fine so behind the scenes in our in our create collectible function we're actually first funding it with link because in order to interact with a chain link we need to spend some link same as how in order to interact with a ethereum contract we need to spend some ethereum we need to fund it with link first and then we're going to kick off a request that's going to say could we get a random number please that random number is going to get returned and based off that random number it's going to generate the breed of the dog right so we're going to get a random breed of our dog here so that's the function that we're going to be calling right here first and again right now we're just doing the fast version we're just deploying it we're going to build the whole thing from scratch in a little bit so we're going to run create collectible.pie okay so this is going to interact with that contract that we just deployed excuse me this is going to interact with that contract that we just deployed it's going to now create our first token id with it this is going to be creating this is going to request that we get a random dog breed back and we actually will hang around for a little bit because we need to wait for two transactions to happen we're calling on this function right to get a random number well actually we gotta wait for three transactions we're first funding with link funding our contract with link then we're creating a request to get a random number back and then the chain link oracle has to respond actually by giving us that random number so we actually are waiting for three transactions here so we do have to wait a little bit longer great so now we've just completed the transaction here and even gave us what the dog breed is so dog breed of token90 is a saint bernard we're going to get a seat for nard okay so got to relax the cuteness is overwhelming so we've just created an nft of a saint bernard so how do we actually view this on openc how do we show it off to the world how do we do stuff with it well in order to do that we actually have to create metadata and then use that metadata to set the token uri i'm not going to go into what that is quite yet but let's just follow the instructions some more so we're going to call this create metadata function which is going to create this metadata file xerosynbernard.json again if we want to actually upload this image and upload this metadata to our own ipfs we can but we're just going to skip over for now you can go ahead and skip over the ipfs stuff too because you're just going to use the one that i've uploaded uh and and render that so you're going to be all set and i'll go over metadata again in the in the from scratch version right because right now we're just we're still just doing the quick start so we've created some metadata now with that metadata we need to set the token uri of our smart contract to that metadata right and in this metadata file that we just created it's going to give all the attributes of of the uh of the dog so we have the name which is the saint bernard which we got randomly generated from the chain leap breath we've given it a description and we've given it an ipfs image which i'll go through again in the longer edition of this and we've also given it a couple traits because you know why not so once we hit that set uri function we now get this message awesome you can view your nft at here uh if you're entertained here please give up to 20 minutes and hit the refresh metadata button so really oh look it's it's already done it's already excuse me sorry anyways uh so this is the this is the nft that we just deployed and we actually didn't even have to refresh i maybe open c is getting faster which is great so we didn't even have to refresh here and this is the dog that we just deployed so we can see its levels its cuteness level 100 we can see a little bit about it an adorable st bernard pup and we can see that we just created this three minutes ago right this is the one that we just created so now we can do whatever we want we can we can list it we can make an offer whatever we want and again you do need your metamask on rink b uh here to actually work like you can go to your your profile and stuff and get signed in and change your avatar and do everything here but but this is the openc network and it is connected to your uh your metamask so that is the quick start of this that is the like okay you want an nft boom follow these instructions let's go now let's break this down let's do this whole thing over from scratch okay we're gonna do this whole thing over from scratch bear with me guys we're about to go through the long addition of this all right let's come back over here and let's restart everything from scratch and we're going to explain everything that's going on along the way okay i'm going to create this directory nft from scratch and we'll start there all right so we just did the quick start and now we're going to learn how to customize these how to build anything and how to do anything with these puppies and with these entities right we're going to go through the long version and explain everything that happened in the code to get to that point this way you can make any type of customized nft any type of world that you want all using these brownie packages so i know i just said that we're going to start from scratch but we do need to at least start from a blank brownie template now i'm partial to pretty much always starting with a chain link mix which we can run by you know brownie bake chain lick mix which will have all the chain link stuff and everything to work with oracle's and random numbers and price and blah blah i'm a big fan of actually starting there but for the sake of starting from true scratch we're actually just going to do a brand new brownie implementation so we're going to do brownie init and now we have a brand new browning project so let's talk really briefly about what each of these folders is actually doing and what's going on because they're they're all going to start out blank but they are going to give us what we need to get going so the build directory is what happens when we build a smart contract and we deploy one on chain this keeps track of every time we deploy a smart contract and where we're deploying it to the contract section is going to be for all of our contracts these are where we're going to put our solidity code interfaces is a good place to put contracts that have already been deployed that we want to interact with we can also put them in contracts but if you're a little bit confused ignore that for now reports are where we can put some reports you can ignore that for now scripts are where we're actually going to put some of our deployments you can also alternatively put them in a folder called deploy folder but scripts are where we're going to do our python that's actually going to deploy these contracts for us and then tests are obviously going to be our test so the first thing that we probably want to do is we probably want to build our nft contract now for this we are going to do the advanced implementation so there are going to be a lot of steps here but this is really going to help you understand how to do everything that we're going to go over including ipfs storing the data what is metadata everything we're going to be super super thorough here so the first thing that we want to do is we want to create this this contract right so we're going to create a new file and we're going to call it whatever we want to call it right advanced collectible.soul and this is where we're actually going to write our solidity code here so i'm going to make this a little bit bigger for everybody so that we can really see what's going on here now the first thing that we want to do is we want to create at the top of every solidity project pragma solidity 0.6.6 right so we're going to work with 0.6.6 why it's just the version that i built this contract in so that's what we're using now let's talk about what this contract is actually going to look like and before we actually even go into that we do need to understand what an erc 721 is okay so let's go to open zeppelin an erc 721 contract is just a contract that follows a certain set of standards or principles so when i say my contract is an nft contract or an erc 721 it just means that i have the same functions as every other contract that says that they are an nft contract some of those functions are going to be token uri minting token ids and a number of other things but they're going to all have this same functionality now we could 100 percent build a contract with all these from scratch and we can even go to open zeppelin github erc sometimes i want to open zeppelin they do a lot of different types of contracts they are not the repository for storing the stuff but they do a great job at building sample contracts so we could 100 percent uh go through their co copy paste this all into our code and and follow the whole standards right because an erc in erc721 needs to have a name needs to have a symbol you need to have owners balances token approvals and all these functions that are in here we get 100 rebuild everything or we could actually just inherit from this open zeppelin contract and that's actually what we're going to go ahead and do so first thing that we're going to do we're going to import at open zeppelin contracts slash token slash erc 721 erc 721 dot soul now in brownie we can actually just import things directly from github with this syntax and we have to do that in our rowdy config which we haven't made yet so we're going to go ahead and make this so browning config.yaml so this browning config is going to define a lot of stuff about our project and we're going to be working with it a lot so since we're going to be we're going to be pulling from their github right and we're just going to be pulling everything in here into our smart contract so that we don't have to rewrite and maintain all this code again what we're going to do in brownie is we're going to say dependencies are going to be open zep lin open zeppelin contracts so in their github open zeppelin opens up on contracts this is what we're defining in here and then we also want to define the release version so they just did 4.0.0 i haven't actually worked with 4.0.0 so i'm actually going to use 3.4.0 um this is the excuse me 3.4.0 this is the most recent release before 4.0.0 so um so that's the first thing that we want to do and the next thing that we want to do is we actually want to do a little bit of remapping right so we are going to be working with opens up on slash contracts but the syntax we're doing here is at open zeppelin contracts so how does brownie know to do to turn this into at opensupply contracts well when we do the compiler of sulk or solidity we're actually going to remap or we're going to do what's called remappings and this is just the syntax here and we're going to say app open zeppelin is going to be equal to open zeppelin slash open zeppelin contracts at 3.4.0 and then subs and then save so this is how our compiler of solidity knows that hey we're going to be pulling from the open zeppelin github and then we're going to be remapping this to at open zeppelin right so now we can call at open zeppelin which is going to refer to just this repository and then we can go into whatever we want so we're going to say at open zeppelin and that's actually how we can import anything from github into our brownie projects great and we're going to do that same thing actually with chain link okay because we want to use the chain-link vrf to get a provably random breed for our dogs getting randomness in our nfts is a great way to make proven and true scarcity so in our smart contract we're also going to do import at chain link slash contracts slash src slash v0.6 vrf consumer base dot soul dot soul and we have to do the same thing in our browning config and just ignore this this little squiggly line it's uh it's just annoying vs code um so we have to make another dependency right so what's our dependency here going to look like well in the chain link github there's actually a package specifically for browning right now so smart contract kit you can even just look up brownie and we have chain link brownie contracts which has the same thing contracts and it's just a whole bunch of contracts for brownie depending on when you watch this that actually might get wrapped up into the main repository here but we'll see in any case if you if you get lost or confused always check the readme check the config go ahead and use that but this repo will likely be here too so again so we want to use smart contract kit slash chain link brownie contracts at 1.0.2 right because if we look in here if we go back in here we can see the latest release is 1.0.2 and of course you can use whatever release that you want we're going to use 1.0.2 and then we also want to remap this as well so let's go ahead and create a new entry here we do at chain link so now anytime we reference at chain link we're really going to be saying it's smart contract kit dash chain link brownie contract excuse me contracts pardon me contracts there as well at one point 0.2 okay excuse me this is open zep ellen open zeppelin open zeppelin apologies now we can do a brownie compile and we should be able to compile our smart contract here great so we are able to compile our smart contract that means that we didn't screw up any any spellings or any typos up here so great that means we're doing things correctly here so now that we have our two imports we need to actually start creating our our contract here so we're going to call it contract advanced collectible is erc721 so we're inheriting this code that we just looked at and we're also inheriting the vrf consumer base which i didn't go into but this is what's going to allow us to use randomness in our smart contract so we're also going to say is vrf consumer base great we can even try to compile this and we get actually we get an error because it's saying hey you you imported you inherited these contracts but you didn't do it they said that you needed them to do so we'll we'll we'll do that so your your brownie compile will now start failing but don't worry about it so great now we need to do let's jump into building this contract so we need to make a constructor and in our constructor we need to pass it a couple of things so we need to pass it our vrf core denator and again if you haven't used the chainlink vrf before head over to docs. excuse me head over to docs.chain.link scroll down to uh randomness get a round number and just click this button and you can you can do a remix version of it and then just follow the instructions here to kind of do that with remix but but you'll also see it in the contract that we do so we need to pass it a vrf coordinator this is actually what's going to prove and get a and get our provably random number we have to pass the address of the link token we have to do the 32 of the key hash okay which the key hash along with the vrf coordinator is going to be used to prove that a random number is actually random and then that's it then we're going to make this a public function now we have to add the constructors of the erc721 and the constructor of the vrf consumer base in our constructor so we're going to say vrf consumer base it needs the vrf coordinator and it needs the link token and then we also have to do the same thing for the erc 721 and the input parameters for the erc721 are going to be the name and the symbol so what is the name of our nft factory contract we're going to call it doggies and we're going to have the symbol be dog boom and this is going to be our constructor function here now if this part confuses you don't worry too much about that again we just need these addresses to work with the chain link vrf we need the key hash two we're gonna get to that in a minute but for all intents and purposes just giving it the name doggies and the symbol dog is going to be the main starting point for us now we do have to do some stuff in the in the constructor but we're just going to go ahead and move on conceptually to what makes sense so we've deployed our constructor we've deployed our factory contract and we're going to need a function called create collectable or create doggy or we whatever we want to name it and this is the function that we want to call whenever we create a new nft and create a new token id for that nft remember when we deploy this contract it's really just a factory contract right it's the boilerplate contract for creating nfps of type doggies dog so we need a function create collectible and what do we actually want this to uh take in as its parameters here well the main thing that we actually need is a uint256 user provided c this is going to be a number that we actually input that the chainlink vrf is going to use to prove again whether or not the number that it gives us is truly random right and this is really important for creating that scarcity that we want the other thing that we're going to need to pass in is a token uri now what is a token uri and why do we need it let's finish this function we're going to say it's public returns we can even move this over just a hair public returns we're saying bytes32 okay so what is this function actually going to do we want this function to be the one that creates our collectable for us and creates that kicks off a request to the chaining vrf to return a random number to create us an nft okay so let's talk about token uri for a second what is token uri if we look into the erc 721 or even the eip erc eip they basically mean the same thing one means request for comment the other means ethereum ethereum improvement proposal we look up token uri we can see them define what a token uri is right and we can understand what a token uri so a token uri is a stinked uniform resource identifier for a given asset the uri may point to a json file that conforms to the erc721 metadata json schema okay what does that mean when we deploy a token uri and we when we excuse me when we deploy an nft we want these nfts to have pictures right when we deployed the doggy earlier it had a picture of a dog now deploying entire pictures are a lot of data right and i don't know if you guys have known this but generally deploying a lot of data means using a lot of gas using a lot of gas means very expensive so something that nft creators thought of when they were building the erc721 standard was how do we actually render these images without having to deploy that whole image on chain so they said here's what we'll do we'll give it a token uri or uniform resource identifier this can be an api call this can be an ipfs link this can be any url or api or whatever that points to a specific json file okay and the json file is going to look something like like this i'm actually going to pull an example from the pugs that we were making earlier so the json file is going to look like this so when we call an api we want it to return something that looks just like this it needs to have a name a description an image and then attributes this is just for rendering purposes we obviously want to still have these attributes on chain if we want the tokens to actually interact with each other and do more things than just be art right if we wanted to have a game character we would need to have it actually have some type of strength on chain right so we have to put it both in the token metadata and on chain so in any case that is all the token uri is it's just an api that returns something that looks like that the question that of course becomes is where do we store this right if we store it in a centralized server or centralized api then in 10 years our nft is going to be nothing right so a good solution to this is actually storing these images on ipfs and this is actually what we're going to do here ipfs is a peer-to-peer network but basically ipfs is a network in a decentralized manner where we can store data and we can store this information now to keep it persisting there forever we do have to reach out to other node operators and have them also host our data or we can use some type of persistence network like filecoin to make this permanent right we're not going to go into too much of that here but ipfs is going to be a decentralized way for us to store our data let me just show you another example of what what one of these looks like here's what it looks like on ipfs we can share the link copy the link and we can paste it into our browsers and actually see it so i have this thing called ipfs companion installed in my braid browser here it's just a plug-in we can add it here we can actually see this is going to be the api that these nft marketplaces are actually going to be calling when they work with our stuff so and you can see it has this image section which we can also copy and paste and we can see this is the image of the dog here that's what a token uri is so where when we create our collectibles we're gonna have to set this at some point so the nft marketplaces know what to do we're gonna have to set this json file now for the purposes of this demo we're actually going to leave that blank at first until we've uploaded our metadata to ipfs based off of the characteristics and the traits of our dog on chain once we found out the breed of the dog we'll make the token uri and we'll set it on chain you'll see how we do it in a second here so the first thing that we need to do is kick off our randomness request to the chain link vrf right and remember this is going to be asynchronous so when we call create collectable we're going to be calling this function and it's going to omit a request to get a random node from the off chain chaining oracle that's going to respond in a second transaction that we're going to define below that function is going to be the one that actually creates the token id and everything that we need so create for create collectable let's just do the chain link vrf bit here so we're going to do bytes 32 request id equals request randomness key hash fee and user provided seed the key hash and fee we need to pass to the chaining vrf the key hash is used to actually verify the number is truly random and then the fee is going to be how much link token we're going to send to the chain link oracle remember when working with transactions on ethereum we pay a little bit of eth we're working with changing oracles we pay a little bit of link so here up at the top we're actually going to go ahead and define those as global variables so we're going to do bytes 32 internal key hash and we're going to do uwent 256. we'll just do public fee and we'll even set the key hash and fee in the constructor so we're going to say hash equals key hash and fee this one we are actually going to hard code to 0.1 link which we have to do in a way so we're going to do 0.1 times 10 raised to the 18th which again stands for 0.1 like remember when working solidity doesn't work with decimals very well so it actually so this number is actually 1 1 2 3 4 5 6 7 8 one two three four five six seven eight nine ten uh it's actually eighteen zeros right which stands for one link but it's just kind of like a little bit nicer visual to be like okay it's one link so we're gonna hard code that so this is the request randomness function which kicks off the vrf call to get the random number and return it back to here we do have to do a couple other things in this function when we request this random number we want a way to know that the random number that we requested is the same random number associated with the request when the chain link node returns it's going to return and assign the round number to the correct call so we actually have to do a little bit of mapping here okay so when we we have to know that when i make the request when i create a collectible the random number that gets returned is returned correctly to me right if someone else calls create collectible the random number that was kicked off when they called it needs to be returned to them so we have to make a quick mapping here so we're going to do request id to sender of request id equals message.sender and we're going to create a mapping at the top called request id to sender so we're gonna do a mapping of bytes32 request id mapped to address and we're gonna call it public request id to sender okay so this is when i create the request that request is associated with me message.sender me it's all about me here and we also let's say we did set the token uri we'd want to do request id 2 token uri request id equals token uri now we're uh we're like i said we're going to be defaulting this to blank but if you did want to set the token uri right from the get go this would be the way that you do it so we also have to do this mapping so do mapping of bytes32 request.e2 to string public request id to token uri again the token uri being that api call to that json response okay so now we have requested a token uri as token uri and we're also going to do one more thing purely for testing for when we write our tests we're going to omit a requested collectible request id function now this is going a little bit into events here so we're omitting an event an event is the closest thing to ethereum logging that there is it's spit out we can't actually access events on chain but we can read them from off chain but we have to create our event type so we're going to say event requested i requested collectible it's going to be a bytes32 indexed indexed request id so we're saying we have this event again this is like ethereum version of logging our smart contract can't interact with events but we can interact with events and we can use them for testing so we want to make sure that our request id is happening and is the right one so we're going to omit that request id so this is going to be the starter main piece of creating that collectible now once the chain link node responds we're going to want to fulfill randomness so we have to create a function called function fulfill randomness and it takes a byte 32 request id a u and 256. random number and it's actually going to be an internal override turn internal override when we kick off a randomness request the chain the node responds by calling this fulfill randomness function it actually calls something through the vrf coordinator which calls us but don't worry about that for now and it's going to return with that request that original request that was created up here and that random number right because we were requesting a random number so it's going to return it's going to say hey here was the request that i got here's the random number and the vrf coordinator has already processed it already made sure it's a provably truly random number this is how we can create that that beautiful scarcity that we're looking for so now we can actually start setting it up and actually mint this new nft in this new token id so let's do this so we need to get the address of the dog owner all right we need to get the address of the person who originally created this request and since we saved it in a mapping we can do request id to sender of the request request id is going to be that dog owner right because above here we mapped it out requested a sender request id is message.sender down here we're going to unpack it from that mapping okay so now we have the dog owner we also need the token uri string memory just in case we did set one so string memory token uri equals request id to token uri request id so this is going to be doing getting the token uri that we initially added when we called crate collectible which which again you know we're skipping for now now every time we mint a new collectible every time we mint a new nft on our nft factory contract we have to give it a token id or a new id so we're going to say you went 256 new item id equals token counter so we need to keep track of all of the tokens that we're making so we need to add another variable at the top uint256 public token counter and we need to initialize it to zero well we don't have to but we're going to right and it's going to default to zero so our first token id is going to be zero now we're going to call a function that we're going to that we've inherited from the open zapping 721 it's gonna be called safe mint now we're gonna safe mint and nft and we need to give it the owner which is gonna be the dog owner the one who initially hit that create randomness function or excuse me create collectible function and then we have to give it the id which is going to be new item id we also typically want to set the token uri so we can do set token uri of that item id to that token uri that we originally sent in again for us it's just going to be none but i did want to show the functionality here from the get go because if you wanted to give it a token uri from the get go you absolutely can now here's where we get to have some fun we are going to be using this random number to be choosing a random breed but we could do a whole lot more than this we could give our dog a speed stat a color stat a random any type of random attribute for our nft and again the dungeons and dragons ones does a great job of that the dungeons and dragons demo it gives like random strength dexterity constitution etc we're just going to be doing a random breed here so we need to actually get a list of random breeds that our dogs could be so we're going to use this by doing an enum an enum so we're just going to do three dog breeds so we're going to say we're great we're basically creating a new type here type read so we're going to say enum breed and you can be a pug a shiva in you or a saint bernard er nard okay now we have this new type breed we can actually make objects of this type so down here we're going to say breed read so variable name is breed of type breed and then maybe we we can call this like dog breed dog breed or something that's probably better but i'm just gonna stick with breed um equals a new breed um of one of those three so if it's a zero breed is going to stand for pug if it's one oh and then actually this doesn't need a semicolon sorry uh pog is going to be if it's zero it's going to be a pug if it's one ship in you two saint bernard three nothing it's gonna air out so we're gonna say uh new breed and we're gonna use that random number to actually give us the breed so we're gonna do what's called the modular function random number mod 3. this is basically it's going to divide the number by 3 and use the remainder to actually choose so if it was 9 9 divided by 3 is um 3 with no nothing left over so it would be 0 there's no remainder now if we did 10 10 divided by 3 is like 3 point something another way to put it is that there's one left over right because 9 divides evenly 10 has 1 left over it would be 1. so that's how the modulo function works so this way we'll always get 0 1 or 2 right because we can't get 3 because 3 divided by 3 is 1. so great so now we have the dog breed now we actually need to assign that dog breed to this new token id so we're going to do token id to brie we're going to create a new mapping here token id to breed new token id equals breed so we need to create this new mapping up top and as you can see we're starting to get a lot of mappings another way to do this is actually with a struct of type breed to kind of store all this in there but this is just this is just one implementation i thought it would be easier but another way to do this would be to make these structs so we're gonna do uint256 token id to breed because again we have that new breed type public token id to breed now we also need a way when we're testing we are also going to need a way to map up the request id to the token id so that we know that it's right so we're going to be adding this in for some testing as well we're going to do a request id to token id of request id equals new item id so again at the top we're going to create this new and again you'll see why we need this in a bit mapping of bytes32 to uint256 public request id to token id boom and then we just need to iterate the token counter so token counter equals token counter counter plus one right and this way every time we create a new token it's going to have a new id so great we've just implemented the main functions that we need and technically we could just go ahead and send this and this would work now obviously we would need to set the token uri correctly from the get-go but we'll fix that in a second so let's actually compile this let's see if we did anything wrong here we did we did we did some a couple of misfit spellings so let's actually fix that bytes32 fear of consumer base and let's see if that works and great our contract compiles here which means we don't have any glaring issues at least so we do need one other function right because since we're don't we don't know the breed of the dog before it gets created we actually have to add the breed to our metadata to our token uri later so we're going to create a function called set token uri and this is going to set that token id to the correct token uri so we're going to do ui 256 token id we're also going to do string memory underscore token uri and we're going to make this a public function now even though we are going to make this a public function we really only want the owner of this token id of this little doggie to be the one to be able to set the token urine that's where we can do this require statement and we're going to again this is imported from that erc 721 open zeppelin you say is approved or owner underscore message sender i'll just go token id so this is imported from that erc721 from opensupplement they have a function called is approved or owner and this just says hey is the message.sender the owner of the token id that's all this is doing and then if they're not we'll have it kick out a message erc 721 transfer caller is not owner nor approved great and then we can just call set token uri token id to token uri right and this is going to be the same method that we called above it's the token uri but we're just calling it in its own function here okay now again let's see if it compiles awesome we now have it compiling now in the nft mix and in the chain like mix we actually go ahead and write some tests right writing tests for your local network is really really big and i've even imported the conf test into this test folder if we're not going to go over the tests here okay but you definitely want to actually test a lot of your stuff locally before you deploy it to a real test net because even though a test net is free and you can get your test net link and you can get your test net eth you're going to be able to test much faster if you test on a local chain first okay and then to do that we actually do need to download a hard hat we actually do need to download ganache and in the future i will update this package for hard hat as well so you can see if you have node with node v again you can go to you know download node node.js download node.js to actually get that and then you're going to need to do then you're going to need to npm install ganache right npm install g ganache cli again i'm not going to do it because i already have so that's how you're going to need to run your tests you absolutely should 100 any development experience do that we're going to skip over it so now we're going to write some scripts right we're going to skip over we're just going to jump into writing some scripts here okay so we're going to create a new folder just because that's what the mix has advanced collectible and in this folder we're going to create our functions to actually uh do things so our first one is going to be deploy advanced dot soul okay and this is our contract to deploy uh the advanced now we can 100 wrap all the scripts that we're gonna write into one big script uh but we're gonna but i'm gonna go ahead and break it apart so that you kind of can understand a little bit more what each step is really doing okay so this is going to be deploying our smart contracts to the rink b test net chain okay so we're going to do from browning import we want that advanced collectible advanced collectible we want accounts these are going to be accounts associated with our private key or our mnemonic we want network we want to know what network we're on and we also want the config now i know i'm typing a lot of stuff here let's see what it is in a second this is excuse me not that soul i was wondering why i was highlighting weird dot pi excuse me and when we run our scripts we can actually run them like this we can do brownie run scripts advance collectible oops sorry let me actually put that in the right folder deploy advanced.pi right and it's not going to do anything right now but it's just going to spit out now as you can even see it says launching ganache cli this is because the default network of brownie is going to be a development network where it launches ganache okay and it calls the main function we haven't had it do anything but we could do something like print hello now we do browning run scripts advanced collectible deploy advanced hello and that's it right so it compiles everything and runs the script great let's have it actually do what we want to do so the first thing we need to do is since we're deploying to a real chain we need a wallet we need an address we need a private key or mnemonic so we have to and we have to add that to our accounts so we're going to do accounts.add our private key or whatever okay we're actually going to define this private key in our config configuration so in our config we're going to make a new section called wallets we're going to do from key private key and this is a way this is how brownie knows how to get our private key from the environment variables right so you see the syntax around it this this currently means get it from an environment variable this just means it would be private key but we want the environment variable we could also do from mnemonic and do like you know mnemonic if we want it but now we can actually have our key or mnemonic stored in our in our config and again you can get that from here count details export private key okay so now in deploy advance we have to add our account here so we're gonna do accounts.add config this can this brownie config here pulls from our browning config and we're gonna say at wallets so at that wallops section and then we're going to do from key okay we could also do i think it's from mnemonic i think that might be it i actually i'm not sure and then we can do from uh mnemonic here if we wanted to use our mnemonic instead but we do accounts.add and now we can do we're going to say our dev account equals accounts that add this we can even do print dev right and hopefully this will print our account right this this is my metamask address so great so we are adding our account properly fantastic now what i also like to do is i also like to just do this print network dot show active just so that we know what network that we're working on so we'll do we'll run this again we'll see what we get we're on the development network if we want to change networks we can do dash dash network rank b and it'll say okay great now you're on the rinkvie network okay we don't need to define anything in here because brownie knows what our networks are so if we do brownie networks list it already has some pre-built into it for example rink b covan ropsten i've i've added a bunch in here so these are the ones that i've added but um it has a whole bunch built in now there is currently uh i'm just going to go we're going to skip over publishing to ether scan just because again there's there's currently an issue with doing it here so i'm going to set this this variable publish source equal to false and you'll see why we'll do that in a second so now let's go ahead now that we have an account again we have it funded with ethereum and with chain link we can go ahead and deploy our collectable here so we'll do advanced collectible we'll call it advanced collectible lowercase equals advanced collectable dot deploy right because again we're importing this smart contract from brownie and we're just going to deploy it with advanced collectible dot deploy now what do we deploy it with so remember when we when we set it up the constructor said it needed a vrf coordinator link token address and a key hash we get absolutely 100 hard-coded here but we're actually going to do something a little bit more clever so in our browning config we're going to create a networks tab or a networks section set the default to be development which it already is but if we wanted to run this on coven if we wanted to run this on rink b the addresses of the vrf coordinator of the link token of all these other things are going to be different right so we want to specify that when we're working with the rink b chain we're going to use specific addresses right so the vrf coordinator is going to be a certain address the link token is going to be certain address all these other things are going to be certain address now again i'm just going to copy paste here but if you're like well what are all these things you can go to the chain link documentation and find all these addresses here so this is the address of the vrf coordinator on rink b this is the address of the link token on rink b this is the key hash again this is what the chainlink vrf uses to make sure our number is truly random on rinkby and then this is the the fee of the uh of the vrf on rink b i think we can actually even get rid of that because i don't think we ever do anything with that so now in our deploy advance script we got to add the those those parameters that are in our constructor right and again oops if we look in here vrf coordinator link token key hash and we can do it on a per network basic so we'll do config networks network oops network dot show active vrf coordinator right so we're saying from the config go to the network section go to the active network which is rank b networks rink b vrf coordinator networks rink b vr coordinator but now we've got to do that for all of them so we're going to config networks network dot show active link token config networks network dot show active key hash great and every single time we deploy a smart contract or work with a chain or make a transaction we always have to add this from object from dev and this is also where we'll define anything else so we're saying we're deploying from this dev account and we can also do publish source and this will verify it on ether scan if we have our ether scan api key environment variable set uh to publish source which again we're just defaulting for false at false for now okay so when we deploy this we also again we need to fund it with link so we're actually going to put this fun script we could put this fun script in here i'm actually going to go ahead and put it in its own script so what i'm going to do is i'm going to create a new function called or a new script called fund collectible pi and put it right where i want it to be and we're actually going to define that in here we get 100 define it in the deploy advance script but i want it to be its own script so i'm going to say from browning import advanced collectible i also made a a helpful scripts file in here so we're actually going to make that too cd scripts we're going to touch helpful script stop i and actually we're going to put it in there so we're going to do we're going to open this helpful scripts and this is actually where we're going to put it so we're going to go from brownie we're going to put it in here we're going to import in fun collectible and import that to deploy advanced you'll see so we're going to from brownie import advanced collectible accounts config interface interface network import a whole bunch of stuff in here right and we're going to add this function def fund advanced collectible and we'll have it take in an nft contract as the variable to start oops and again we're going to set the dev account dev equal accounts dot add config wallets and we i guess we could pass that but we're not going to pause while it's from key right because since we're going to be funding it we do need to fund from an address and we also now we need to send the link token now here's where interfaces become really helpful whenever you interact with a smart contract on chain you need two things you need the interface or abi and you need the address the interface is secretly a way to get the abi what is an abi an abi defines the way to interact with a smart contract so you always need that api and the address okay we're going to be getting the api from the interfaces section so we're going to actually create a new file called link token interface dot soul and i'm just going to copy paste so as you can see it's just like a list of functions this isn't a real smart contract but it shows us what we can do with the link token right we can approve it we can transfer it as a name and a symbol blah blah whatever okay and we need this to actually interact with the chain link token and send um and transfer and fund our contract so we need that and we also like i was saying before we also need the address so from our interface from the interface folder which we get from brownie interface dot link token interface the one that we just made and again you can copy it from the nft mix it's in there we need the address so we're gonna do config networks network dot show active link token link token right because every network is going to have a different link token address okay so the rink be chain this is the address of that token so we're saying we're going to say hey let's get the address from rinkby of that link token and we're going to wrap it in this interface so we have the address this is how we get the address and this link token interface is how we get the api we can even you know make this either we can say link token equals this then we can call linktoken.transfer now that we have the api and the address we can actually do stuff with it we're going to do linktoken.transfer nft contract so we're going to send that nft contract um some amount we'll do one one two three four five six seven eight one two three four five six seven eight nine ten we'll send it a whole link or actually i think in the in the mix we send point one link so we'll do that so we'll send it that and then from right because we already knew from dev okay so now we have this fund fund advanced collectible all right good thing we fixed that so now in our fund collectible script we can actually import that function from scripts dot helpful scripts import fund advanced collectible and we can just have this function or this script be really simple def main advanced collectible equals advanced collectible and here's how we actually can get the most recently deployed contract so this advanced collectible object that browning gives us is actually a big list so what we can do is we can get the length of this advanced collectable list minus one and now advanced collectible this advanced collectible is going to be the most recent deployment of advanced collectible this client advanced collectible instance can be the most recent one and we're going to do fund advanced collectible advanced collectible right so we're going to be passing the most recently deployed advanced collectible to this fund advanced collectible script and boom great so now back in our deploy advanced function we can actually import that same way we did before i'm just going to copy paste from scripts.helpfulfor scripts dot import fund advanced collectible and we can run fund advanced collectible and what are we going to pass what are we going to pass we're going to pass that advanced collectible excuse me that advanced collectible and then let's return oh i guess i let's do it like this and we're going to return the advanced collectible what a mouthful okay so now we have a function that deploys our contract and then also funds it with link okay so the only other thing that we need again is we do need our infera right like i said in the quick start we do need the infera get started for free you can sign up and get your your web3 infura it's going to be your web 3 and fewer project id this does need to be an environment variable right and again if you forget how to do that you do export private key equals blah blah blah you can create a env file and do export private key equals blah blah blah and then just do and then obviously you know export web3 blah blah whatever it is equal to you know whatever it is and then you do source dot emv and that will actually run these exports in your terminal we can also do the pi dot e and v but uh we skipped that for this but if if that's confusing don't worry about it but let's go ahead and at least test this see if it works on rink b okay because right now it's not really going to work on development because now we're kind of hard coding this to work for development we're going to say hey in the networks tab of the network get the vrf coordinator and if we go to the browning config obviously there is no vrf coordinator for development so let's go ahead and test this okay brownie run scripts deploy there's gonna be advanced deploy advanced network rink b and great it looks like it's actually working properly we have a transaction here and we should be able to go to ether scan rink b paste it in and it actually looks like we are getting a transaction here so this first transaction is of course going to be actually deploying the smart contract right it's going to be deploying the smart contract we will have to wait for a second transaction which happened right here which is going to be funding it with link so grant it looks like we've actually deployed a smart contract it's been created and we can see it's been funded with point one link so this is great we now can see that we have this contract on chain it's been funded with link awesome now we actually need to interact with it right we have these other functions in our advanced that we need to call right we need to create our collectible we need to uh which is going to kick off the function to get a random number to fulfill it and create the actual collectible with with the token you excuse me with the new token id and then we also need to set the token uri right we need to store our data someplace ipfs et cetera server whatever we need to store it somewhere so that when openc goes to render it it knows what to do right because if we take this right now it'll it'll show up it'll come up as blank right it'll say hey i don't know what you're talking about it's just a this is just an nft means nothing to me though right and that's that's clearly not something that we want to do so we need to write the rest of these functions here so we need to write a create collectable function which is going to call that we can also do this from the console like the brownie console dash network rank b but you know we're going to skip that so and if you even look into deployments now we can see we have a deployment for rink b in our in our build folder over here so great so we have deployed it we've funded it let's create a new one called create collectable dot pi this is actually going to create the collectible now again we could just wrap these all up into one script but we're going to put them in in their own scripts just to break it down for us here so we're gonna do the same thing here from brownie import advanced collectible accounts config we're also going to do we're going to also create a new function in those those helpful scripts called get read we're also going to import time you'll see why in a second so you'll see why we need get breed we haven't made it yet you'll see so let's create our main function def main again we're going to do dev equal accounts dot add config wallets from key right this is the same as before we're just getting our dev account from our private key and we're going to do advanced collectible we're going to interact with that contract that we just deployed equals advanced collectible and again we could do like zero here we do one we do two we always want to get our most recent ones we're gonna do the length of advanced collectible minus one so when we call this we're just auto hard coding it to always work on the most recent deployment of of advanced collectible and great now we need to call that transaction uh that create collectible transaction so we're going to say transaction transaction equals advanced collectible dot create create collectible and we're going to give it a token uri of none for now just for now and we also need to give it a seed right and this is what the vrf uses to get that random number so we're gonna do static seed equals we're just gonna call it one two three static seed and again since we're making a transaction we always got to do this oops sorry from oops from dev from that account okay so now we're gonna do transaction dot wait we're gonna wait for two confirmations or one confirmation or whatever we wanna do we're gonna wait for that transaction to actually finish uh and then this is where those mappings are going to come into place because we want to get the breed of this dog so we're going to get the request id of the dog by actually grabbing that event that we made right because in this advanced collectible we had this omit requested collectible so in our transaction here we can do transaction dot events and requested collectible in that requested collectible event we're going to get the request id and then we're going to get the token id based off that requested because remember we set those before so we're going to say token id now is going to be advanced collectible dot request id to token id request id so we're grabbing the request id from that event we're going to get the token id based off of that mapping of request id to token id okay then we're going to get the breed now based off of that token id so now breed is going to be get breed advanced collectible dot token id to breed of token id right because we also in here we have tokenity debris so this is how we're going to get the breed token id and then we're going to print out the breed now we don't have this get breed function because we haven't defined it yet so let's create it so we're going to do def get breed in this helpful scripts function and we're going to do breed number right because again it's going to be 1 0 1 or 2 zero being pug one being shiva in you three being or two being saint bernard we're gonna add this little dictionary i'm gonna call it switch equals zero is going to be a pug one is gonna be a shibba in you two is gonna be a saint bernard and then we're just gonna return switch breed number great so now we have this spree number here now we can call this get breed function and we're just gonna do print little print statement here we're just going to say dog breed of token id this is this that format token id breed quick question do you guys like that formatting or like this took an id or like this better i'm i'm sure he's still out i think i'm going to start moving to that one but let me know in the comments what you guys think but great okay now we have this crate collectible right so this is actually going to kick off this advanced collectible right because we can't we have to wait and then we have to wait for a second transaction to go through sorry about that so we'll wait for the transaction and then we actually have to wait for the second transaction here so this is where we're just going to kind of hard code time.sleep we'll say 35 seconds right we're going to wait for some amount of time hopefully by the time the second the second transaction by the chain link node has actually been done so apologies we do have to wait and let's try this out so now we can do brownie run scripts advanced collectible create collectible network rank b let's see if this works can i convert none to way oh i have them backwards oopsies so we're going to do this flip these two around in the in the actual mix there they're flipped the other way so sorry about that now let's do it quick flip and here we go so now we're actually kicking off this transaction that's going to create our first collectible okay so we have it's conf the create has been confirmed now we're doing a little bit of a quick sleep here and we're going to be waiting for that second that second one to be to be admitted so or that second transaction happened so we could probably even do this we could probably even just do this right wait for it to happen then we'll grab the request id we'll grab the token then we'll wait on the second one so that's what we're waiting on right now dog breed of token id 0 is pug and we can actually even double check to make sure that's the case because maybe we didn't even wait long enough by going to the console so brownie console rank b and we can do the same thing here right we can get the most recent advanced collectible by running this right here and now we can get the breed again by doing well so there's only one token id right now which is zero so we do advanced collectible whoops advanced collectible dot token id to breed oh sorry it's okay i need to to breed of zero and we're actually getting one so we actually didn't wait long enough so that's why i bumped this up to 45 seconds here because that means the token id the dog breed of token id 0 is actually 1 which is actually going to be a shiba inu so we didn't wait quite long enough maybe we'll even do 55 here so the next one we'll be able to wait long enough but so great so now we have deployed the nft contract we've created our first collectible that's a random breed base off the chainlink vrf awesome we did it now we just got to do the next bit which is going to be getting it onto ipfs so we can see it in openc so to do this we're actually going to need to create the metadata based off of this on-chain data that we have so we're going to create a function called create metadata.pi okay and then let's put into the advanced collectibles here now in this we actually want to deploy this to ipfs we want to deploy this metadata to ipfs that way we can have that uri and have the marketplaces actually referencing this metadata here so now there's two different ways we can kind of do this we can do this manually where we create the metadata and then we just upload it to like our ipfs desktop right we could 100 do this and oops we could 100 just upload it to our own you know our own desktop here and do just kind of manually create the json and the image and everything but we're going to actually do it a little bit more programmatic so that it automatically is deployed to ipfs a lot of stuff here so let's just let's just jump into it def main and let's just let's do a quick line just to say we're working on print working on plus network dot show active now again let's get our advanced collectable advanced collectible is going to be advanced collectible let's get the length of advanced spelled this wrong advanced collectible minus one i'm gonna have to import that from brown again from brownie import advanced collectible great so we're gonna need to get this function right and why we also need networks excuse me advanced collectible collective b-l-e b-l-e there we go spelling's important now why do we need this well because we need this to get the breed of the dog right we need the on-chain breed of the dog so we know to assign this specific token id the correct image right we want since it's a shiva inu we want to actually give it the shipment shiba inu right we want to give it the shiva inu image so normally what i'll do is i'll do i'll even get the number of tokens there are number of tokens equals advanced collectible dot token counter right because we have that token counter so we can even run this right now write brownie run scripts advanced scripts create metadata network rank me and we'll be able to oh whoops i should probably print this out right there should be one right because we've deployed one we've created only one and uh and that's exactly what we see here right the more we print this token counter keeps going up remember how we made this token counter right got initialized to zero and whenever we create one we add one when whenever we create a new n of t we add one add one to that list there so so we can even like print you know the number of tokens you've deployed deployed is this format number of tokens right so we can run this again it'll say hey here's the number that you've deployed the number of tokens you deployed is one perfect so once we do that we're going to actually want to write some metadata so i'm just going to create a function called write metadata from the number of tokens and with the advanced collectible okay because i want to write metadata for each one of these tokens so if i deployed like 10 tokens great each one of them gets their get their uri set up correctly so let's do def right metadata and we'll do token ids and we'll do the nft contract okay so this is going to be the list of token ids excuse me the number of token ids and if there's 50 of them and we can even just do this and if there's 50 of them it'll be 50. again in the nft mix this might be a little bit different but if there's 50 of them we want to set the metadata for all 50 right so it doesn't matter how many how many we do we'll just always get that so 4 for each token id in range of of this number of tokens we want to have some type of um metadata right we want to have like a boilerplate metadata so that we always know um what the basic metadata looks like so i'm actually going to create a new folder where we're going to store all the metadata and in this folder i'm going to do sample metadata dot pi and this is where i'm just going to have the sample metadata the metadata template so i'm going to call metadata template equals and this is just where i add the metadata template we're going to do name that's the name description it's going to be blank here too we'll do image keep it blank and then we'll do attributes attributes and this is actually going to be a list right a list of attributes so we're going to do trait type and since we're just going to all be having the same trait types let's just go ahead and add a give it a cuteness one a value 100 right so uh every dog that we're going to deploy we're just going to give it this trait again this isn't on chain um if you do have on chain attributes this is where you would store them right so like for example we're just doing breed to change the name but maybe we gave our dogs like a strength the speed on chain whatever this is where we put them so in our create metadata in our create metadata folder file we can now do from metadata import sample metadata right so it's going to import that boilerplate for us we could of course also add it right here we do like sample metadata equals you know whatever we're just going to import it from that other just to make it a little bit cleaner and now we'll do collectible metadata equals samplemetadata.metadata template right so we're just kind of we're going to give our our this token id we're going to start it off with some boilerplate metadata so they all start with some boilerplate metadata now we need to get the dog breed so the breed is going to be get breed which we can import can import from our helpful scripts right we do the same as we did in create collectible we can do from scripts dot helpful scripts import get breed so we're going to do breed equals get breed nft contract dot token id to breed token id remember because we we have this token id to breed and we can use the token id to get the breed and now we're going to create a metadata file name so we're going to we're going to store this this json object somewhere so we ideally want to store it in this metadata file so i'm even going to go ahead and create a new folder rinkivy to store all of our rink b metadatas so we're going to do metadata file name equals and we're going to make this a nice little list here so we're gonna do dot slash metadata so in this metadata folder the network that we're working on and we're gonna do dot format network dot show active right so metadata file name is going to be in the metadata folder in the rink b folder of that which we just made plus the token id and then we're going to do plus a hyphen plus the breed plus dot json so we're going to be creating a file named basically you know metadata rank b token id which is gonna be zero uh shiba inu dot json right this is what we want to the file path to be now if we've already have this if we already have the metadata let's do a quick if if we've already done it if path and let's let's import the path if you guys don't work with path with python i highly recommend it it is is really helpful so we're going to do from path lib import path if the path of that metadata file name if path metadata file name dot exists if the path is already there i'm just going to do print already found dot format metadata file name otherwise we're going to create it so we're going to say else print creating metadata file format metadata file name and now let's create the file so we're going to do collectable metadata name is going to be get breed right again that nft contract that token id to breed took an idea probably should save the breed above but so we're just going to say the name is just the breed okay and then we'll do collectible metadata description i'm mixing my double quotes in single quotes it's pretty gross but it's fine description equals an adorable pup dot format collectible metadata name right because this is just the breed of the dog so that's going to be the description it's going to be the name all right great we can even print this dictionary that we have so far so let's go ahead and run this brownie run scripts advanced collectible create metadata network rink b and we should see the dictionary that we just created right perfect and this is what we want it to look like so far right so as you can see what we're missing here is this image bit and this is going to be the image uri right a unique variable or a unique url you know defining where the image is actually located so this is something that we have to upload to ipfs and again we also have to upload the metadata that json file we need to upload to to ipfs so once we upload it to ipfs then we can actually grab the url pointing to that ipfs upload so we need to upload the image metadata let's get into getting ipfs setup so that we can actually do that so the first thing that we need to do is we actually need to download the command line for ipfs so if you just google download command line again this will be in the description you'll come here and you can just download right from one of these all right so just click and you'll be on your merry way you'll know that you've done it right is if you can type ipfs and you get the command line print out here okay that's how we know we can do it right and once we've done that once we've downloaded ipfs we can go ahead and run the ipfs daemon right so we can do ipfs daemon and this will kick this will start a ipfs node on our local machine we can even view the web ui of it by clicking this in the in the in the output here this web ui button and this will show us where this ipfs actually is right and so this is the our ipfs node with the web ui which is fantastic so cool so we know that it's actually running appropriately now the other thing that i'm going to recommend you guys do is you guys should download ipfs companion companion for your for your browser right i'm using brave if you're using chrome whatever what have you uh it allows you to actually view ipfs hashes and urls in your browser and i do one other thing in my companion here i go to settings and i change the port to 502 or excuse me 5002 just so that it doesn't conflict with my local one right because if i'm running yeah just a 5002 just so it because it doesn't conflict with the daemon that i'm running right because the daemon here is going to be on port 5001 so i just changed this one to be 5002 and that way you can view both of them so great once we have those set up now we can actually continue on and we can move forward so we have our ipfs running let's create a new shell here and so now ipfs is going to be running on this shell so we'll be able to know if we've actually uploaded stuff to ipfs so we need to first like i said upload that image so we're going to do image to upload equals none we're just going to start from blank here and in the brownie mix we're even going to set it so that if upload ipfs the environment variable is true only then are they going to do it so os.getenv upload ipfs equals equals true then we're going to upload to ipfs right so we can do this we'll do export this equals true and now that that equals true we can even do like print hello run the script again oh i gotta redo it brownie run scripts advanced collectible create metadata network rank b if os os is not defined whoops and great hello okay perfect so now that means our environment variable is there so if it is defined we're going to have to get that image path image path which is going to be equal to oops already cheated and i added the images here um but a new image path right so so we have these these images here um and if you want to just create a new image like i said i already have them you can just do new folder you know image and then add the images there i copy pasted my images from the nft mix you can put whatever images you want here obviously mine are these cute adorable little puppies um so the image path which is going to be image variable png format format and this is going to be the breed but lower uh just because i have them set as lowercase 3.lower and i also have replaced replace i also replaced the underscores with hyphens so this is the image pass that we're going to upload these the images that we're going to upload to ipfs and then i'm going to say image to upload and this is going to be the image to upload to our collectable metadata equals upload to ipfs image path so we need a new function upload to ipfs so the way we were to the way we upload to ipfs is we're going to call this api right we're going to call the ipfs api which is located here and how we would do this with curl if we want to do this with curl and just kind of raw upload it we can do we can do this we can do curl dash x post dash f file equals at file equals at image slash pug.png http http slash localhost or for those who don't know 12 of 127.0.0.1 it's also known as localhost port 5001 slash api v0 add boom and this will give us a hash and it'll give us the response so this means it was successfully uploaded and here is the hash of that and we can even check to make sure that this is right by going to like a pinning service like pinata or something so i've already logged in to a pinata service here i highly recommend you guys get a pinata service as well or at least check it out and i've even already pinned it here let me let me just remove it this way you won't have to have your node up all the time right because if your node goes down nobody can see the images somebody else needs to have pinned this image up to so i would highly recommend using pinata so we can even add this cid here pug.png we'll give it a name search and pin great it's been added to the queue we'll refresh and great we have it here and if we click on it we can see that the image hash has been uploaded successfully which is fantastic right and again the reason that this is rendering is because we have our our ipfs companion working here so great awesome so we've done it here so that's how we successfully upload them with the curl now we want to do that exact same thing with this curl we want to do it in python right we want to do it we want to do it the raw python way so let's do this def upload to ipfs it's going to take the file path in now we're going to do with path file path dot open for the binary as file path once we open this we're going to say image binary equals fp.read ipfs url it's going to equal this localhost http localhost 5001 and then if you're using the mix you'll see like if os.g.envip fest url you know use that you can absolutely follow the follow the mix as well uh the mix also uses a emb config you can read a little bit more in the mix if you're following along there but so this is kind of the base url now we're going to do we're going to make that request to it so we're going to say response we're going to make that api call equals requests.post ipfs url plus this endpoint that endpoint that we just called which we can find going to the documentation here the ipfs api documentation which we know that this endpoint adds a file or directory to ipfs so we can say plus api v0 add now for files this is how we do that that file at syntax here files equals file image binary and we can check to see if this worked by doing print uh response.json right we should get that same uh that same response that we got when we call it like this oh and we also have to import requests so let's go ahead and try this by running the script let's see if this works looks like we ran into an issue here whoops i passed uh a past itself in there so i got to do image path sorry about that so image to upload is going to be upload to ipfs image path and then we're going to print the response here sorry about that now let's go ahead and run it and great we do get that same output that we got before right name file hash size great and let's go ahead and delete this now because it's going to get annoying so great so this has been uploaded successfully but that's not going to be the whole story right so that uploads it but we still need to get that url that uri of this image to add to our metadata right so now we got to do a couple other steps so we're gonna get the ipfsh equals response.json hash and then we're gonna get the file name which is gonna be equal to the file path dot splits we're gonna do a little bit of fancy python stuff here minus one zero and this just gets the name of the file path we can even print out the file name just to show you kind of what i'm what i'm doing here this gives us shivanu.png it's taking this file path it's splitting it up and then it's grabbing just the shift in you part of the whole file path right because the whole file path is like image you know dot slash image and we don't want that we just want shiva in you so great so now we have the file name we have the hash and now we have to make the image uri which is going to be equal to https ipfs.io ipfs slash this is where the hash is going to go excuse me file name equals and this is where the file name goes so dot format ipfs hash file name and we're going to print the image uri or actually since we should rename this since it's not just going to be the image this could be the image or the metadata so we're going to call this the uri we're going to say uri here print uri and then return uri otherwise we're going to return none so great let's see if this works so this should print out this file right here which great it does and if we click it if we option click it great it shows the picture of the pug which is exactly what we want and we've already um excuse me not the plug or the ship it menu and and this is actually this is the hash that we'd want to to pin on pinata not the pug that i i did before so upload cid so sorry this is going to be shiba inu dot png or is it it's hyphen it should be any png search and pin and great now we've pinned it and this is exactly what we want right so we're going to double check to see if it is the ship menu and it is which is great and again the reason that we're pinning in it on pinata is so that if our ipfs node goes down and when it goes down there's another node that still has it up so people can still access this data right so that's really important so great so we have the image uri perfect so now we have this image to upload we have everything set up we just need to now add the metadata up okay so how do we actually do that well we're going to go through the same process actually so we're going to say now collectible metadata right because we still have to assign it image equals image to upload right so now we're adding this collectible this this uh this uri for the image that we just got to that dictionary to that json object and now we have to paste this we have to print this into a new folder new folder rink it b in this rink b folder right and we're going to do with open metadata file name file with open metadata file name excuse me with openmetadata file name we're going to write to it as file json.dump collectable metadata file so we're going to dump this json object into this this metadata file and we have to import json here then again we're going to do if os dot get env up load ipfs equals equals true then we're going to do upload to ipfs for the metadata file name as well right so now if we run this it should upload both of these to ipfs we should see two and that's exactly what we do so then we can even take this copy it go to here add a cid and we'll call this the same name should it new.json we'll refresh we'll give it a little bit and i haven't added this in here yet but we could also programmatically uh pin these to pinata i just i just haven't added it in here yet so if you guys want to make that improvement to this mix you know please do but we've added it to the queue we should see here any second but if we go ahead and click this we should also see the json object returned and this is exactly what we want this is our completed metadata this is our com this is going to be our completed token uri for our nft now now we're hosting it on ipfs we've basically hosted our own api which is incredibly exciting and we can see that it is indeed it is indeed added here it is indeed added to our pinning service here awesome this is so exciting now for those of you who kind of want to skip over some of this stuff uh skip over the programmatic stuff i also added like this cheaty little dictionary um in the in the nft mix here uh called breed to image uri that i add right here i'm just going to copy and paste it from the mix uh basically it takes the images of the pug the shimmer and you the saint bernard and has their image url right here and then if we don't want to upload to ipfs every time we can just use this breed to image uri right so we can go down to image to upload we can actually say image to upload equals breed to image uri of breed if actually take this down one if not image to upload else upload to ipfs image path right so if we if this isn't set if upload ipfs isn't um if upload ipf um actually hold on excuse me image to upload equals this ah sorry else this so this is a little confusing basically we're just saying uh if we didn't upload this to ipfs then we're just going to use kind of this cheaty thing up here okay and gray and we'll still get the creative metadata but we have it set to be true so when we run this we are indeed going to get the um the metadata object but now we are also getting uh this this stopper here saying hey you know it's already been found you already made it you don't have to make it again which is great that's what we want because we do it we do have this correctly made right we'll even format it here we can see that in our metadata file this is indeed correct so perfect but this is perfect we've uploaded our images to ipfs we've uploaded the json to ipfs now all we need to do is set the token uri of that token that we've deployed right let's even redeploy the whole thing right so in our scripts here now we've got a couple of scripts so i'm just going to redeploy the whole thing so brownie scripts excuse me brownie run scripts advanced deploy network rinkaby and again you don't have to redeploy from scratch i just want to redeploy so i can let's just redeploy and see if everything's working as expected here okay advanced collector deployed to here let's even just copy this great clear we're going to do brownie run scripts advanced it's been deployed let's create a collectible network rinkaby we can even go to rink b ether scan this is our contract here now it's been funded we're calling create collectable right now right and remember this is going to hit the create collectable function and then it's going to make the vrf call return a random number and that random number is going to be the seed of our of our random dog and great dog breed of tokenite d0 is again a shiva in you so we actually don't even need to create metadata again but let's do it anyways so we'll do brownie run scripts advanced collectible create metadata network rink b and it's going to say hey you've already created it so it's not actually going to redo anything we can actually even stop our ipfs for now because we're not going to need it awesome so now the main the last main important thing if we go to open c right now and we go to our doggy so it might not be there right away you might actually have to wait for a little bit but as we can see nothing's here this is our doggies this is our pug here and it's like there's nothing about this it's a blank picture right uh so this isn't what we want we want to render in ipfs rents because we render it in openc from those ipfs images and metadata that we just gave it okay so how do we do that well let's create one more script called set token uri and this is going to be the last script that we need in order to set the token uri so we're going to need to get from brownie import advanced collectible because we need that contract and we're going to need a whole bunch of other stuff we're going to need from scripps dot helpful scripts imports get breed and probably some other stuff but let's just go ahead and start doing it so def main print working on plus network dot show active just so we can see the network that we're on and then of course we need to import the network so we can do brownie run scripts advanced collectible set token uri network rank b and it should just say hey you're working on rink b working on rigby great advanced advanced collectible we're going to do that same syntax as before we want to get the most recently deployed one of these so we're going to advance collectible length of a glance collectible minus one and then we're going to do is do a quick print to get the number of tokens that we have print the number of tokens deployed is and then let's actually get the number of tokens number of advanced collectibles equals advanced collectible dot token counter oops token encounter because remember every time every time we um deploy one of these excuse me every time we mint a cr create a new collectible we're actually going to increase that token counter right so this should tell us we've deployed just one so let's go ahead and run this that's exactly what we get the number of tokens you've deployed is one now why do we want this well because we want to loop through all the tokens that we have deployed and make sure their token uris are set appropriately so we're going to do for each token id in range number of collectibles so we're going to loop through all the collectibles that we've created let's get the breed equals get breed right from that that function that we imported from the helpful scripts get breed of advanced collectible dot token id to breed right because again we have that mapping in the advanced collectible called token id to breed of token id so we're going to get the breed and we're going to check to see if we haven't already set the token uri so if we if not advanced collectible dot token uri of token id that starts with https so i know that there's kind of a lot here but remember we have the advanced collectible contract has this token uri function imported from the erc721 of token uri that starts with right so we're going to say if this token id doesn't have a token uri that starts with https then we're going to set it right so remember how we did when we actually deployed excuse me when we actually create a collectible we're actually currently setting the token uri to none right so another way we could actually do this is we could say um if if it does start with none then we want to set it right either one would work so we're saying we're basically saying if we haven't set already let's go ahead and set it so i'm going to print setting token uri of that format token id and then we're going to set the token uri so i'm just going to go ahead i'm going to create a new function called set token uri of token id and we're going to give it the advanced collectible and we also need to give it the uh the uri that it's needed right the that json that metadata json thing that we printed out before right because remember above it was actually printing it out for us okay so what we could do is we could actually save that save that printed out you know string that printed out string i actually already saved all of them um i've already saved all of them and i'm going to cheat a little bit here i have this thing called dog metadata dictionary which has the um which has the hashes uh of the metadata of all the dogs already so i i cheated a little bit but yes another way you could do this and probably a better way too is maybe in your metadata file um so we have the shibbit inu.json maybe you have like another folder in here that's like urls.pi or some or urls.json right and it's just has and it you print this list in here so i think that might be a better one a better way to do it but i'm just going to go ahead and cheat a little bit copy and paste it here so i'm just going to say i'm going to pass dog metadata dictionary of breed so if it's a pug we're going to get the pug one should it you should have anyone saint bernard say bernard one right because we want to set the token uri of the token id on the advanced collectible contract with the correct token uri and i know there's a lot there's a mouthful here but we're getting there i promise we're getting there so let's create this set token uri function def set underscore token uri and we're going to take token id nft contract and token uri so what do we need to do well since we are going to make a transaction because remember on the advancedcollectable.sol set token uri it's a transaction that we have to make it's a function we're going to be changing the state of the blockchain so we do need that account so we've got to do this accounts.add again from config wallets from key and this means that we need to import config and accounts from key great now we can call nftcontract.set token uri of token id and token uri right remember if we go to the advanced collectible.sol it takes the token id and the token uri so token id token uri and as always we have to do from dev and then we're going to do a little print here we're going to print awesome you can now view your nft at here that format and i'm also going to do one more cheaty thing so i i know the openc format of these nfts you can of course just literally copy paste from here right boom the format is going to be the address of the contract and then the id of the token right so we took that we put it into this openc format variable but we variablized out the address and the token so we're going to take this open c format thing at and we're going to say open c format dot format token or excuse me excuse me nft contract dot address and token id oops token id and we're going to do one other print just because sometimes openc can be a little bit slow please give up to 20 minutes and hit the refresh meta data button oops refresh metadata button because sometimes it can be a little bit slow so if we've done it i'm not going to run this quite yet but if we haven't set it we're going to go ahead and set it else we're going to print oops i always hit that we're going to print skipping this we've already set that token uri dot format token id all right a little bit of moment of truth here so let's run this brownie run scripts advanced set token uri network rink b and if we did everything correctly all of that ipfs stuff both the metadata the json object is going to be attached then to our nft and we should be able to see it in openc let's go ahead and run this number of tokens you deployed is one setting token id of zero at this transaction let's see what happens here side note i drank a whole sleeve of brisk iced teas in recording this probably not necessary for you guys to know though and okay great we have this output here i'm kind of i'm kind of in the way but that's fine um so awesome you can now you view your nft at here please get up to 20 minutes so let's go ahead and click this option click and hopefully we've done it right so we see right now it's blank let's go ahead and refresh metadata and it worked we have our puppy here and it says shiva in you we have the image of the shiba in you here we can even go look into the details we can see its cuteness level 100. we can see that we've recently made it about 18 minutes ago i waited a little bit my opencv was being a little bit slow i fast forward here but now we can do whatever we want with this we can transfer this we can share this with other people we can do anything that we want right and we can see how powerful this is because we've uploaded an nft to a blockchain right and it belongs to us and we've given it uh we've given it attributes that can be viewed on openc on all these nft marketplaces so people can see what our actual looks like let's go ahead and and sign into to you know give this one some love of course you know give all these some love please and thank you um and yeah now we can see the power here right and we can go way beyond this we can make these nfts do anything that we want them to do right because all this really is is a whole bunch of code it's a whole bunch of code in here so we can make these nfts battle we can make these nfts be cards we can make these entities be pokemon we can make whatever we want to do we can do it here and i know this was a long video guys i know there was a ton of stuff we went into we talked about ipfs we talked about brownie we talked about the erc 721 token standard we went into a lot of stuff but we finally made it we deployed it from totally scratch from the beginning we deployed it to a test net and this works the same on maintenance it's gonna be the same thing some of the addresses are gonna be a little bit different but at the end of the day it's the same thing thank you all so much for watching this video i know this was a long video please leave any questions or comments in the comment section at the bottom there'll be a whole bunch of links in the description as well feel free to join the discord ask some questions on stackoverflow reach out for support uh super excited that you're beginning your nft journey here and hope you guys learned something i'll see you then oh and like and subscribe to the puppies you
Info
Channel: Patrick Collins
Views: 136,377
Rating: undefined out of 5
Keywords:
Id: p36tXHX1JD8
Channel Id: undefined
Length: 132min 8sec (7928 seconds)
Published: Wed Apr 14 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.