No doubt it won't be very useful if we don't do a course showing you how to pull data from the web.
And so this is the video for doing that.
Now we're going to use some external libraries to make life much easier.
We've already got ethers installed, so you just need to add these ones here.
So add them exactly as I have them with the exact same versions.
By now you should know how to do that.
For example, with request you can go cargo add request like such with a W and you can go features you
know which are going to be equal to Json.
And that's just one way you could go and add, for example, this item, or you could just type it out
exactly as I have it.
Just make sure you also build your project once you've added these libraries here.
Now request is similar to requests you can think of it as in Python.
It's a library that allows us to go and make requests to the web.
And so we're going to use it for making a web request.
And so Jason is very useful for let's say you're making requests to an API.
You don't know what data structure they're going to return and you need something to interpret that
data structure structure into strings and floats and numbers, etcetera.
So Jason is a great library for doing that.
I've used it an awful lot.
It's fantastic.
And it could even be pronounced Saudi.
I've heard it pronounced Saudi and said, so, you know, take your pick.
And when we're making API requests, we are doing so asynchronously.
A lot of the time we need our code to pause and wait for that request to complete and return a value
to us before the code continues.
You'll be used to asynchronous requests in whatever programming language you've come from.
And so Tokyo is a library that enables us to do that very easily using Rust, and I use Tokyo a lot.
So these are three as far as I'm concerned.
These are three libraries I have in almost every project that I use.
So definitely let's include those.
So that's step number one.
Step number two, let's create a module over here.
We'll call this seven and we'll call it async classes, not sync sorry async for async request classes.
And let's add that here to our mod as well.
So M seven async.
Great.
Now that we've got that created, we now need to configure our test.
So here, remember we were copying and pasting this before and this time I'm actually going to type
it out, but also because we're going to make a slight change.
So we're going to write our test piece here with Mod, and here we'll just call this tests and we'll
also use Super with a star to import all like such.
Great.
Nothing new there.
Now, instead of just putting test like this for our first test function here, we're going to write
Tokyo like such Tokyo test.
Going to import this from the Tokyo library.
And it's not just going to be a normal function.
We're going to make be making a call to the web.
So here we're going to write an asynchronous function.
So this will be an async function and this will be calls, you know, async function.
And here I'm just going to write tests.
Calls, async function.
And there we go.
That's what this will do.
Let's make sure that's all working, put in debug and let's just say our usual hello.
Make sure that that is working as expected.
So if we go here to save our file cargo test.
Like such.
And let's run it there.
And there we go.
We see.
Hello.
We are ready to get rock and rolling.
Now, the reasons why we're using Tokyo, the reason why is because we are making this asynchronous
call.
So we need to make sure that we give it this procedural macro here from the Tokyo Library.
If I was in main courses and I was making an async call from Main here, I would use Tokyo Main like
such, and then this wouldn't be a function anymore.
This would be an async function.
And that's how you can do this from the main function.
But given that we're learning through this unit testing approach, this is fine.
We've got it here and that's ready to now rock and roll.
So we need to build out our function at the top.
Let's do that now.
Let's have an asynchronous function.
So that'll be func FN and we'll call this my async func or my async call.
And let's pass in here a URL.
That URL will just be a string reference or a string literal like this and what will have it return
will be a result.
A nice result.
Enum from Rust and either it's going to return a value which will.
Right now we don't know what it's going to return in terms of its structure.
We haven't defined a struct to interpret with it and we'll be doing this a lot in the project section
of this course.
By the way, we will be converting whatever the API returns into exactly the structure we want, but
right now I don't know what that is.
So I'm going to borrow here something very useful from the Json library, which will be a value.
So we're either going to return that value or it's going to return a request from the request library
req w request error, and that's what this function is going to return.
So it's going to be either, you know, a Json formatted structure or it's going to be excuse me, this,
this error from the request library.
And so here's how we're going to write our request.
We're going to say let response.
Be equal to a in terms of its type.
So Jason and this will be here a value and that will be equal to request get.
So we're going to make a get request to the URL.
And so once we do that, you'll see it's throwing up an error.
If I just remove this type for now, let's see what it tells us.
We're getting put a semicolon in there and it's saying, look, this response here is going to return
a future.
Now, for the time being, it's throwing up this error because I'm not returning this adjacent value.
So what I'm going to do for now is I'm just going to actually remove this and just comment it out just
to show you what's going on here.
So this is returning a future, right?
It's a promise.
If you're coming from JavaScript.
Normally we'd need to do some kind of await to turn this from being, you know, a promise into some
kind of actual value.
So it's no longer a promise.
We're waiting for it.
And so there we go.
We can use this dot, await keyword and I'm actually going to, you know, push that down here just
to create some space.
So here's the future.
It's returning and then we're awaiting on that.
Now that await there is going to return some kind of result for us.
So I could either, you know, unwrap that.
If I unwrap that, I'm going to be, you know, faced with a problem that what if that return actually
failed?
Then my whole program is going to panic.
And because we know what I want to end up doing, I want to either return that there was an error.
So I don't want it to panic.
I just want it to return what the error was or the actual value.
If it was successful, I don't want it to do that.
And we'll get into error handling shortly.
We're not going to talk about that right now.
So right now what we can do is just put a question mark.
And what this question mark is doing is saying, provided that there's the right type of error we're
returning, if an error happens, it'll push it out as an error and return that.
So let's go back now and put this here.
At the top.
And you can see now we've got this await with a question mark.
And it would return an error if there was an error.
Now, we're still seeing an issue over here because we're not quite done.
You know, this is not matching what we want to return over here.
So let's finish off this code.
So once we've awaited that, we should be able to then go and convert that response into a Json format
using.
And here you can see I'm using our turbo fish over here using the Serde Json library and basically converting
it into that struct that value there and open and close parentheses.
And then that also needs to be awaited.
That's also an asynchronous request.
And here we put our semicolon on the end.
Now, once we have that, we need to return the result.
And so our result here is going to be returned as okay.
And that is going to be our response like such.
And you can see all my errors have gone away.
Now, usually what I do, by the way, when I'm building a function so I don't just see this compiler
error when I'm trying to build is I either remove this completely and put it in at the end after I've
built the function, or I'll just put okay on the bottom of the function, right?
So you don't get all those compiler errors.
But what's happening over here is we're getting some kind of response and if we don't get a response,
then this will throw an error and it will feed an error back to whoever's calling this function, whatever
task is calling this function.
Otherwise, it's going to go and take the output of this and put it into a Json format for us and await
that.
And if for some reason it can't put it into that format, it's going to then also return an error.
So again, it will return that error up here as such.
And what I can do here where it's got value is just basically say this must be a Json value.
That's what I expected to return.
If it doesn't, it will basically do the equivalent of this.
Okay, except it will return an error with whatever that error is.
That's what these question marks are doing.
Now let's go and actually make that call over here so that we can we can go and deal with this.
And so here I'm going to say let API URL, which will be equal to a string.
Now this is important when I'm doing this right now today, it's, you know, it's the 2nd of June 2023.
Okay.
And so I'm going to use this API endpoint here as the URL.
We're going to call Before you go doing that, go to your browser and paste this endpoint in.
You should see a bunch of text get returned like this.
If you do, the endpoint is working.
If you don't, there's no point in trying to call it with rust because it doesn't matter what programming
language you use, it's not going to work.
Make sure you find an API endpoint that's public that you can call just like this in your browser and
you can replace this with that endpoint if for whatever reason you're not able to connect to that.
All right, so there's our string slice there.
And then what I'm going to do here is I'm going to say let my result and that's going to be equal to,
you know, make my my API call over here.
And what do I need to do?
Because this is an asynchronous call and being made from an asynchronous function.
Well, this is a future now because it's going to just get that as a promise.
So I need to await that.
And there we go.
Now I've got this as a result, and it's going to be a result of either that adjacent value or an error.
And so what I can do now is use a match statement to actually handle whatever that result is.
If the result is okay and I'm just going to put R for result.
What I'm going to do here is just print line as follows or even debug is probably better to use here
debug and we're going to debug our like such.
Otherwise it's going to be an error.
And if it's an error, I'm just going to put an underscore here for now and I'm just going to say panic,
you know, failed.
Failed to make request.
Uh, like such.
Okay, that looks good.
And remember, I need my fat arrow here as well.
Perfect.
Now, I don't want to return anything, so I'm just going to put a semicolon on the end there and I'm
going to add those on my debug and my panic here as well.
So let's go.
Cargo run and test this.
So cargo Sorry.
Test not cargo run.
Cargo test.
And this will be no capture like follows.
And let's see.
There you go.
We've got our data returned here.
You can see if I actually maximize this for you.
You can see it was returned from that API call.
And what's really cool about the Json library is it's now wrapping this in string.
It's wrapping this as a Boolean.
It's wrapping.
This is a string.
It's cetera.
And when we get into the project of this course, we will be absolutely working with all the values
we make on the call right now.
We don't need to take it much further because you're going to get very used to dealing with making API
requests.
But for now, this is pretty good.
You can see we're able to go and pull data from the web and actually handle it.
If there was an actual error, I'd like you to take note here as well that we are being forced here
to handle the error.
Right?
If I want to get the values out of this, I have to use a match statement pretty much.
I could also do the if let okay.
Result etcetera.
But it's the same thing.
I pretty much have to do it.
And I could choose not to deconstruct an error over here and or patent match to an error over here.
I could choose not to do that.
But then again, I'm making that decision consciously as a programmer.
I'm given the opportunity to handle the error, and this is one of the things that makes rust really
good.
If you're building, say, a backend web server or something, it's going to force you to deal with
error handling in a way which can keep your app running, etcetera, or handle the error however you
want to handle that error.
So brilliant.
Now what I'd like to do, you know, in an up and coming video now is deal with error handling.
Let's talk more on that.
In terms of here we use the question mark, but what are some of the other options we might have?