Now that we've managed to get our login authentication working, the next step is to be able to use 1
the authenticated account to claim from the faucet and to be able to use that principal ID as the msg. 2
caller. 3
So in the case where we've got our faucet.jsx here, we should be able to call instead of token. 4
payOut, 5
we should be able to call the authenticated canister and call the payOut method on that canister. 6
In order to do this, we have to write a little bit more code. 7
The first thing we're going to do is we're going to import our authClient class from the Dfinity auth client 8
module. 9
And in addition, we're going to import some other elements from our declarations. 10
In addition to token, we're going to need the canister ID and also the create actor method. 11
And these come from our declarations. 12
And if you look inside the index.js, you can see that we created our blank internet computer project, 13
these methods have already been created for us. 14
The create actor method, which basically creates the canister, and the canister id is basically just 15
a environment variable that is replaced at runtime. Coming back to our faucet.jsx, now that we've 16
got all the necessary imports, 17
the next thing that we can do when the click happens, 18
so when the faucet is being clicked on, once we've disabled the button, the next thing we can do is 19
we can create a authentication client in the same way that we did in our index.jsx. 20
So we have to await for this process and we're going to use the AuthClient.create method. 21
And once it's been created and we've gotten this auth client back, then we can use it to get the identity 22
of the authenticated user. 23
We can again use our await and we're going to do authClient.getIdentity. 24
Make sure that you don't make any typos and that you've got both of these awaits in there. 25
Now, we can use this identity that we get back to create a actor. 26
So, as I mentioned, createActor, 27
you can see it inside the declarations, and it's going to take the canister id, which is a environment 28
variable that contains the principal id of the canister. 29
And in addition, this createActor can take some agent options where we can supply the identity of 30
the authenticated user. 31
So I'm going to create a authenticatedCanister constant, and I'm going to call the createActor method 32
and I'm going to supply both the canister ID, by using this environment variable here, 33
and in addition, I'm going to supply an object. 34
These are going to be the options for creating this actor or canister. 35
And the options I'm going to set are the agent options. 36
Which is again going to take a 37
object, 38
so curly braces, and I'm going to parse in the identity that we got back from the authentication process. 39
And let's add our commas and semicolons, and just check that you've spelt everything correctly. 40
For example, createActor or getIdentity and that you've got all the semicolons and curly braces in 41
the right places. 42
So now, it's with this authenticatedCanister that we're going to call the payOut method on, because 43
what that's going to mean is when it gets back to this payOut method, the msg.caller will then 44
be the principal ID of the authenticated user. And it's that authenticated user who's going to be getting 45
the token transfer. 46
Unfortunately, though, even if our code works and it's correct, we can't actually test it at the moment 47
because if I go ahead and click on 'Gimme, Gimme' in the faucet, you'll see 403 error code. 48
And the reason is because we're running a local version of dfx, which is a simulation basically 49
allowing us to test and debug. 50
But in order to have the sign off and to get the authenticated session, we need to deploy our project 51
onto the live Internet computer blockchain. 52
That's what I'm going to do right now. 53
A caveat to this is, of course, you need to have enough tokens for it to work. 54
So if you're low on cycles, then you might need to transfer and convert some ICP tokens into cycles 55
as I've shown you before. But once you're done, deploy it onto the live network, which you've done 56
before. 57
But just in case you wanted to be reminded of the command line command, you can take a look inside 58
the read me and under the section deploy the project to the live IC network, 59
you can see step by step how we're going to do this. 60
Instead of writing out the commands which is super prone to error, I want you to simply copy it step 61
by step. 62
The first thing we're going to do is we're just going to do dfx deploy --network 63
ic. 64
And as long as you got enough tokens, this should go through in a couple of minutes. 65
Once all the canisters have been deployed, 66
the other thing that we needed to do, if you remember, was to transfer some tokens into the canister 67
so the canister actually holds on to half the tokens and the owner yourself will hold onto the other 68
half. 69
And the half a million that the canister has is going to be used to distribute through the faucet. 70
There's a couple steps that we need to go through to do this. 71
Firstly, we need to check the live canister's ID because it will be different from the one that you 72
have been running locally. 73
Once you've managed to get hold of that, you can see that we're going to put that command inside another 74
command in order to embed the output into a new variable, which we'll call the live canister key. 75
And once we've done that, let's just check that it actually worked by echoing the variable back out. 76
And you can see that we've now got the correct format in order to assign a principal ID. 77
So finally, we can call the transfer function on our live canister and transfer half a billion tokens 78
into it. 79
And once that's done, you should get success back. 80
Now, once you've successfully done that, then we want to be able to get hold of our live deployed canister 81
front-end 82
ID. Remember that in our project we've actually got two canisters: one which is token that contains 83
our main.mo file, 84
that's our business logic, 85
that's our backend 86
that's going to talk to the blockchain. 87
We've also got another canister which is our token_assets which contains our frontend, all of that 88
React and JavaScript goodness. 89
So this is the access point that we want to get to from a browser and to find out its ID, we have to 90
call this command in the command line. 91
So it's dfx canister --network ic id 92
and then we pass in our canister, which is token_assets. 93
And once we get that ID, then we combine it with the suffix .raw.ic0.app and that will take us to the live 94
version of our faucet application. 95
Again, we've got our pop-ups blocked, so let's make sure that's unblocked and let's refresh. 96
And because this is first time that we're accessing this website, we need to authenticate ourselves. 97
And you can see this time we're now proceeding to authenticate on our live website. 98
Coming back here, 99
we're going to repeat that test that we did before, which is where we try to use our faucet. 100
And because we're running on the live network, you might notice that for that success to pop-up, 101
it might take a little bit longer than it would when you're testing locally because it depends on 102
how busy the network is. 103
Now, once that's successful, that means that our authentication actually worked. Because that worked 104
instead of giving us a error like what happened previously, 105
that means our authentication code is actually working and we're using the authenticatedCanister with 106
the identity that's authenticated to pay out into that id's account. 107
Unfortunately, because we're not running this locally, our debug print don't actually come out in 108
our terminal. But we don't have to print it out here. 109
We can actually get hold of it on our frontend. As soon as we've authenticated ourselves or if we're 110
already authenticated, then we get access to this auth client here. 111
So let's go ahead and console.log the identity from our auth client. 112
So getIdentity, 113
make sure that you haven't made any typos. 114
And once you've got that, go ahead and deploy to the network again. 115
Now, once that's done, let's go ahead and hit refresh. 116
And if we take a look inside the console, then you'll see that what's being printed is that authClient 117
.getIdentity. 118
It's the same identity that we used in our faucet to create our authenticated canister. 119
Now this identity contains four really important things, but what we're interested in is getting hold 120
of this principal which exists under the property _principal. 121
So that means that we can actually get hold of the principal of the logged in user simply through this 122
identity. 123
Let's save this into a constant. 124
And we actually should put an await here 125
so the line reads const identity = await authClient.get identity. And I'm going to use that 126
to get hold of the userPrincipal, which is the identity._principal. 127
So I'm just going to copy that piece in here. 128
Now remember that at this stage it's still looking somewhat like this, right? 129
And we have to use the two string method in order to convert it into a string so that we can actually 130
read it. 131
And once we've got that, I'm going to firstly console.log this userPrincipal. 132
So now let's hit save and let's redeploy our changes. 133
And once that's done, let's go ahead and hit refresh again. 134
And now we've got our familiar format of principal IDs. 135
If I take that principal ID of the, remember this is my authenticated user's principal ID that we got 136
hold of through all of that convoluted process, 137
if I check its balance, you'll see that this account has the 10,000 138
DANG that I fauceted out earlier when we tested the faucet. 139
So that means our authentication works and it's actually the authenticated user who is logged in and it's 140
with that identity that we called the payOut method. 141
Now, just for convenience sake, it would be really nice if I could actually see my principal ID here. 142
So I'm going to use a feature of React to bring it onto the frontend so that we don't have to console.log 143
it each time. 144
And the way we're going to do this is through props. 145
So I'm going to call my prop loggedInPrincipal and I'm going to pass it the userPrincipal that we 146
got hold of right here. 147
So it's the name of the prop = {the name of whatever you want to pass through.} 148
Now I can go into my app and I can get hold of the props in here. 149
And I'm going to pass it over to the faucet. 150
The faucet here is going to have a userPrincipal prop, and it's going to be equal to the props.-- 151
and then it was the name of whatever I gave it here, loggedInPrincipal. 152
So let's go ahead and add that there. 153
And now I can go into my faucet and go ahead and get hold of the props that get passed in. 154
I sort of typed it wrong. Not pops. 155
And once I have got hold of that, I'm going to add the props into this label here. 156
Instead of to your account, I'm going to add in the props right here. 157
So it's props, and then the name that I gave it, which is userPrincipal. 158
So let's put that here. 159
Let's hit save and let's again deploy and make sure that that worked. 160
So now when we hit refresh, you can see instead of saying to your account, it's actually printing 161
out our authenticated user's principal ID which is really really neat. 162
So now all that's left for us to do is to do the same thing in our transfer.jsx. 163
So instead of calling the token.transfer here, we want to use the authenticatedCanister through 164
the same process that we did with faucet. 165
So I'm going to set this to you as a challenge, and I want you to pause the video and try to get this 166
to work so that when you transfer to a particular account, 167
so if I use this previous anonymous account's principal ID, I should be able to put it here and then 168
transfer something over coming from my authenticated account. 169
At the moment it doesn't work because this transfer function is not hooked up to use the authenticated 170
Canister. 171
I want you to fix this and make it work using what you learned about authentication previously. 172
Pause the video now. 173
All right. 174
So the first thing we got to do is to add our import. 175
So I'm just going to copy and paste that over here, and I'm going to need the canister ID and the create 176
Actor. 177
We don't actually need this token anymore, so you can take it away if you don't want it there. 178
And we're going to add the canister ID and createActor into our transfer. 179
Now here, just before we call our token.transfer is where we're going to create our authClient 180
and we're going to need to call the await AuthClient.create method. 181
And with that, we're going to then create the identity. 182
Again using await and then using the authClient.getIdentity method. 183
Identity-- 184
Yep. 185
Make sure you spell that right. 186
And then finally, we can use the identity to create the authenticatedCanister, which is, of course 187
done through the imported createActor method. 188
And we're going to pass in the canister ID 189
and some options. 190
So the agentOptions is going to be another object, which is going to contain the identity that we 191
got hold of just now of our authenticated user. 192
So now instead of calling token.transfer, we're going to replace that token with the authenticated 193
Canister.transfer. 194
But still transferring to the recipient that the user typed in and the amount they wanted to transfer. 195
Now let's go ahead and hit, save and deploy our changes. 196
And once that's done, we can try this again by refreshing and then putting in the same information, 197
click transfer 198
and now, after a really long wait, we've got success instead of insufficient funds. 199
And if we check the funds for our current logged-in user, you can see it's 200 less. 200
And if we check the account that we transferred to, you can see it's successfully received the tokens. 201
So now we're able to authenticate ourselves using the Internet identity, and using the authenticated 202
user 203
we're able to create a canister and call methods using that identity. 204
Now, we've achieved a lot in this one project, so I hope you really enjoyed it. 205
And in the next project, we're going to be building an NFT marketplace. 206
So I hope you're excited. 207
And I'll see you on the next project.