Now in the last lesson we saw how we can use variables and constants in the Motoko programming language. 1
We also saw how we can import libraries from the Motoko-based library and use it to do things such as 2
printing into the console. 3
In this lesson, we're going to dig a little bit deeper and we're going to add a little bit more functionality 4
to our actor, which is the DBank canister that we control. 5
Now, one of the things that we're going to have to do if we are creating this money market is we're 6
going to have to let people be able to deposit their cryptocurrencies or money into our application. 7
And in order to do that, we're going to have to create a function. 8
So in the Motoko, functions are created with the func keyword similar to the Swift programming language, 9
if you ever use that. 10
And then the next thing is we get to give our function a name, which I'm going to call topUp, and 11
then we open up a set of curly brackets and we get to define what happens when this function is triggered. 12
So let's say for now, we're just going to increase the current value by $1 each time this topUp function 13
is called. To make it less confusing, let's first comment our previous debug print. 14
So when we've increased the current value, at the very end of the function before it finishes, we're 15
going to try and print the new value of this variable. 16
Go ahead, pause the video and write a print statement using Motoko to print out the current value at 17
the end of this function. 18
All right. 19
So again, we're going to use the Debug.print function and then we're going to need the debug_show to 20
be able to slot in this variable inside here. 21
Now, let's go ahead and actually use this function. 22
Just below where I've created this function, I'm going to call it. 23
And you'll see that you might get some errors here because we haven't closed off this function with a 24
semicolon. 25
So you have to be quite careful with this programming language where every function expects a semicolon 26
to cap it off. 27
So now we're going to describe how this function works, 28
then we're going to call it and if we go ahead and hit dfx deploy right now, you'll see that in the 29
printout we get 30
is the current value that's being printed right here on line 12 is now 101 because we've incremented 31
it by one and then we printed out the current value. 32
And that is all through calling this function inside our DBank canister. 33
Now this is what you would call a private function. 34
It's a function that's only accessible within this particular actor's curly braces. 35
Now, as you've seen before, when we had the Hello World application, when we first did our setup, 36
we can actually call functions within canisters from the outside. 37
So I'm just going to comment this line of code out and I want to be able to call this code from the 38
command line. 39
If we take a look at the documentation for that hello example that we've already run, 40
you can see it tells you that after you've hit deploy, you can use this structure in the command line 41
to get the canister to call a particular function within a particular canister. 42
Now you can also insert an input to that function, but in our case, we have no inputs. 43
It's empty in here. 44
So all we need to do is just to call the function. Following that format, 45
all we have to do is write dfx canister call, and then we have to put in the name of our project, 46
which you can see here is all lowercase dbank. 47
And then we're going to have to put in the name of our function, which is called topUp, and notice 48
how it's spelt. 49
Now there's just one problem, and that is the fact that this function is currently private to our actor 50
DBank, which, as I said, means that it can only be called from within these curly braces, like we 51
did here. 52
So that means when I go ahead and hit run here, I'm going to get an error 53
and it's going to tell me that this canister, which corresponds to my DBank canister, it has no update 54
method called topUp. 55
It actually cannot see this function because it's private. 56
So what can we do if we wanted to call this function for this canister from the outside? 57
Because in the future you can imagine you could have an application that's very complex with multiple 58
canisters. 59
How can you call a function within another canister? 60
Well, we have to add a modifier keyword up here called public. 61
And this is going to expose this function to the public, to outside this canister basically allowing 62
us to be able to call it from the outside, for example, from the command line here. 63
So let's go ahead and hit save on this file to update the changes. 64
And then we're going to have to use dfx deploy to make sure that this new code gets deployed into 65
the canister. 66
And then once that's done, we can try that command again where we say dfx canister call this top 67
Up function from our DBank. 68
And you can see now it has executed and we've got that 101 being printed over here again. 69
So this is how we can create a public function in a canister and how we can call it and get it to run 70
from the command line. 71
Now, what if we didn't want to have to type all of this out every single time? 72
What if there was a way that we could have a simple user interface to be able to just click a button 73
and get the functions in our canisters to run without having to type a whole bunch of stuff? 74
Well, the team have already thought of this, and this can be done using the candid UI. 75
Candid is called an interface description language. 76
And basically it's kind of like... I don't know if you've seen these API documentations which are interactive. 77
For example, if we take a look at the one for GitLab, you can see that there is a try it out section 78
where you can access certain paths or certain API endpoints and you can interact with these while you're 79
exploring the documentation. 80
So Candid basically provides a really easy way for us to interact with our canisters. 81
And it doesn't matter if the canister is written in Motoko or Rust. 82
Basically, instead of using our dfx command line, we can actually use Candid to specify input arguments 83
or get it to generate random input arguments or display return values from our canister methods. 84
And that means we can actually get a 85
UI to interact with instead of having to work with the command line all the time. 86
Let's try it out for our basic a new program. 87
So the first thing we have to do is we have to get the canister ID for this interface. 88
You can either go ahead and copy this code here from this link, which I'll provide in the course resources, 89
or alternatively it is just simply dfx canister id 90
and then this is two underscores Candid with a capital C underscore UI. 91
And once we put that into our terminal here, you can see we get a canister id back, which we're 92
going to need because we're going to go to the localhost server that's currently running and we're 93
going to add a question mark and then the query, which is CanisterId with capital I, and then we're 94
going to set it equal to whatever it is we got back from this command. 95
So let's try it out. 96
So I'm going to copy everything up until the equals sign and then after the equals sign, I'm going 97
to paste in what I got from here. 98
And now when I hit run, you can see it's asking me to provide another canister ID, so be careful 99
here. This ID that it wants is the canister ID for our program, 100
so in this case it's all DBank program. And we can get a hold of that ID by simply using the command 101
dfx canister ID and then provide the name of our canister. 102
So in our case it will be dfx canister id and the name of our canister is dbank, as you can see right 103
here. 104
So now let's hit enter and we'll copy this id which you can see is separate from the candid UI ID 105
and then I'm going to paste it into this field. 106
Don't worry about this one. 107
We don't have a did file and then we're going to go and hit the go button. 108
So now all Candid UI has been created. 109
We did absolutely zero front-end work, but this is automatically created by it reading our canister 110
code in here. 111
So you can see we have a single function that can be interacted with, which is called topUp and here 112
is where you see it. 113
So now instead of having to type dfx canister call, blah blah blah, I can actually simply just 114
tap the call button and it will run the same command. 115
Now once it's run, we can confirm that it worked by seeing the output here. You can see our current value 116
has been incremented yet again by one because we called it and we can keep doing that as many times 117
as we want. 118
And basically this candid ID simplifies how we interact with our canisters when we are testing and 119
writing our code. 120
So what if we wanted to change our function so that we can add an input? 121
Because normally when you top up, you don't just top up by $1 each time, right? 122
In order to add an input to our function, we're going to have to fill some stuff in these brackets. 123
So we're going to provide a name for the input, which I'm going to call amount. 124
And then in addition, we have to provide the data type of this input, which in our case can be a natural 125
number or shortened to nat data type. 126
So natural number, as I mentioned before, is any natural number that is positive, 127
so starting from zero, going up. Now instead of incrementing by one, we can increment by the amount that 128
was specified. 129
If I go ahead and save my file and then go ahead and run deploy again to update, then when I go back 130
over here and refresh, you can see we've now got a field that we can type into and it's telling us 131
is expecting a natural number. 132
So let's say I decide to top up $12. If I go ahead and hit call, you can see that this is going to run 133
and then we've now increased our total amount by 12. 134
So that is how we managed to add an input to our function. 135
Now some of you, I know, are really keen-eyed and you might have noticed something quite interesting. 136
Previous to the last deploy we were on $103. 137
After I deployed the new code, it went back down to 100, added the $12 that I topped up, and we're 138
back onto 112 instead of 103 + 12, which would have been 115. 139
So why is that? 140
Well, that is related to this concept called orthogonal persistence, which we're going to talk about 141
in a lot more detail in a future lesson. 142
But for now, let's just assume that every time we run dfx deploy, all our variables get wiped and get 143
reset to their initial values. 144
So now that we've created the topUp function and we've seen how we can allow the user to provide an 145
input to say how much they want to top up into dbank, 146
it's time for a challenge for you. 147
Which is to create a another function which will allow users to withdraw an amount from the current 148
value 149
and then once they've done that, we're going to decrease the current value by whichever amount they 150
provide it. 151
So try and create this function called withdrawl. 152
And again, this function requires an input, and then the function is going to decrease the current 153
value by whatever amount is specified. 154
And finally, make sure that you actually print out the final value of currentValue. 155
So pause the video here and see if you can create this function. 156
Once you're done, run the code and test it out on candid UI. And then afterwards we're going to run through 157
the solution together. 158
So, 159
pause the video now. 160
All right. 161
So again, because we need to access this function from the command line and from Candid UI, we're 162
going to make it a public function and then we're going to call it withdrawl. 163
And then we're going to provide an input, which again, I'll call amount and it will again be a 164
natural number, 165
so a positive number that we're going to withdraw from our bank. And simply we're just going to do the 166
opposite. 167
So the current value we're going to -=, so decrement, the currentValue by the amount that 168
was specified. 169
And then finally we're going to Debug.print the current value after the decrement has happened. 170
So if this is what you've done, then great. Let's go ahead and hit save to save our code and then 171
we're going to run dfx deploy to update our canister with the latest code. 172
And if we go back to our Candid UI and hit refresh, then you can see we've got our new function showing 173
up here, 174
our withdrawl function. And if I go ahead and specify an amount, say $10 to withdraw from the bank, 175
hit call and then go back over here, 176
you can see it's now decreased from 100, which is the current value by 10, which is what I specified. 177
And now it's on 90. 178
So there you have it. 179
We've got a withdrawl function, we've got a topUp function, and we're able to see these functions 180
and interact with them using our Candid UI user interface on the frontend. 181
Now there's just a couple of bugs that we've still got to iron out and the main issue is here in our 182
withdrawl function. If the user decides to withdraw a extraordinarily large amount, an amount that 183
we don't have in the bank, then you can see our current code is going to provide an error, something 184
called a natural subtraction underflow. 185
So in the next lesson, we're going to learn more about how to work with conditionals in Motoko and 186
make sure that we fix this issue. 187
So for all of that and more, 188
I'll see you in the next lesson.