🔍
How to implement an ERC721 Token and connect it to OpenSea (DAY 2) - YouTube
Channel: Kie Codes
[0]
Welcome back to day two of my journey to
develop my first-ever crypto collectible
[5]
and smart contract for the Ethereum blockchain.
If you haven't watched the first video I highly
[11]
recommend it. Today we will write our first
smart contract in solidity and figure out
[16]
how we can connect our own NFT
to marketplaces like OpenSea.
[21]
If this sounds like a lot of work
you're right it was a hell of a day.
[33]
So here is the idea: I want to develop
a non-fungible token called Date Token,
[37]
so you can mint your own token for every date
in our calendar. From year one till now. Unless
[43]
somebody else already owns that token. Every Date
Token is unique. You could mint your birthday,
[49]
or the date of the moon landing or the
invention of the light bulb, whatever
[53]
date you want to own. And I want to store all the
needed information inside of the blockchain: year,
[60]
month, and date. That sounds like a small and
achievable goal for one day let's see how it goes.
[67]
Some of you might ask: What is an NFT?
NFT stands for non-fungible token. A
[72]
token is something you can have inside
of your wallet. If you have one ether,
[76]
that would be one token of ether inside of your
wallet. But what does non-fungible mean? Fungible
[81]
means replaceable by another identical item
and non-fungible means basically the opposite.
[86]
So if I give you a dollar and you give me one
of your dollars we both end up again with one
[90]
dollar. There is no value difference in your
dollar to my dollar. Dollars are fungible.
[95]
But if we were to trade Pokemon cards. I give
you one of my Pokemon cards and you give me
[100]
another one of yours. We both have the same
amount of pokemon cards after the exchange,
[104]
but the value of the two cards is not necessarily
the same. Pokemon cards are non-fungible.
[109]
The same goes for the Date Token. If
I owned the date of the moon landing
[113]
and you own some other random date, I
certainly don't want to trade with you,
[116]
because the intrinsic value of my
date might be higher than yours.
[119]
I learned that there are different tokens on the
Ethereum network and each token needs a certain
[125]
smart contract to be implemented in order to work.
If you want to create your own currency you would
[132]
need to implement the ERC20 token and for NFTs
you use ERC721. ERC20 and ERC2721 are basically
[142]
interfaces you need to implement in your smart
contract in order to be recognized as a currency
[147]
or an NFT on the Ethereum network and so that
other dApps can identify and use your tokens.
[154]
If you have looked into NFTs before, you
certainly found the website OpenSea. OpenSea is
[159]
a marketplace. On there you can buy and sell your
NFTs. All of these are so-called ERC721 tokens.
[165]
You can also create your own NFTs here on OpenSea.
You just need to upload whatever graphic, video,
[170]
or audio file you want and OpenSea creates an
OpenSea NFT for it. What OpenSea basically does,
[175]
is creating an OpenSea token, which is connected
to your media file using their own smart contract.
[180]
But doing that would be way too easy. We want
to create our own smart contract. In order to
[185]
create our own ERC721 smart contract, we could
write implementations for all of these functions.
[190]
Or we could use OpenZeppelin: A library
for implementing different types of ERC
[195]
tokens. OpenZeppelin can be installed using
NPM and helps us by implementing almost
[200]
all of the functionality we need for our
ERC721 token. We just need to fill in the gaps.
[206]
So I installed OpenZeppelin using NPM and built my
[209]
first ERC721 smart contract.
This is what we got so far.
[214]
I created a file "date.sol". I added
a little header. I imported the
[219]
OpenZeppelin ERC721 contract and the contract
date is ERC721. I call the constructor,
[227]
define my own token name, and my own token
symbol. I inherit all the functionality I need.
[232]
And, yeah, let's try to
compile it. "truffle compile".
[237]
So the next step is to actually migrate
our smart contract to our local ganache
[242]
blockchain. As far as I know, I
need to write "truffle migrate".
[247]
Okay, it went through. In ganache, there's a tab
called "contracts". Going there I see a Migrations
[254]
and I see a Date contract, but it is not deployed,
[258]
which means we have to add our Date
contract to our migration script.
[262]
For that to work, we need a new file in
our migrations subfolder starting with a
[267]
2, so it's the second migration step. I call that
[271]
"2_token_migration.js". In there i need to load
my smart contract and deploy it to the blockchain.
[279]
So what's basically happening here is,
that we import our "date.sol" file somehow
[285]
and we export a function that calls the
deployer to deploy our data. Let's try it out…
[291]
And this time you see, that a
second migration phase is executed:
[295]
"2_token_migration.js", "Deploying Date"
[298]
So if I open up ganache now
I see that our contract Date
[302]
is actually deployed and has the
following address. That worked …
[306]
After this first success, All I need to do is to
implement the rest. I want to store the year month
[311]
and day on the blockchain, I also want that
the user can add a title to each date, and
[316]
I have this idea of different materials to make
minting more exciting, but more on that later.
[321]
The development cycle for smart
contracts basically works like this:
[324]
You implement a function. To make sure it
works, you implement a Unit Test for it.
[328]
truffle.js comes with a testing framework
so you can make sure your smart contract
[333]
works before you deploy it locally to
a test net or finally to the main net.
[337]
It has been a couple of hours now and I
think I have the Date token smart contract
[342]
ready. So here's what I got so far …
[344]
I want to store the year, the month, the day, a
title for the date token, and the color on the
[349]
blockchain. So what I did is to define this struct
metadata. I added this mapping here, where I map
[356]
the token-id to the metadata. This is basically
how you store data inside of the blockchain.
[361]
The constructor is executed when you deploy
your smart contract to the blockchain
[366]
and because I want to have
some Date tokens for myself,
[369]
I call this mint function nine times to generate
some interesting Date tokens for my wallet.
[374]
The mint function takes a year, month, day,
and a color, as well as a title to create a
[380]
new token. It's defined "internal" so only the
contract itself can call it and nobody else can.
[387]
In order to create a token for
yourself through the web app,
[391]
I have a different endpoint
defined which is "claim".
[394]
It has the same parameters, not the color because
the color is randomly chosen, it's external so
[401]
everybody else can call it, and it's
payable so you have to pay a little fee
[404]
in order to create your own Date token.
[406]
It costs 10 Finneys to create a Date token. So if
that is not given you get a little error message.
[413]
And then we check the incoming parameters
for validity. If they are valid, I generate a
[418]
different color based on some probabilities I have
chosen. Put it into the mint function and transfer
[426]
the 10 Finneys that you have to pay to my account
because I am the owner of the smart contract.
[431]
I can "get" a Date token: So I
want to read the metadata that
[435]
is associated to a token-id. So
that's the "get" function here.
[439]
I can get the title of the Date token.
Either by token-id or by year, month, day.
[445]
I can change the title of the Date token. But
only, If the token exists and, down here, if
[452]
the owner of the Date token is calling this
endpoint. If you don't own a Date token,
[456]
you can't change the title.
If you own it, you can.
[459]
One cool thing is that truffle.js comes bundled
with a testing framework. The first thing we
[465]
test is if, after deployment of the date token,
the owner of the Date contract is correct. In
[470]
the test environment, the first account in the
ganache blockchain is deploying the contract.
[476]
So we check if the deployed contract
date has the correct owner. Like this.
[482]
We check if the name is correct, if the token
symbol is correct, we check for the base URI
[487]
or the token URI. Then we check if I as
the owner get all the Date tokens that
[493]
I have defined in the constructor.
And then I check that minting a date
[496]
actually works and that you have to pay
the 10 Finneys to get the date token.
[500]
I know that I went over this code
rather quickly, but remember the
[504]
link to all the code is down in the description
below if you want to have a closer look.
[507]
Now, let's try to run the
tests, compile the contract, and
[512]
migrate it to the ganache blockchain.
[515]
"truffle test" runs the test suite. All the tests
[518]
went through successfully. Let's
compile the contract: "truffle compile"
[524]
"truffle migrate" to migrate the contract
to the blockchain, but since we already have
[529]
migrated the contract to the blockchain
once, we need to add "--reset" to the
[534]
command line parameters so we reset the
blockchain and can redeploy our contract.
[541]
Bringing up ganache now, I see
that the contract is deployed
[544]
and that I paid a little bit
of gas for the deployment.
[547]
Looking at MetaMask, we see that MetaMask is not
showing the nine Date tokens, that we should have
[554]
because of the deployment of our smart
contract. But we can add the token…
[559]
Go to "custom token" and
paste the contract address
[562]
here. It automatically reads the token
symbol. We go "next" and see nine Date tokens.
[568]
So now in our MetaMask wallet, we see the
nine Date tokens, that we own. Amazing!
[574]
If you remember OpenSea and all the little
images on it, you might ask yourself:
[579]
"how does OpenSea know what
to show for each token?"
[582]
Looking at the OpenSea developer documentation,
[584]
you see that each ERC721 token has something
called a "tokenUri". In there you can store
[590]
any kind of URI and OpenSea reads this to
get its needed information. It basically
[595]
expects a JSON like the following. In here the
title and description of the token is defined,
[600]
as well as a link to an image, and some
optional arbitrary attributes. So what we
[605]
need to do is to implement a service which
returns the JSON for each of our tokens.
[610]
After I found out about this, I
spent the last couple of hours
[614]
thinking about a nice representation for
our Date tokens so they look good inside
[619]
our collection on OpenSea.
Here is what I came up with…
[622]
The Date token should be represented by this
futuristic-looking card. On there we have the date
[629]
written out, as well as the token-id and a barcode
encoding all the information of this token. The
[635]
top half consists of three parts. We have five
squares in the center which encode the day of
[640]
the month. So it looks different for Elon Musk's
birthday or the moon landing or the start of the
[646]
Ethereum blockchain. It is a 5-bit encoding
of the numbers 1-31. The triangles represent
[654]
the month. So January looks different than June or
December. 4 bits for 12 months. And the last part,
[661]
the dots on the circle, represent the year.
Which again is simply a binary encoding.
[668]
OpenSea supports animated SVGs. So, of course, I
want it to be animated. And because I want to have
[676]
some rarity factor for each minted date token, I
also invented eight different colors: blue, green,
[684]
red, black, silver, gold, neon, and pearl which
get chosen randomly during the minting process.
[692]
Now, let's program a
javascript express.js service,
[697]
which generates those SVGs and
the JSON needed for OpenSea.
[703]
So how did I do it: I implemented an express.js
server app. I used web3.js to connect to our
[711]
ganache blockchain like this. After that, I got
all the contact information from our compiled
[717]
JavaScript ABIs that truffle generates
in order to interact with the contract
[723]
and handing in the contract address from our
migrated contract. This way I can actually call
[729]
the functions inside of our smart contract. Then
I have one endpoint for OpenSea to get the JSON,
[736]
and another endpoint for
OpenSea to get the SVG image.
[740]
Inside of the first endpoint, I call
a contract method "get". You remember
[746]
"get" is the contract method that returns the
metadata that we store inside of the blockchain:
[751]
year, month, day, color, and title. And
I use this information to generate the
[755]
JSON for OpenSea and to put in the URL to our
SVG endpoint to get the right representation.
[762]
And down here we generate the SVG. All of the
code generating the SVG is inside the "svg.js"
[770]
file that I put into the repository
as well. So if you want to look at it,
[774]
there's a link in the description below.
[777]
And that's it for today good night.
[780]
Day two is a wrap. And what a day it was!
[784]
If you want to follow my journey
consider subscribing. Thanks to
[789]
my patrons for helping running
this channel. I see you in one
[792]
of my other videos if you want. And
as always have a lot of fun coders!
Most Recent Videos:
You can go back to the homepage right here: Homepage





