All right. 1
So let's get started. 2
And to get started, I want you to head over to the course resources in this Udemy lesson and download 3
the open starter compressed zip file and then go ahead and unzip it and move the folder to your project 4
folder. 5
So I'm going to drag it into my ic-projects and then I'm going to open it up inside VSCode. 6
Now if you take a look through the source folder, you'll see that we've got a main.mo file which 7
has basically nothing in it. 8
And then we've got our assets file which contains most of the frontend with a lot of the HTML already 9
written for you. 10
There's quite a lot of styling involved in this project, so there's long sort of class names, but 11
if you just see them for what they are, which is just individual HTML elements with some styling applied, 12
then it's pretty simple. 13
The part that we're going to focus on is to make sure that our backend and our frontend actually works 14
together nicely. 15
So we're going to be walking you through that step by step. 16
The first thing we're going to do in our project, though, is to actually create a new canister file. 17
Normally, we've always been working within the main.mo file, but in this case, because we're 18
building an NFT and each NFT is a new instantiated canister on the Internet computer blockchain, we 19
actually shouldn't really be building it within the main file because this is going to be the backend 20
for our NFT marketplace. 21
So it's the e-commerce part. 22
So the first thing we're going to do inside this source folder is we're going to create a new folder 23
which I'm going to call NFT. 24
And inside here I'm going to create a new file called nft.mo. 25
So this is our nft. 26
mo File. 27
In addition to creating the actual Motoko file, we also have to add it to the dfx.json. 28
So you can see in this JSON file, we've got all our canisters listed here. 29
We've got opend, which is the main.mo file, 30
we've got the opend_assets, which is our canister for our frontend, 31
and now we're going to add one more canister. 32
So you can either add it after this one or for simplicity's sake, 33
and I think it be less bug-prone, if you add it after this first opend canister after the comma, then 34
we can create our nft canister. 35
So let's add a comma here. 36
And then inside here we're going to declare our main, which is going to be the source of the location 37
of our source file for this canister, which is going to be inside the source folder, this one. 38
And then we have to go into the NFT folder, so /NFT/nft 39
.mo. 40
This is what you should have if you've named everything the same as me. 41
And then we're going to give it a type for the type of code that's inside there. 42
And it will be Motoko. 43
Cool. 44
Now we can go back to our nft.mo and we're going to create a new actor which we'll call NFT. 45
And then inside this actor, I'm going to add a simple debug just to make sure that it actually works. 46
So as usual, we import our debug from mo:base/Debug, and I'm going to do a debug. 47
print and I'm going to print 48
It works. 49
Once that's done, let's try and get it to actually initialize and work. 50
So bring up your terminal by going to new terminal. 51
And the first thing we're going to do is we're going to run npm install. And this is going to install 52
all of the pre-added requirements in the package.json. 53
There's quite a lot of things in there, and we've used a lot of those things before. 54
So if we go ahead and just run this command in our terminal in VSCode and grab a cup of tea, then 55
after a few minutes it should be done. 56
All right. 57
Once that's done and all our packages have installed, then we're ready to do the next part, which 58
is to spin up our local dfx with dfx start. 59
And once it's a running on localhost, then we can split off another terminal and here we can run dfx 60
deploy. 61
Now, once all your canisters are deployed, you should see over here in the panel where you've got 62
dfx start running printing 63
It works, and it comes from the canister, which is the ID for nft.mo. 64
So this is our NFT actor here. 65
If you manage to get to work here, then brilliant. 66
If it didn't work for you, one of the things you can try is try stopping the terminal here and then 67
rerunning dfx start. 68
Otherwise, check to make sure that you've got your dfx.json properly written and properly formatted 69
and that your files are named the same as mine. 70
And your file path is exactly how it should be. 71
There's many points of failure here, so just check a few things and go back in the video. 72
But once we've all gotten here and it says it works, then we can move on to actually creating the contract 73
for our new NFT canister. 74
This NFT is going to have to have a number of properties associated with it. 75
We might have a itemName, for example. 76
We might have a nftOwner. 77
We might also have something that will store the imageBytes, so the actual image data. 78
And in order to fill up these properties, we have to pass it in 79
when we create this new actor. Instead of simply creating our actors as we have done before, we're 80
going to create what's called an actor class. 81
Now, the reason why we're creating an actor class rather than a simple actor is because this is going 82
to allow us to create our canisters programmatically. 83
And that's really important if you're making a website that's going to allow people to mint their NFTs, 84
a place where they can upload that image and we can create that canister programmatically based on the 85
things that they've uploaded and the information they've provided. 86
So in order to change this to an actor class, we have to add the class keyword after the actor keyword 87
and then after the name of our actor class, we're going to provide the input, 88
so the data we're going to use to initialize this actor class. 89
Now, in our case, the things that we need is a piece of text for the name of the NFT. 90
We're going to need a owner, which is going to be passed in as a principal. 91
So that means we're going to have to import that principal type as well. And then we're going to need 92
to give it some content. 93
This is going to be the actual image data, which in our case we're going to store as an array of eight 94
bit natural numbers, 95
so Nat8 is the data type here. 96
We can actually store the image data in bytes through using an array of natural numbers. 97
Now the numbers will look pretty wild and you can take a look for yourself if you look in the read me. 98
You can see that it basically just looks like all of these random numbers. 99
But it's encoding the bits and bytes for our images. 100
Now, we're going to use the read me a little bit later on. 101
But right now, let's finish building up our NFT actor class. 102
What's going to happen is when we initialize this actor class, we're going to initialize it with all 103
of these values, and then we're going to use those values to set the properties for our NFT. 104
So our itemName is going to be equal to the name that's passed in, 105
the nftOwner is going to be equal to the owner that's passed in, and the imageBytes is going to be 106
equal to the content. 107
Now that we've defined all of this, we actually have all the code we need to create an NFT, believe 108
it or not, because each of these NFTs are going to have a unique thing which is going to be their unique 109
principal ID. 110
So whenever we create a canister, we know that we have these principal IDs that gets created. 111
For example, our main canister opend has this principal ID and the NFT canister which we minted 112
just now, has this particular ID. 113
And every single time we programmatically create a new NFT through building this actor class, then 114
it will be assigned a new, unique principal ID, which is going to uniquely identify that particular 115
image or resource. 116
And it cannot be exchanged for anything else. 117
It's not equitable to anything else, and hence it is how we create a non-fungible token. 118
Once we've created our NFT and it captures all of these pieces of information, we need some ways of 119
getting hold of it right? 120
So let's go ahead and add some query functions; public query func and the first one is going to be 121
getName and it's going to return asynchronously a piece of text that describes the name of our NFT. 122
So we'll just return the itemName property here and then we're going to build these query functions 123
for all the other properties. 124
Next, we're going to return the owner. 125
So we'll call this getOwner and this is going to asynchronously return the principal ID of the owner 126
and we're going to return the nftOwner property. 127
And finally, our last function for now at least, is going to be for us to get hold of our asset, 128
so getAsset. 129
And this is going to return our byte data. 130
So it's going to be an array of Nat8 numbers and we're going to return the imageBytes. 131
And with those few lines of code, we've actually created a simple contract for how to create a new 132
NFT programmatically using the Internet computer. 133
Now all we have to do is give it a spin. 134
So let's hit save and let's go ahead and deploy this canister. 135
But notice that you can't simply just do dfx deploy and the name of the canister is 136
nft. 137
Now, if I go ahead and actually run this, you'll see it will give me an error. 138
And the error is quite mystifying. 139
Invalid data. Expected arguments, but found none. 140
And this is, of course, what I wanted to show you, which is that when you create a normal actor, 141
you can simply do dfx deploy because it doesn't expect any arguments. 142
But now that we're creating an actor class, we do need to provide all the arguments that we promise 143
to provide. 144
So we have to initialize it a little bit differently. 145
Now, if you take a look inside the read me file 146
and you can put it into preview mode if you want, 147
you can see that I've created the command line argument for you already. 148
So here we're using the -- to input the argument, and the argument goes in on the command line 149
and in quite a strange formatting. 150
It is just the way it is. 151
It has to go in between these quotes. 152
And then we've got a set of parentheses and we've got our three arguments. 153
The first one is the name, 154
so I'm going to call my NFT CryptoDunks and then I'll just add a number afterwards to simulate what 155
they have on Opensea. Next is the unique principal identifier of the owner right here, which I'm adding 156
in as a format like this. 157
Now, in your case, you should replace this with your actual principal, and you can find this out 158
by going to the terminal and writing dfx identity. 159
Again, try to not make too many typos like I am. And then it's get -principal. 160
And if you haven't made any typos, then it should output your own principal for you as the command line 161
user. 162
Now go ahead and copy that and you can paste that and then you can use it to replace what I've got inside 163
here. 164
So simply just delete that and then make sure that your principal ID goes in between these double quotes 165
after the word principal. And don't change any of the spacing or any other formatting here. 166
It can easily go wrong. 167
Once you've done that, then you can copy this entire thing from the dfx deploy all the way to the end. 168
And this is going to allow us to deploy all our canisters and provide this as an argument to any of 169
the canisters that needs it, which is going to be our NFT canister right here. 170
I'm going to copy everything here and then paste it into my command line and hopefully it's going to 171
create my brand new NFT and we're going to mint a new piece of artwork. 172
So the artwork data is stored in here and it's just a simple 10 by 10 pixel art. 173
So that way it doesn't have that many bits and bytes to store. 174
And in addition to the raw data, we provided all the other pieces of input that's required. 175
So hopefully we should get our successful deployed canisters. 176
Now, how can we check to make sure that it actually worked? 177
Well, we've got our query functions, right? 178
So we can go ahead and query our canister, which, if you remember, is called nft and we can get hold 179
of the name that we gave it, the owner or the asset. 180
Let's try that. 181
So we'll do dfx canister call and then the name of the canister which is nft and 182
then the name of the function which I'm going to call getName. 183
So it's get and then capital N and you don't have that, the parentheses, when you're calling the function 184
in the command line. 185
So let's hit enter and we get the result back, which is what I said just now when we created it. 186
CryptoDunks number 123. 187
And again, I can use the same thing to call getOwner and I can also call getAsset. 188
Although unless you are a computer, you won't be able to interpret this as an image. 189
It doesn't describe the rdb values, it doesn't describe anything that we can really relate to. 190
It's just the raw data in bytes. 191
In order to be able to view our newly minted NFT, we're going to have to build up the frontend, which 192
is what we're going to do in the next lesson. 193
So for all of that and more, I'll see you there.