Build a Decentralized Bike Rental App on Binance Smart Chain | Travis Rodgers | Skillshare
Drawer
Search

Playback Speed


  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x

Build a Decentralized Bike Rental App on Binance Smart Chain

teacher avatar Travis Rodgers, Freelance Web Developer

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

    • 1.

      Welcome and Project Overview

      8:07

    • 2.

      Creating our Smart Contract

      48:10

    • 3.

      Finalizing Our Smart Contract

      30:31

    • 4.

      Project Setup and Building the FrontEnd

      24:26

    • 5.

      Building the Dashboard

      35:25

    • 6.

      Connecting MetaMask and Talking To Our Contract

      60:19

    • 7.

      Building the Add Renter Form

      33:29

    • 8.

      Populate dashboard final optimized

      37:23

    • 9.

      Optimizing UI and Security Checks

      38:50

    • 10.

      Owner Bonus Features

      2:37

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

162

Students

--

Projects

About This Class

Create a Decentralized Bike Rental App on the Binance Smart Chain using Solidity for the Smart Contract and React/Ethers.js on the front end. A solid project for your Web3 portfolio.

Are you looking for a unique Web3 project to add to your portfolio?

Perhaps you're looking for more practice with Solidity, Ethers.js, or just blockchain development in general?

Or maybe you are tired of using Ether in your projects and want to explore the Binance Smart Chain (and its low gas fees)?

Well, this project checks all three off the list.

In this decentralized bike rental app you'll learn:

  1. How to use BNB in Remix IDE instead of Ether.
  2. How to create a secure Smart Contract in Solidity and deploy it to the Binance Smart Chain.
  3. How to interact with your Smart Contract and the Blockchain from a React front-end.
  4. How to display error messages from your smart contract on the front-end.
  5. How a decentralized project like this can provide sustainable income for the owner.

AND... as mentioned above, you'll have a solid Web3 project to add to your portfolio.

Prerequisites:

This course is not an intro to Web3 technologies. If you have NOT explored the Web3 ecosystem, then go and work through my hands-on Web3 technologies introductory video first.

Also, if you have not used Solidity or need a refresher, here's an optional Solidity tutorial that I created.

If you have:

  1. Basic working knowledge of HTML/CSS
  2. Basic working knowledge of React and React Hooks
  3. Basic understanding of Blockchain technologies

Then you will do well in this course. Go and get started!

Meet Your Teacher

Teacher Profile Image

Travis Rodgers

Freelance Web Developer

Teacher

Hello, my name is Travis Rodgers and I am a Freelance Web Developer, Blogger, Content Creator, and Digital Strategist over at Travis.Media.

Web development is not only my profession, but my passion, and I have over 4 years of hands-on experience building websites and providing custom coding solutions for small businesses, start-ups, and web agencies.

Whether it's a CMS like WordPress or a framework like Django, it's always thrilling to be able to create unique projects from scratch and share with others what I've learned along the way.

So I hope to bring value to all of you and help you in your own programming journey.

See full profile

Level: Intermediate

Class Ratings

Expectations Met?
    Exceeded!
  • 0%
  • Yes
  • 0%
  • Somewhat
  • 0%
  • Not really
  • 0%

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. Welcome and Project Overview: Hello everyone and welcome to my course. In this course we're gonna be building a decentralized bike rental application on the finance smart chain test net, we're going to start off by coding a smart contract and putting all of that logic together. Then we're going to deploy it out to the finance smart chain testing it. Next we'll build out our UI. So we're gonna be using React. We're gonna be building a homepage in a dashboard page. And then finally, we're going to connect that front-end with their deployed smart contract so that we can interact with the blockchain in make transactions and pull data in all of that good stuff. And sometimes it's just better to see it in action. So here's a look at the final application in an explanation of how it works. Okay, so here's the application. So imagine that you have a lot of bike trails in the downtown area, and you buy a little office space and put a bunch of bikes in it and set up a bike rental business. But instead of accepting cash or debit card or whatever, you're going to accept B&B. So if I wanted to come in there and rent a bike, I would come to this app. If this was my first time, I would first connect my wallet. So click Connect wallet and connect your wallet. And then I'd click choose my bike. And here we have a form. It says, Welcome, Please enter your first and last name to register. You have to register yourself as a renter on the smart contract to check out bikes. So I'm just going to put Travis test and hit Submit. Then I'll confirm the transaction in MetaMask. And by the way, I look at these low gas fees, this is like $0.20. So Confirm. Once this is done, it's going to display my dashboard because I'll then be a renter on the smart contract. So it says welcome, Travis or whatever your firstName is. Here are your stats. So there's B&B credit. So I can add credit to my account. My amount due, my amount of ride minutes, if I check a bike out and my bike status currently it's red, which means I don't have any bike checked out. Now we have two forms. One to credit your account, one to pay your dues, and we have three bikes to choose from. And I can come down here and check out a bike and check back antibiotic. So let's go ahead and credit our account. I'm going to add in 0.2 B&B to credit my account. So my total is 0.2 with some minimal gas fees. So hit Confirm. And when this transaction completes, I'm going to have 0 to B and B credit. So now I'm ready to check out my bike. I have some credit in here. And I want to check out, let's say I want to check out this middle bike. So click checkout and confirm that. And what's going to happen here is my bike status is going to turn green, which means I have a bike checked out currently. In my ride minutes will start to total up and I'll be able to take my bike out for a ride. And we're still pending. There we go. My bike status is green. The bike is free to take out for a stroll. I'm going to come back in about seven or eight minutes and we'll check the bike back in and I'll show you the rest of the app. Okay, so it's been about eight minutes, so let's check the bike back in. So I'm gonna come down here and click check-in and confirm the transaction. Now what's going to happen is my bike status will go back to red, which means it's not checked out. My B&B do will be totaled up in my ride minutes will total as well. So my bike status is red. My B&B do I have 0.005 B&B in my ride minutes or at eight. So now I can pay my B&B, do 0.005 BNB. And click submit. Confirm that. Now once I pay my balance, this is going to go to 0. My ride minutes will go to 0 and my bike status will be back in. I'll actually be able to check out a bike again. Because if you have a balance, you're not able to check out a bike because you've got to pay your balance in that kind of keeps the owner free from having to chase people down. This is a way that the owner doesn't have to be super involved with his customers. He just needs to provide the bike. Because if you don't pay your balance, you can check out another bike. Now, on our smart contract, we also have a lot of checks in place to make sure renters don't do things they shouldn't like trying to pay my do when I don't have a due amount. So if I click Submit, it should throw an error. I should have an error slide in up here, giving me some kind of error message. Yeah, execution reverted. You do not have anything due at this time? If I try to do something else like check antibiotic that I never checked out, I should also get a message. Please check out a bike first. And that's basically the gist of the application. In addition to this, at the very end of the course, there's a bonus lesson where we build out an owner's dashboard. This dashboard, it's going to show the total amount of the contract, the amount that's the owners, the button that gives the ability for the owner to withdrawal his amount. Now you may be wondering, how does an owner make money off of this? So if someone comes in here and credits their account with $10, it actually credits the smart contract with $10, but that $10 is allotted to them. So when they pay their do, it actually comes out of their credit in that amount that they pay actually becomes the owners. So every time somebody pays their Mountain Dew, that transfers over to the owner. So we'll be creating at the end as a bonus and owners dashboard where they can actually view that amount and withdrawal that amount. So I had a lot of fun building this and I know you will too. So who should take this course? We'll see if any of these scenarios appeal to you. Number one, maybe you're looking for a solid Web three project to add to your portfolio. So maybe you're learning blockchain development and you want to land that job and get into that industry, but you need some solid projects to add to your portfolio. Then this course is for you. Maybe you've done blockchain development with a thorium or on the Ethereum Virtual Machine. And you're wondering how it works with B&B or how you can use BNB and remix, or how you deploy to the BSC test net, then you will find this course beneficial. Or maybe you just want the whole package. You want to learn how to create a smart contract, how to deploy it, and how to interact with it from a library like React. Or maybe you're interested in seeing how we can display solidity errors on the front end to let our user know when they've made a mistake. Or maybe you're just interested in how an application like this would provide sustainable income for the owner. If any of these appeal to you, then I think you're in the right place. Now there are a couple of prerequisites. Number one, you should have base web development knowledge. So you should probably have learned HTML and CSS and have built a couple of easy web pages. Number two, you should have a base understanding of JavaScript and react. So we're gonna be using a reactant this course and that's gonna be expected. It's not gonna be crazy like we're not going to be using Redux and have all this elaborate stuff. We're going to try to keep it simple, but you should still have that base knowledge. And then finally, you should have an understanding of the blockchain and how it works, which I assume you do or you wouldn't be here. And as far as solidity goes, you don't have to know solidity to take this course because I have an optional lesson with a solidity primer to get you up to speed if you don't know it. I think you'll have as much fun as I did building this app. So let's get started. 2. Creating our Smart Contract: Okay, So if you go to remix.ethereum.org, we're going to use the re-mix IDE as we should. Change my workspace to the default workspace. Click on contracts and create a new one. Just right-click new file. And let's call it bike chain because I'm not very good at making up names, but bike chain, blockchain, kinda catchy. Then as always with solidity, you're going to put it in your license identifier. So this is commented out SPD license identifier MIT, which means open-source dinner, pragma statement, pragma solidity. Then we're just gonna do 0 dot dot 0 because that's a good number. And we'll say contract and we call this bike chain. And here we go. Isn't it exciting to have a fresh screen to codon? Anyway, I had some complaints and a previous video that it wasn't big enough. I can make this part of the code bigger, but not really this over here. So bear with me. So as we usually do, Let's start this off with some pseudocode and it's going to go something like this. Add yourself as a renter because you've got to add yourself as someone who can rent a bike, checkout bike. You'll go and you'll check the bike out. Check in a bike. So you check out the bike, you ride it around and then you check it back in. Get total duration of bike use. So how long were you on the bike? And then we want things like get contract balance just because it's good to have that info and specifically get renters balance. And then with this total duration, we need to be able to set the amount due, like how much the rent or O's. So set due amount. And I think this is a good start. Let's start with, this will go from here. And I'm having this error down here. It's because I didn't put a semicolon behind this. I've been in JavaScript the past few days, so bear with me if I forget the semicolon. Alright, add yourself as a renter. And actually before we do that, one thing I like to do is to set an owner. So if whoever deploys the smart contract, that's the owner in case they want to restrict things to just themselves. So to do that, we'll just put a, a variable up here, a storage variable of owner of type address. We'll create a constructor. And we'll set the owner to message dot sender. And what this does is this constructor runs when it's first deployed. So when this contract is first deployed, the sender who is gonna be the person deploying it is gonna be set as the owner. Now smart contracts are immutable. They are on the blockchain, they can't be changed. So this constructor runs once and the owner will be set. So we're going to put that before pseudocode. So here's the first one. Add yourself as a renter. So we'll create a struct called renter and we'll set some properties. So first, address, payable wallet address. Because each renter has a wallet address, everything in Web three is a wallet address. We can identify the person we can pay the person, the person can pay other people. And that's a type of address and we set it as payable. By the way, if you're like, I have no clue what this stuff is, this pragma in this payable. I created a YouTube video not too long ago. It's about an hour long. It's called Learn solidity in one hour. If you want to go and check that out first, I'll explain to you all the datatypes wouldn't address is what a payable is. And we'll go over things like functions and loops and we'll actually create a pretty easy smart contract so I can teach you how Solidity works. So if you have no clue what I'm doing, go and watch that, then come back to this. I think it will be very beneficial for you. I'll put a link below to that. And again, it's a free YouTube video. So they have a wallet address. Next, we're gonna do String firstName. And of course String lastName. Because even though they are a wallet address, we want some kind of personality behind it. Then we're going to set a couple of Booleans so bool can rent, can they rent, are they allowed to rent? Are not allowed to rent. You will see how this works in a minute. Bool active, are they active? Are they currently on the bike when they check it out? There'll be active when they check it back in, they won't be active. Balance. They can send money to their balance to cover the fees. And then a couple more UN's. So the amount due this is the amount they have to pay. So they take the bike out and it costs this many minutes in a totaled up to this amount. This is what's due. And then you went to start an end so we can keep track of the start and end time so that we can get that time span. You went end. And that's it. That's all I want with my renter. And we created that in a struct which is like an object. If you watched my Learn solidity in one-hour video, what we did there is we created an array of renters, and then we just did a loop to find the index that we wanted. Whenever we wanted a particular renter, we would look up the wallet address, get that index. We'd know the renter is. In this video, we're gonna do something different. We're going to not use an array. We're going to use a map, which I think makes it a lot easier. And you don't have to deal with loops, which sometimes if there's too many of them or if there are an unknown amount of loops, it could cause high gas fees. So we're gonna do a thing called mapping. It's like a dictionary, it's a key-value pair. Do mapping, and the key will be the address. The value is gonna be the renter. Will make it public, and we'll call it renters. So we can look a renter up by their wallet address. We won't have to loop through anything. We can just say, here's the wallet address, give me the renter. And finally, we can make this ad renter function for air parameters. It's going to be the renter parameters. So we're gonna say address. Actually, it's probably easier just to copy this, paste it in, because we're going to put the exact same thing as the parameters. Take these semi-colons out and put commas. And by the way, that's Command D. If you select something and do Command D on a Mac, you can just select the next instance of it and then change all of them at once. And I didn't change this one. And then I can take like the whitespace and hit backspace. And there we go, put a space between them and they're all in a line. So all of these just correspond to the properties and the renter. That's all it is. Then take off this trailing comma and put my curly brackets. And then from here we want to add this renter to our mapping. And to add to a mapping, you just do renters, right? Because they're mapping is called renters. And in brackets, you put wallet address because that's our key. Addresses are key. In this, by the way, is the type, the type is address. In our wallet, address is going to be the key. The value is gonna be the renter. So to add something to a map, you just use like renters wallet address equals one or something in it adds a key of wallet address in a value of one. But instead of one, we want a renter. We're going to add a renter with the same values above. Wallet address, FirstName. Lastname can rent. Active, balance. And let me turn on. Do they have a word wrap Word Wrap and editor doesn't seem to be. Oh, there we go. I had to cut it off and cut back on. But it's down here in these options. Balance, do start an end. These are our parameters. So we're going to use this Add rent or function. We're going to put in all the parameters we want and it's going to create us a new renter. In this map. It's just going to, It's just like a push. In JavaScript. We're just pushing a renter into this mapping or dictionary or whatever you want to call it. Now I have an error. What is going on here? No visibility specified. And Yup, we want to make this public. We have another error and data location must be memory are called data. So strings have to be memory are called data, which we're going to use memory. And that should clear the error. Awesome. So that's our ad rent or function. If I open up the deploy tab over here, and I just choose the JavaScript VM. Click Deploy. We can test this out. So add renter. So let me put my values here. So I'm going to choose just an address up here and account address you've got a bunch to choose from. You can use one as the owner and the others is the non owner, but right now it doesn't matter. So I'm going to copy the first one, paste it here. Now FirstName, I'm going to put Travis. Lastname. Let's put test. And then can rent. So true, everybody can rent upfront active, false. And then the next four are gonna be 0, so 0000. So let's try adding a renter. Down here. It looks like it was successful. And if I choose renters and put in my wallet address, which is our key, we can look it up by clicking renters. And there I am. Here's all of the values of the renter I just added, so everything is looking good. Now, close this out and continue on. Alright, so next on the pseudocode is to check out a bike. So let's do a function called checkout. And we're going to pass in an address. Like I said, you're gonna be seeing this a lot because I'm going to check out a bike and when I pass in my wallet address so that it can identify, that's me checking out the bike. And I want to make it public. And inside of it, I want to flip a few of my renter properties, two different values. So when I check out something, I want to set active to true, right? So. Renters wallet address, dot active. So this is the renter width, this wallet address in the mapping, dot active equals true. So this is, hey, I just checked out a bike. I'm currently active. The next thing I'm gonna do is I'm going to record that timestamp. So renters dot wallet address dot start equals block, dot timestamp. Now this used to be used to just type now. But now in solidity you use block dot timestamp. So this is gonna give us a timestamp and that's in part converter. So it's a Unix timestamp is not like a month, year kind of thing. It's a unique time Unix timestamp, which is a uint8, which all dates in Solidity RUN. So we're going to set the start time. And we also want, if you think about it, if they check out a bike, we need to set the can rent to false. It starts out, hey, I can rent. There's no restrictions on me, but once I check a bike out, I need to set that can rent to false because I already have a bike out. Let me select this, paste it and do can rent false, this person cannot rent a bike because they already have one. And I think that's good. So now we can check out a bike. Now, let's check in a bike function, check-in, address, wallet, address, public. And we're gonna do something similar here. We need to flip active back to false because they're not on the bike anymore. We need to set the end time. Now, we set the start time, we need to set the end time. So end is blocked timestamp, this will give us the timestamp for the check-in. Then finally, we want to set the amount due. So remember, they have this due property. This is how much they owe based on how long they had the bike out. We'll do that in a few minutes. So I'll just put up put it to do here, to do set the amount due. And that's checking in a bike so we can add a renter, we can check the bike out and we can check the bike backend. Next, get the total duration of bike use. And let's create a function for that. We'll call the function get total duration and address, wallet address. We're passing in the wallet address for an identifier. Public in this returns a U, and so it's going to return to us a total, the total duration as an integer, a U, and an unsigned integer. So the first thing we can do is we can subtract the end time from the start time. Remember it's in a Unix timestamp, so we can just subtract the two. But I'm going to create another function to do that. So I don't have to pull in a lot of parameters here. I'm going to call this renter timespan. You ant start, you went end. And I'm going to keep this internal to the contract. And it doesn't do any of that, doesn't alter the contract, are really touch any variables outside of this function. So I can label it as pure. If it did interact with some other variables, I could do it as view, but pure means that I'm not touching any variables. I'm doing all my work right here in the function because I'm passing in these two values. And this returns a uint8. And it's as easy as saying return, end minus start. So back to my function here. I can say u and timespan equals renter, timespan, renters wallet address, dot start. And we'll see other parameter. I'll put my start time in my enzyme. So it's going to be the same thing. But the end timestamp, the ND, that should get the difference between the two. And so this is in seconds. So I want to get this into minutes. So I can do uint8 timespan and minutes equals timespan divided by 60. 60 seconds in a minute. That should do it. And then return timespan and minutes. And I have an error here it says function state mutability can be restricted to view. So I can put here a view. So it's not quite as low as pure. Pure doesn't even read other variables. It only deals with this function view will read other variables but not alter the blockchain in any way. Then if I needed to change a value or something, it would tell me I have to remove view. That's all that is. Again, if you want a deep dive on this stuff, check out that solidity and 60 minutes where I go through all of these things in detail. Let's good. So we've got the total duration of why queues. So we've got the time, the total duration in minutes, and we can move to the next piece of pseudocode. So these are just simple methods that we can make use of. So like get the contract balance, we can do function balance of view public returns, a uint8. In all we do is return, address. This dot balance. Now this looks ugly and you're probably like, what is this for? Well, this refers to the contract returned, the contracts balance and this is kinda convention. You'll see it in solidity. Just accept it, memorize it, and if you ever need it, use it. So I can get the balance anytime you return the address dot balance of this, It's the contract. And then to get the renters balance, Let's do that one function, balance of renter. And we want to know which Renner. So let's address wallet, address. Public view returns. You end. And we just want to return the balance of that particular renter. So renters wallet address dot balance, semicolon. So we've got renters balanced, we've got the contract balance, total duration of bike use. The next thing we wanna do is to set, is to set the due amount. Now for this, there's a bunch of ways you could do this. What I'm gonna do is I'm going to say every five-minutes they have the bike. I'm going to charge 0.005 B&B. So B&B price USD. Alright, so 0.05 is $2. So every five-minutes you're going to pay $2. So I'm going to use that 0.005 BNB. And one thing you might be asking, if you haven't asked already is, hey, this is remix.ethereum.org. What are we doing with B and B? Well, the binary smart chain uses the same amount of decimals as a theorem. The theorem has this 18 decimal system so that it's able to have small fractional parts of one ether. And it's the same thing on the ByteDance smart chain. It's 18 decimals. On the bayonets chain, it's, I think eight, but the biomass smart chain is 18. So we can technically do anything here in ether. And it will transfer over to the finance chain when we go to deploy this. We're actually when we go to test it, you'll see here in a minute. So that means I can take this 0.005 and move that decimal place 18 and assume that that's way. Which way is like ten to the 1800s of an ether? It's a smaller number, which means it has more zeros. It's a way to break up your ether into fractional amounts. We can assume that's the same on BNB and I'll show it. This will all make sense to you here in a minute. So let's write a function set. Do so we're going to set the due amount of a particular address. This is gonna be internal. We're setting this internally. We don't want anybody else messing with this. Let's put timespan, minutes equals get total duration. So we're, we're calling this function to get the total timespan and minutes. Let's get that. Then we're going to break this into five-minute increments. So if there's 20 minutes on the bike, it only counts as four minutes because we're only counting five-minute intervals. So five-minutes You're gonna be charged 0.005 B&B. The second five-minutes, 0.005 B&B. So I'm just going to divide that by 555 minute increments equals timespan minutes divided by five. So that means if you are out there again for ten minutes, it's gonna be ten divided by five, which is two. You're gonna be charged point O one, O, B, and B. Now we want to set that do property. So renters wallet address dot du equals five-minute increments times. Now here's what we're going to move the decimal, 0.05 B&B per five-minute increments. I'm just going to say start right here with my decimal and say 12345678910111213141516171818 decimal spaces. So that is five. Let's see. Let me put commas just to make it clear. Comma there, comma there, comma there. Comma there, comma there. So we got 3691215 zeros, 515 zeros. Again, if we move this back over, we got 123456789101112131415161718. And then we put r dot And we have 0.005. That's all that is. We're just hard-coding this at 0.05. You might want to pull the latest price and do some kind of math. The thing about solidity is that they don't do fixed point out the box. You have to do some kind of crazy math to get a decimal. So I'm just going to keep the decimals out of it and not try to be like 0.005 divided by the US dollar or something crazy like that. We're just going to set at 0.05 every five-minutes. Some put a semicolon. And we have a problem. It's because I put unit instead of you and which I do all the time. And wrong argument count for function called get total duration. We got to pass in the wallet address because we need to know whose duration. And that is set due amount. Now we can visit that to do we have up here. So when they check the bike back in, we want to set that amount. So we can just simply call set due on the wallet address. And that will set that do variable as soon as they check the bike in. And let's save that. I think we're close to being able to test it. We do need to put some required statements in here, but let's give it a test. Actually before we do, there's one more thing I want to add, and that's just to check something we can use, I think on the front end. And it's just a function called can rent a bike. This is just a way to say, Hey, Can they rent a bike without having to go and look at the properties of the struct. We can just call it right here and get a true or false back. So address, while at address. Public view returns bool, turn renters, wallet address, dot can rent. So it's just telling us true or false. What does this set S? That's all. Let's test this out. This is gonna be a lot of fun. I think while we're doing this, you'll see all these conditions of things we want to protect. They shouldn't be able to do this. They shouldn't be able to do that. And it'll cause us to create require statements. So let's test it out. Let's test it just locally first before we do anything on the ByteDance chain. So you come over here and we're going to choose JavaScript VM. Again, like before, I'm just going to choose the first address and make them the owner because we're deploying it and click, Deploy and open this up. So first thing, let's add a renter. And let's make it not the owner. Let's choose the second person and copy. So I'm going to put the address. Here's all my parameters here. And you can also find them up here with the renter. But I'm gonna put my wallet address. What Travis chest can rent. True? Because I can rant. I don't have a bike out. Active false, and then no balance, nothing is due, no start and no end times. To add renter. And come down here, choose my wallet address. Come down here and see that I have a renter here. Great. Can I rent a bike? True? I can rent a bike. Get total duration 0. And to be honest, we shouldn't be able to check that if the bikes checked out, so we'll put a condition on that in a minute. But let's go ahead and check out the bike. I'm going to check it out. And then when I click renters here, it should say, can rent false because we don't want to be able to rent while we have unchecked out. It should say active, true. And there should be a start time. So I'm going to run this again. There you have it can rent false, active is true and here's my start time. Now we set this up in five-minute increments and I could go and change that, but I'm just going to wait the five-minutes and come back. I'm going to pause this, come back after five-minutes and we'll check the bike back in, see how that works. Alright, it's been about five minutes. So I'm going to check the bike back in. And so I'm going to choose check-in, click check-in. And now if I check, check my renter here it should have a n time. Active should go to false and can rent should stay false because they haven't paid and we should have an amount due. So let's click renters, and there we go. So we have a start time, we have an n time. We are no longer active and we can't rent. Great. We also have a Mountain Dew, and it's gonna be five with all the zeros, which is gonna be something an ether. But again, it's going to translate over to B&B when we get there. So let's check some of these other things. I can rent a bike that's false. Or the balance of the renter, how much balanced I have in there. I haven't put anything in it. So should say 0. Balance of the contract is 0 and my total duration should now be six minutes. Yeah, it's a six. So that calculated properly. We had the bike for six minutes. Now the next thing we'd want to do is to be able to pay our balance because right now, can I check a bike out? No, I can't. Because I have a balanced due and I just realized we didn't set any way to make a payment. So we need to be able to send money to our balance to pay that off. So let's close the contract and put that together. So that's another one I totally forgot about. So let's put another pseudocode comment down here and just say make a payment. And actually before we make that function, I realized that we also didn't set any way to deposit money. So the flow is like this. The renter is going to deposit money into their balance. So one of the properties here is balanced. They're going to deposit money into the balance so that there's money in there already. It's kinda like pre-paying. But the money, when you deposit it, it's gonna go to the entire contract and then the amount you put in is going to go to you. So if ten people put in $10, it's gonna be $100 in the contract, but $10 credited to each person. And then as these people make payments, money is gonna be deducted from their balance so that, that money and the total contract becomes the owners. Hope that makes sense. I think it will once we write this. So let's do this. Deposit real quick. Composite function, deposit, address, wallet, address, payable, public, then renters. And just to show you this, I can actually close this and just leave it in. This will deposit money to the contract because it's payable. I can call this deposit function and send money. And it's going to deposit it to the contract. It's going to do that anyway. But we also want to add it to the renters balance. So we want to do renters wallet address balance plus equals message dot value. Now, message is one of those global variables, like we had up here, which I didn't mention. I probably should have message dot sender, who's sending this message dot sender. We also have a message dot value. What is the value I'm sending? So when I call this deposit function, I'm going to send a value to it and it can be picked up in his global message, variable, message dot value. That's all that is. So we're depositing money to the contract, but it's also going to credit specifically to this person. So we're depositing money to the contract, but we're also going to credit this wallet address or this person. Now to make the payment, let's create a function called make payment. Address, wallet address. This is payable public. And what we're gonna do here is we're gonna do renters, wallet address, dot balance, and we're going to take money out of the balance. So minus equals message dot value. So say you're the only renter, you put in $10 towards your balance. So there's $10 in the contract, but that $10 is in your balance. So what you're doing when you're making a payment, you're just pulling that amount out of your balance. So there's $10 in the contract and it's all allotted to me. And I ride my bike for $10. When it takes that $10 out of my balance, that $10 is no longer mine. I have no balance left. That $10 belongs to the owner. And that's kind of how the ownership thing plays out, how their owner gets paid. So we're not sending money to the contract, we're actually removing money from our balance. And there's also a few other things we want to check, like Let's see me just copy this. And there's also a few other things we want to do. Like we wanna sit, can rent back to true. Because now they can run again. Hey, there balances paid, they're free to rent again. And I'm just gonna I'm just gonna copy this a few more times. The amount due is going to be 0 because they paid the amount due. Start time is gonna be 0. In the end time is gonna be back at 0. So everything is kinda set fresh again. You have things paid off, you're able to rent. You have no time on the clock. Go grab a bite, and I think that's it. I think that's everything we need. Let's go ahead now before we deploy it and put it in some require statements, some checks to be sure we're not allowing things we shouldn't. And the way you should do this, I've already done it, so I'm going to add them and explain them. But the way you normally do this is you take this here and you deploy it. And then you go clicking buttons and testing things and you go, Hey, wait a minute, they have a balance. They shouldn't be able to check out or hey, they shouldn't be able to make a payment because they don't have anything. Do you gotta have checks like this? So as you're testing and clicking buttons, you'll come up with the require statements, but I'm gonna go ahead and put these in and explain them. So let's come up to the checkout function first, there's two things we want to check for. One, we want to make sure they don't have a do balance. If they have a balance due when they shouldn't be able to check out again, that keeps people paying their bills. Otherwise, they just keep checking the bike out and not make any payments because we're not going to enforce it. We're trying to be decentralized here. So what it is is they just won't be able to check out unless they pay their balance. So we need to check that. And we also need to check that they can rent that they can rent property is set to true. So we do that with require statements. And what's neat about require statements is that they will revert the transaction before gases span, which is pretty neat. You don't blow the gas and then have it fail and then you lose your money. To do that you put require and then you set your condition that you're requiring renters dot wallet address dot do and we want to do to be equal to 0. We don't want any amount, do we want them to have pay their bill? If that's not true, we can put a comma and then some kind of message. You have a pending balance semicolon and we're going to put the other one. Let's make a copy and instead of do, we're going to check it. Can rent can rent should equal true? That's what we require. We require that they're able to rent. If not, we're going to put a message. You cannot rent at this time. That's all for checkout. Now for check-in, we want to check that they're active because if you're not active, you don't have a bike, right? So if you just click check in and you don't have a bike checked out, it should throw an error. So I'm going to copy this require statement. I'm going to put this here and do active. So active should be true, meaning they have the bike actively checked out. Otherwise the messages, please check out a bike first. Now let's go down to get total duration and we want to put a check here. We want to check that active is false, meaning that they've checked in their bike. They can't get the duration unless they've checked the bike in. And if that's not true, then we're going to say bike is currently checked out. Then finally, on this make payment function, now there's probably more that you could put here. Like somebody in the YouTube comments said, Hey, you forgot this check. Well, there's lots of checks and things you could put. This one's going to production. We'd want to make sure there's lots of checks in place. But the last thing I wanna do is make payment. I want to make sure that I have an a Mountain Dew That might do is more than 0. If I'm making a payment, I don't have anything to pay. What's the point? I also want to check that my balance is greater than the amount I'm paying from trying to pay ten bucks and only have eight, that's not gonna work. So I need to make that check as well. To require statements here. The first one is going to check that du is greater than 0. That's not true. I'm gonna put, you do not have anything due at this time. The next one we want to check that the balance is greater than message dot value. So remember this is a payable, people are sending money. We want our balance to be greater than the amount of money being sent. In here, we'll put, you do not have enough funds to cover payment. Please make a deposit. You can't pay directly, you have to deposit money and then transfer that money is payments and save that. And I think we're done and we're ready to do some testing. So first we're going to test it on this JavaScript VM. Then we're going to deploy it to the finance smart chain. One last thing we should do for testing this get total duration here. We haven't set in five-minute increments. So remember last time we tested, we had to wait five minutes so we could get a number to populate. Well, let's change that just to something hard-coded, like returns six minutes, so we don't have to wait again. Returns six and we're going to have to take out these because it doesn't like unused variables. So save that. So this time we're just gonna get six minutes. We don't have to wait. We can check out, check back in immediately, and be able to test. So let's deploy that. Someone to choose the first address is my owner. Go and copy the address and deploy it. In the second address is gonna be one of my renters. So add the address. First name is Travis, last name is test, which isn't my last name by the way, I can rant is true. And what are the other? Active is false. 0 balance 0, do 00, start and end times. I'm going to add that renter should be able to come down here, put in the address, and see the renter. Great. Now let's check out someone to check out a bike. Click checkout. And my values down here should change accordingly. Click renters have a start time. Now active and I cannot rent because I have a bike out. Great. Let's do some other checks. So can rent a bike is false, get total duration should give me an error. So if I click that, it reverted and says bike is currently checked out. So that is this require statement here. Bike is currently checked out because active, the requirement is that active is false but activist true, so it throws an error. So that works. One other checks do we have we'll check that one. So check out you have a pending balance. You can run it this time. I will check all those in a minute. So let's check back in. Check back in. And if we get our duration, it should be six minutes because remember we set that manually. So here's six minutes. Now that we checked in, we should be able to come down here to renters and see the changes. So click this. Can rent as false, I can check out another bike. Why? Because I have a due amount, this amount and it's five to all these zeros. But remember, that's to the one-thousandth power. It's really 0.05. Because we only checked out in one five-minute increments. Active is now false, which is good. We're not on the bike anymore, but we can't rent because we got to pay this balance. Now what happens if I tried to check out again, throws an error. It says you have a pending balance. That check is good. My can rent is false, so it also fails there, but it doesn't hit there. It fails right here. So that check is good. And if we go down to make payment, we have this balance should be greater than the value. So if we try to make a payment and put my address here, and we tried to make a payment of let me type in way converter. So way again is ether to the one-thousandth power. So I'm going to just do 0.01. Let's just do 0.1 and get this large way number. So I'm going to take this number and I'm going to try to make a payment, put that here and make sure I choose way. And I'm going to try to make a payment, but my balance is 0. And we have a check-in here that says the balance must be greater than the value I'm sending, so that should fail. So I click Make Payment. It says you do not have enough funds to cover payment, please make a deposit. Because I have no balance. I have no way of paying this. So what I need to do is I need to deposit money into my balance. So I'm going to put my address here. I wanted to pause it that much way, so I have everything covered. I'm going to paste that here and I'm going to deposit way. Now remember, when we do a deposit, we have a value that we're sending and re-mix. You put the value here. In ethers JS, you send it as a value object. But anyway, we're going to send this much. We're going to deposit it to my address. So hit deposit. And then when I click renters, I should see I have a big fat deposit here. Great. Have a big balance enough to cover the amount due. So the only logical thing to do next is to make a payment. Somehow addresses in the make payment and I'm going to send this much money. This amount is due, 0.05 is due. So I'm going to paste that up here. And I'm going to send this amount to my balance. I'm going to click Make Payment. That went through. Now if I update my renters, I should have an amount of 0 due and that much taken out of my balance. So it should be instead of 100, it should be like 95 or something like that. So let's click renters. I have nothing else to do. And it took it out of my balance. And my start times back to 0, my n times back at 0. I'm not active, but I'm able, again to rent. It looks like everything went through great. In that our contract works wonderfully. Air contract is fully functional and it's deployed here locally. Now let's deploy it on the finance chain to see that the finance conversions work. So let's close this for a minute. Now, if you go to your MetaMask, you need to add the binary smart chain tests net. If 3. Finalizing Our Smart Contract: Okay, so before we move to the next section, we need to add a couple of other functions here on the smart contract. And I know this because I went ahead and built the front end and I realized we needed a couple other things to help us out. So let's add three functions here. The first one is going to be called Get do in all it does is get the dual mount for a renter address, wallet address, a public function, it's a view and it returns you and and we're just going to return the renters wallet address, dot do. So the amount that renter has to do. Next, we're going to get the actual renter. So we're gonna get the renter and it's going to return four pieces of information for us about that renters. So it's basically like returning the rent or object, but without the Uinta part, parts of it. So it goes like this. Function, get renter. We're going to pass in again the wallet address. It's public to view, and it returns for things. So string memory, firstName, string memory, lastName. Bull can rent. In bull active. That's all we want to know in this instance. So here we're going to say firstName equals renters wallet address dot first name. Whoops. Then I'm going to copy this three more times on a Mac, that's Shift Option. And then down to copy the line you're on. And I'm going to use Command D to select both instances of the firstName and lastName. And then I'm going to change this one too, can rent in this one too active. And all we're doing is just returning these properties of that renter. And then finally, we're going to create a function called renter exists. And it's going to return a bool, whether that rent or exists or not. So we need to know if that renter needs to add themselves to the smart contract or whether they're already added. So we can say function renter exists address while at address, public view, and it returns a bool. Here we need to check if that wallet address exists or not. So we can say if renters while at address dot while at addressed property, if that wallet address is not equal to address 0. Now you might be like what is address 0? What does that supposed to be? Well, here's a good explanation. So with mappings in Solidity, there's no way to check directly if something exists. Everything is set to its default value until it's changed. That means every integer starts with 0, every string starts with a quote. Every array starts as this and solidity has no concept of null like other languages. So what they're saying is, if you remember in re-mix, let's, let's pull this up. Just comment this out since we're not done. So let's come over here and deploy our contract. I'm going to click Deploy and open this up. So what if I go to renters and just put in an address and click the button. Well, you'll see that everything is in its default state. There's nothing no, like the postal saying there's nothing null and solidity. It's going to have these, it's gonna be the value of what it would it is basically, so the balance is 0, do is 0. All of these are gonna be 0. The bulls are gonna be false. I mean, it's just the default value, it's not a null. And you'll see here the wallet address is the zeros, zeros, zeros. There's, these are all the way across. And that is equivalent to address 0. I think we could also do address 000 or something like that. But address 0 says, hey, if that person is in the renters in doesn't have this, then they must exist. That's all that is. I don't want to get too deep on this. Hopefully that makes sense, but it's a good way to check whether a key is in a mapping. So let me close that out and get back to this. If renters wallet address dot wallet address is not equal to a blank address, meaning they do exist. Then we're going to return true. Else return false. Then there's a couple of tweaks I want to make. So if we go up to get total duration, I want to remove this require statement because it's just unnecessary. So we remove that require statement. Now I want to put one condition. So if the renters start time is 0 or if their start time is 0, meaning they've checked out the bike but haven't checked it back in. Or if for some reason they just have an enzyme which will probably never happen, I want to return 0 because they're, they're checked out, time is not complete. So if they want to get their total duration before they check the bike and they can't do that. You gotta check the bike and first to do that calculation. So I'm just going to come up here and do if renters wallet address dot start equals 0. Or if I'm going to copy and paste this just because it's quicker for me. If the end time is equal to 0, then I simply want to return 0. You have 0 timespan in minutes. Else. You're gonna do all this stuff. We already had a copy that and paste it in. That's it. Your contract is ready to go. We have our contract and re-mix, and from here we can compile it, we can deploy it, we can get the ABI and all this important stuff. But nobody really wants to do that from re-mix because this is browser-based. I think it saves it in the browser, but it could be lost. And you want all of your code normally together and you want to version control it in GitHub and things like that. So we're going to move this out into a new project. And I'm going to show you how we can use something called a hardhat to bootstrap this whole ecosystem to manage this smart contract. You're going to love this. So go ahead and open up your terminal and we're going to create a folder for our application. So I'm gonna go into my desktop and I'm going to make a directory MKDIR. I'm going to call it bike rental application. Hit Enter. And then I'm going to cd into it. And code dot to open it up in VS code. Or you can drag the folder in, or you can right-click or do whatever you want, just open it up in VS Code. Now, what I'm gonna do is I'm gonna go to hard hat.org. So go to hardhead.org. And what this is again, it's in the theorem development environment. It allows you to run solidity locally, to debug, to test. It gives you flexibility and all this other good stuff. But what you'll see in a minute, all the great things that it does. So go ahead at the top here and click Get Started. And we're going to follow these steps because they're written really well. So installation, we need to do an NPM install hardhat. So make sure you have no JS installed. If you don't, just go to NodeJS and Google and click on NodeJS and just download the LTS version. Once that's done, you'll have NPM, you'll have in Bx, you'll have node, everything you need. So we're going to use this command. And we're going to start actually by doing creating a directory called contract. I'm going to cd into that contract directory. Then I'm gonna do npm in it, y dash y. So npm init dash y. What this does is this creates a package JSON, so that we can install npm packages in the dash y just makes the default installation. So click Enter and it should set everything up for you and you should have in your contract folder a package.json file. So now we can run our command, which is npm install save-dev hardhat. So click Enter to install hardhead. After that's done, we're going to do this Quickstart. This quickstart is gonna do is bootstrap a sample project which we're going to use. To do that. You just run in px hard hat. So copy that. Alright, so I'm gonna paste that in NP x hardhat, hit Enter. And it's going to give us some options. So we're going to choose create a basic sample projects. So the first one here, hardhat project root is going to be the contract folder, so we're good there. Yes, I want to get ignore. And it says, do you want to install this sample projects dependencies with NPM which you will need to install. So click, make sure there's a y and hit Enter. It's going to install a couple of packages that help us with testing and talking to the contract and all of those things while it's installing. Let's see what's next. So it's gonna give us some examples here of how to run tasks. So you can run in px hardhat to run tasks. So you can check, you can print the list of accounts. You can compile your contract. You can run a node, you can do tests, a lot of good stuff. There is a hardhat config js that allows you to configure your deployments. We'll get into that in a minute. You can run in px hardhat accounts to show all of the accounts that you can work with. It, it pretty much creates 20 accounts for you to use. You can compile your contracts by running npm hardhead compile. You can test by running NPS Hall at test. And lots of great stuff. We're gonna go through this. All right, that's done. So if you look in our folder now we have a Contracts folder, which they give us a demo called Greeter dot soul. We of course have our node modules scripts. This is going to be our deployment script. We'll get into that in a minute. You can run tests. We're not gonna do much testing because we just don't want to make this super long course, so we'll probably skip the testing. And here's our config. And of course they're packaged JSON. Let's first copy or contract in here. So let's right-click on the contract folder. Create a file called Bike Rental dot soul. Actually I think we call this bike chain dot soul. And I'm going to take my contract from solidity, highlight it all and just paste it into here and save it. You probably want to install the, though I don't know if you need to, but you may want to install the solidity extension. I think I have that installed. Yeah, I have the solidity extension. So it's yelling at me because it doesn't like the version. Our current compilers 0 dot phi dot 0. So I can open my command pilot and choose Change workspace compiler version. I'm going to change it to 080, which I can select here, and it usually takes like five seconds or soda to clear. Yeah, there we go. Cleared up. So my contract is in here. And actually we can take a look at how this works. So if we go to greet or not soul, you see we have a contract called Greeter. We have our constructor and we have two functions. We have a greet function which returns a greeting, and then we have a set greet function that allows you to change the greeting. So here's the contract. And then if you go to scripts and sample script, It's setup to deploy that contracts. So you see here all the great comments we get the contract to deploy. So get contract factory called greeter, which is the contract. And then it deploys that objects. So this is the greeter object representing the contract. And then it deploys that object with hello hard hat as the parameter. So if you go back to greeter, you'll see in the constructor that you pass in a greeting, whatever you want your default greeting to be. The sample script will deploy this and then await greeter deployed. Then it prints out greeter deployed to whatever contract address it deploys it to. So there's the grader contract, here's how the greeter is deployed. Sample tests. So the, the one test they give is that the greeter should return the new greeting once it's changed. In this does the same thing, creates a greeter object, contract object. It mocked deploys it with the parameter HelloWorld and then it expects, it doesn't expect statement, making sure that that contract has HelloWorld as it's greeting in, then it sets the greeting to something different, and then it expects that is something different. So that's the test and it should pass the original greeting and the change greeting. Then in hardhat config, you don't really need to set anything up for local deployment and we'll see that in a minute. So that's kinda how it works. And now that we know how it works, Let's delete this greeter, not soul in reproduce all of that for our contract. So delete greeter dots soul. Then let's go to sample script and we're going to change this to bike chain and get contract factory bike chain and greeter. We're going to make lowercase bike chain. And then we want to deploy this object which is now bike chain not greeter. Change that to bike chain, deploy and we don't send anything with their deployment. So let's take that out. Change this to lowercase bike chain. In console, log bike chain deployed to bike chain dot address. Hopefully that made sense. We're just changing these variables to deploy our contract and not the greeter. So that should be good. Go to sample tests. We're just actually going to comment this out. And that's it. So now we can do in px hardhat, compile, to compile our contract. And when we do this, we're gonna get a new folder with their air compiled artifacts. So you'll see now we have an artifacts folder. If you open that up, there's some build info. We don't need to be concerned with that. And if you open up the Contracts folder, there's another folder called bike chain dots soul with two files. In the file we're interested in is bike chain dot json. And here we have some key information we're going to have to use to link up our front end. One of those is the ABI. Now the ABI describes all of the functions. That are available in our contract for us to call. Our contract is out there on the blockchain and the ABI tells our application what functions it can call. So you'll see here the constructor, and you'll see balance of function, add, add renter, balance of rent or all of the functions we created. That's what the ABI is. We'll have to put this in our project in a minute. Then down below that we have this lovely looking code, and this is the bytecode. This is the executable that lives on the Ethereum Virtual Machine. So when we deploy, This is gonna be some key information there. But we don't have to keep track of this. In every time you make a change to your contract, you're going to have to run this NPM hardhat compile. And all it's gonna do is it's going to recompile in, refresh the artifacts. We've talked about compiling our contracts and testing the contracts. Now let's look at deploying. So what we're gonna do in this course is we're going to deploy it to the finance smart chain. But let's say you didn't want to go out to a test net, but you just want it to do it all locally. Well, here's how you would do that. So we can use this sample script to deploy. So right here you'll see in px hardhat run in the R script. It'll say deploying a greeter with greeting, greeting deployed to this con, contract address. But you see here a hard hat will always spin up an in-memory instance by default. So this is gonna be an in-memory instance. But it's also possible to run hardhead in a standalone fashion so that external clients like MetaMask can connect to it. This can be MetaMask, your dapp front end, or a script. So you can do this in px hardhat node. And what this does is this creates a standalone node that runs on your computer. So if I type in px hardhat node, hit Enter, it's going to do a couple of cool things. So one, it's gonna give me those 20 addresses, but it's going to give me the private keys to those addresses to, which is really cool and it's gonna give me 10 thousand. In. What I can do now is I can open up a MetaMask. And let's take this first account. So it grabbed the private key of this first account and go to MetaMask. And actually before you do that, you'll need to add the local host 8545 endpoint to your MetaMask. So if you go to ad network and you add a new network, I actually have it already. But I have here localhost 8545. So network name is gonna be localhost 8545. New RPC URL is gonna be HTTP colon slash slash local host colon 854 or five. Chain ID is 1337. And by the way, if you don't have the node running, this is going to give you an error. But anyway, it's 1337. Currency symbol is going to be IV. And then you can leave this one blank. And then hit Save. And this is going to actually save this local host network for you to play around with. I can now copy this private key and then go to Import Account and set the private key, hit Import. And then now I have 10 thousand to play with one account two. And I can actually account details. I can change this to local hardhat test or something like that. Whatever. Then you want to leave this node running. Gotta leave this running. If you stopped, this is not going to work anymore. So you want to go to another terminal. And we'll run this next command, NPS hardhat run. So we're going to deploy this script, but we're going to use the network local host. So you can tell IT network rink OB or whatever testing it you want to use. You just got to configure it in your config. But we're going to use the local host network. And I don't know. I think that just comes default. I don't see it here. But anyway, let's grab this and deploy it. In another term that we'll remember, leave this running in another terminal, run this. Oh, that's not good. Make sure you're in your contracts folder. Make sure you're in your contract folder because when you change terminals, it kicks you back into the root. So run that again. And there it is. Bike chain deployed to this contract address. This smart contract got deployed to your node that's running here. So as you build your front-end application, you can just use this account. I mean, you'll have to put in your contract to dress and stuff like that, but you'll use this account and then you can just test everything locally. You got lots of Eve. It's a lot of fun. But we actually want to go a step further and use the finance smart chain tests net. So that will be live on the test net. And then if for some reason you wanted to take it live and production, or you want to know how to get to production. It's very simple from there. So let's do that now. So I'm going to close this browser. I don't need that anymore. I don't need this node running. And I'm just going to close this terminal out and clear this out. Okay, so that was the scenario of developing in your local host environment. So it spins up a standalone node for you to work with. You can deploy it onto that node and then you can talk to it with external clients like MetaMask. Great option. But again, we want to go out to a test net. We want to make this thing legit and to have a real feel about it, not a local host. Things aren't really happening. Situation. Now there's a number of ways you could go about connecting to the ByteDance smart chain. But many developers, they use a third-party service for this because it allows you quick access and it allows you to scale if you ever wanted to take your app to production. So there are services like interferer, that's a popular one. Alchemy is really popular, but both of those focus more on a theorem, not finance. We're going to use a service today called Morales. Morales is going to allow us to talk directly to the Biodefense smart chain tests net. It has many, many other things that you can dig into as well, but it gives you quick access. It allows you to scale. It just has a platform built for this sort of thing. So if you go to Morales.io and you click on sign up for free, It's completely free. You just put in your e-mail address, create a password. I think it's going to send you an e-mail to confirm and you'll be all set. So I'm gonna go to login and just put in my password. Once you get here, you want to go to speedy nodes and click on the BSC network into points. In here you have a set of endpoints. You have the main net, the main net archive, the test set, and the test net archive. What we want is the test net. So copy that. And let's go back to our project and let's add to this. So put a comma here. And so this is where we can define our different networks. So we can do testing at main net, local host, like what we just did. We can put some info there, whatever networks we want to use. So we're going to call this test net. And there are two properties we need, URL and accounts. For the URL, we're going to paste in exactly what we copied from Morales. Then for accounts, we're going to grab our account from MetaMask. So if you open MetaMask and go to the BSC test net. Now if you don't have this, click on again, networks and ad network. And you'll want to add a new network for the BSC test net. And that info is right here. So the network name is BSC test net. The new RPC URL is https colon slash slash data. Actually just, just go and type in by Nance Smart chain to MetaMask or something like that. And it'll say connecting MetaMask to finance smart chain. Right here, you'll get the values here, test net. So here's the RPC URL. Here's the chain ID, which is 97, symbol is B&B in the Block Explorer URL is this. So make sure you copy these N. So again, go to Settings networks at a network, copy these values in and hit Save. And then you should have an option called BSC test net. And what do you wanna do is probably create a new account. You don't want to use one of your normal accounts. I have one called BSC test. To create a new account, you just click on this circle and create account and then give it a name and hit Create and it creates one for you. But what you wanna do now is in make sure this is an account you're not going to use for anything else, of course. But what you wanna do now is go to account details. And then you want to export private key. So click Export private key. And I got, You got to put in your MetaMask password. So let me grab that. So type in your MetaMask password and hit Confirm, and it'll show you your private key. So copy this. Copy that. Then go back to VS code and that's gonna be your accounts. But see that it's plural. The fact that it's plural means you've got to put it in an array. So I'm going to put your quotes and then paste it in like that. Now, of course we don't want this in our config file. We want to put it in an ENV file. So let's go to contract and create a new file. It's going to be called dot ENV. And we're going to have a value called URL. And we'll grab this URL. And actually it's equals and paste that in. And then you want to, then another call to counts equals. And then here's where you want to paste your private key. So go ahead and paste your private key here, and save it. Now let's go back to the config file and we want to use a package called dot ENV. So npm install dot ENV. And I always forget how this works. Dot ENV, ES6. Yeah, so we're going to import dot ENV. And then once we do that, we can use it as NodeJS uses these environment variables which is processed dot ENV environment name. So up top we will do import dot ENV config, and then we should be able to say process dot ENV dot URL. Then here in the array, we're going to say process dot ENV, dot accounts and save it. And now we should be able to deploy. We got everything we need. Let's try it out. In bx dot hard hat. Actually I got Auto Suggest on. So NPS hardhat run scripts slash sample script.js, dash, dash network. Now we don't want local host, we want what we have up here, which is test net. So we should be able to erase that in the network we want to use is test net. If we wanted to, if we wanted to define something else, we just put all the main net and same kind of thing. Then we can deploy the main net if we wanted, but we're going to deploy to test net and hit Enter. And it says cannot use import statement outside of a module. That's fine. Let's go back and grab the other one, which is the require statement. To put require there and try it again. There we go. Bike chain deployed to this contract address. And if we go to BSC scan tests, net in, confirm this, let's punch in our address or contract address. There it is, age as Thirty-five seconds or contract. Here's our bytecode. Go to events. I don't think we have any events. Transactions, no transactions. Awesome. We've deployed our contract out on the finance smart chain test net. So we're done with the contract part of it. If we have to make any changes again, we'll just recompile and redeploy it. It'll give us a new contract address and we'll just update that in the front end. So congratulations, you're done with your contract. Now it's time to start on the front end. 4. Project Setup and Building the FrontEnd: Alright, now we're gonna focus on the front end. And what we would normally do with the React app is we would use Create React app to bootstrap a project, but we're going to use something different called vite. Now, vite is exactly like Create React app, but it's faster and has some other customizations, but we're not going to worry about that. So it should be like one for one the same. We should be able to use this and do all the things we would do in Create React app. So if you go to vite, it's a byte, js dot dev. And click on Get Started. And then go down to, let's do yarn create vite. Feel free to do npm if you want. I just prefer yarn. And in your root folder, just paste that and hit Enter yarn, create bite. And it's going to bootstrap a React project. So project name, let's call it client. Because this is gonna be the front end of our application. And then select a framework. Of course we're going to choose react. Then I don't want to use TypeScript. So just choose react. And there we go. Done. So if you close your contract, you'll see you now have a client folder. And if you look at it, it's almost exactly the same as Create React app. So we're going to take the app CSS and delete it. And the favicon and the logo, delete those. Then in the app JSX, we're just going to delete all of this input div. Hello just to see that it works. And to run this, if we look at the package JSON, it is, the script is deaf. So we can do a yarn run dev or npm run dev. Either one. Of course I gotta be in the right folder. So make sure you see the end of your client folder. Run that again. And of course we gotta do Yarn install or NPM install to install R packages. All right, Let's try that again. You're not Yarn install Yarn run dev, and go to localhost. 3 thousand failed to input. Okay, So we deleted a couple of files. We need to delete the imports also go to app JSX, delete this important logo statement. We don't have an app CSS, you can delete that, save it. And I think that's it. Main JS. Yeah, that's good. If we open our app up. There we go. Yeah, It says hello, so our apps running fine. So the first thing I'm gonna do, we're actually going to use a thought about what CSS framework we should use with this. We're actually going to use chakra UI because I think we can really get this spun up quick with that. Now I haven't used it a lot. So if you haven't used it either, we're in the same boat, but it's really easy. So let's visit the website first. Chakra UI. And I'm in Brave, I don't want to be in Brave. Let me close this. Chakra UI.com. Chakra-ui.com, and then click on Get started. I'd consider using Tailwind, but I did a two tailwind tutorial one time in the past and it was just so, so many classes to keep up with. I think it'll be much easier with this. So we go to get started and we get to this first Steps page. We'll scroll down to the Create React app page. Click on that. And we see here that if we're using Create React app, we can actually run the command that bootstraps this CSS framework with it. We are not using Create React app even though it's very similar. So we need to do it manually. So come down here to the manual installation. Click either yarn or in VM, and let's install it. So stop your server and paste that command and let's install chakra UI. There's some other packages, emotion and frame or motion. Then we'll want to do this provider setup. So we need to add this provider wrapping our app component. So I'm going to use this import statement first. I'm going to copy it and go to main JS. Let's just paste that in here above your index CSS. Then we want to wrap the app. And I'm just going to take this whole thing and just replace it. We're also going to be using icons. So if you go to Components and somewhere there are icons. Let's just search for it. Media and icons look for this section and click on icon, will want to install this icons package to copy that and install it. So paste that here and install your icons package. And while that's installing what we wanna do for sake of time, since this isn't really a CSS course, is chakra UI has a lot of components that you can basically copy and paste. You can copy and then tweak it to how you want it. We don't want to do things from scratch here. We don't want to reinvent the wheel. So if you go to chakra UI Navbar, that'll take you to a page that has lots of components that are pre-made. So there's the page sections, navigation forms, components, a lot of stuff that's already put together. Now this page sometimes for some reason doesn't load, like this content doesn't load. So I do want this first nav bar because it's the simplest. So just click on this arrow to open it in a new page to get a preview of what it looks like. So yeah, this is what it looks like. Here's your logo, Here's some nav items. They have sub menus and then a sign in and sign up. We're going to run with that. So let's go back to this page and click on code. We're going to use the width sub navigation and CTA. Click on Code and hit Copy. And then we're going to create a new component. So let's go to source, create a new folder called components, and create a new file called nav bar dot js X. And I'm going to paste that in this whole thing. And I'm going to find the main function with this, which is with sub navigation. I'm going to change it just to navbar. It's already exported as default, so we don't need to add that at the bottom. And we do have some errors. What is going on? Oh, this looks like it's TypeScript, so we just need to adjust for that. So let's go down to the bottom and just remove all of these types. So remove that from the NAB items array. And we don't need to interface because this isn't TypeScript. Find the next error. Remove that type under mobile nav item. Keep going up under desktop subnet. Remove that. And I think we're in the clear. So we should be able to save that and run air server yarn, run dev. And we should see this navbar should be that easy. Of course we don't because we didn't add it to our app component. So that's nav bar. So let's go back to app. So APA, JSX, and then at the top, Let's import it, import navbar from dot slash components slash navbar. And then here we can just change this hello and replace it with navbar and save it. And we should have a navbar. There we go. It looks great. Now we don't need all of this stuff, all we're going to keep as the logo section. We're going to put whatever the name of our app is. And we need we don't need sign in and sign up, we just need connect wallet. So let's make some adjustments so we can get rid of. Let's see, find work. So here are the navbar items. So let's get rid of hire designers. Let's get rid of Learn Design and these sub, sub navigations. Let's get rid of the fine work. Let's get rid of the inspiration label. And we end up with an empty array. Save it and see if that's okay. Yep, got rid of our nav items. Alright, mobile nav item. Let's get rid of this totally because we don't have any nav items. It's going to look fine either way. So I'm going to erase that. I'm going to erase mobile nav. Get rid of that. And I'm sure that's referenced somewhere. So let's find it. Mobile nav There it is. So I'm gonna get rid of that whole section there. And I think that covers it. Let's save it and make sure it's fine. Still okay. Let's find the sign here it is. Sign in and sign up. Just get rid of the sign M. And just change the sign-up to connect wallet. We don't really want this pink. We want it till 500. And the hover, we're going to make also teal, but a little lighter, so yeah, let's do it till 300. And instead of logo, Let's put a bike chain. I think that's what we call the app bike chain. And let's make the right before this closing tag. Let's add a font weight equals 900. Let's make it big. And font size. Is going to be X large. So save that and see what it looks like. Bike chain. Then we want to make this background a little darker. So up here where it's used color mode value, it's set to white. Let's put gray 200. Save that and take a look. And that looks great. And if we shrink it down to mobile up, we have this little hamburger icon, which I don't really want. See if we can find out where that is. Icon button, probably that. Let's get rid of that completely. And save. It. Looks like our buttons disappearing, so there's still something mobile going on. Um, it's probably something to do with the desktops sub NAB. Let's get rid of the sub nav. And then let's actually get rid of desktop nav because we don't need any of these nav items. So let's get rid of that too. And that would fall right here desktop. Now, let's get rid of that and save it and see what we have. Alright, and button is still disappearing. And it looks like see this button right here with this display base MD. This is responsive like media queries. So at base, which I think is the smallest, it says none. Let's take that out and just leave the medium. Have it always in-line flex and that should fix it. Yeah, there we go. And this moves over, but I'm not really concerned with it. We can fix it later if need be. That looks good. So bike chain and we have our connect wallet. I see how easy that was to setup, just paste in the example and tweak it as you want. Next, we're going to put a big hero right here that points us to the dashboard page. So if we go back to our chakra templates, there is somewhere hero page sections hero in right here. This is what we want. I'm going to choose this first one here. There's some other options if you want to go with those, I'm going to choose this first one, and sorry, go to code, copy. And we're going to create a component for this called hero dot JSX. I'm going to paste it in just like before, and we're going to change the main function name, the hero. We're going to create one more component called home. So home dot js X. And this is gonna be our homepage. We're only going to have two pages on this app, so we're going to do it like this. And for home, let's say const home equals return one home. Let's just put home to return something. Actually. Let's have it. Of course, return our hero. Hero. Make sure you do your import statement at the top. And down here at the bottom, I'm going to export default home. And let's go back to our hero and tweak this to make it work. And actually we'll just put home here for now. I don't want it here, but let's put it here so we can see what it looks like as we build it. And again, make sure you imported at the top. And it doesn't like that we don't have a parent element wrapping these. So I'm going to wrap it with these blank elements. Great, and we have some errors because we need to adjust some things and hero. So the first thing is it says import hid from next head, which looks like next to JS. So these templates use different technologies. We're not using next to js. I'm going to remove that. And I'm actually just going to remove the head part. We don't need it. And everything else looks good. Let's save it and kinda see what it looks like. It's, it's like already ready to go here, but we do need to change this text. So let's find our text up here and it says make money from, and we're going to say, rent your next bike. And then this text here, we're going to say with crypto. Then for this text, Let's type connect your wallet, choose your bike, and you're off to the races. When you return it. You can easily pay your fare with B&B. And let's turn on word wrap. And we all like those B&B gas fees because we really do save that and take a look. Your next blank with crypto, and here's our statement. And let's actually make this match with our button up there. Let's make all of this green match and there's a Get Started and starting at 15, Let's address that also. So the first thing I'm gonna do, rent your next blank. Let's put this as teal. We want to be using teal, not green. Then down here, get started, let's say choose my bike. And again, set that to teal. And these up here, the background until the color scheme Let's make TOO also see what that looks like. Then this learn more. We don't really need it. So just get rid of that whole button. Then there's starting at $15 a month. Let's put rent at no cost upfront. And we should be done with that. Choose my bike rented knows cost upfront, so we should be able to click that. And that should take us to the dashboard. And this ran at no cost. That's a little bit close. Let's go back and see if we can move that. So let's put the top. We want to put it like 25 instead of 15. I think that's good. Yeah, that's fine. Ran at no cost upfront. You can take the bike out, you can write it and you just have to pay when they get back. So now we want to be able to click this button and go to the dashboard page. So for that we're going to need React router. So I'm going to Google that real quick. React router. Read the docs installation and we just need the yarn or NPM Yarn add React router dom at six. So let's add that. Stopped my server, run that, start my server backup. And we're gonna go to the app JSX and add all of this here. So we need to do an import. Actually, I can probably get it from the page. Import browser router. Let's go ahead and grab that, saves some typing in. Let's do that as a router. I think that's convention. Let's import route, route and routes from React router, dom. In this return statement, we're going to put a router component, capital R. We're going to wrap it all in that router component. I'm gonna keep my navbar there. I'm going to remove home. And inside of this router, I want to set my routes. So routes. And then inside of that, we're going to put two routes, one for a homepage, one for our dashboard page. So the first one is route. Then do exact path equals slash, which is their homepage. Thinner element is the home component and its self-closing. And then just copy that. And the second path is going to be dashboard. Element is going to be dashboard which we haven't created yet. We will in a minute, It's probably going to error out, but it's okay. Let me just format this. Yup. I think that's it. That's good and we don't need this. This is leftover from the initial Bootstrap. So we have a router inside of it, we have routes and we have two routes defined. Now we can go back to our hero into where a button is right here. And since this is a button, you can't really do a link. So let's just do an onclick. We're going to have some parentheses and we're gonna be calling handle click. And as an argument, we're going to pass in dashboard. Then let's define that. So let's come up here to our hero function. And actually before that, we need to import navigate, which is a feature of React router dom, which allows us to navigate to different paths. So we do import, use navigate from React router, dom. Now we need to define this hook. So let navigate equals use navigate. And now let's create our function Const, handle click equals. We're going to pass any path as a parameter. And we're going to call navigate. This is a React router six convention, by the way, use navigated the hook and we're just defining it as navigate and we're just going to use it here. So navigate path in path being whatever I pass in. And if you look down here, I pass in dashboards. So this should navigate us, are direct us to the dashboard route. So save that and we don't have a dashboard routes. So let's go to new file and create a new component. Dashboard dot JSX. And I'm just going to copy home and paste it here and change home to Dashboard. And I don't need this hero import. We got to fix the spelling, and I don't need this component here either. I'm just going to put an H one that says dashboard. So let's check our home component. We have our hero. So that's going to display your hero. In this home component is going to be called whenever we go to the homepage based on our routes, remember the routes we created. So we should be able to now go to our app and go to the homepage. So localhost 3 thousand refresh and it's not working. What do we forget to do? Dashboard is not defined. Of course it's not defined. We didn't import it at the top. See we're using the component but we didn't import it. So we just need to add an import statement under that import dashboard from components dashboard. Save it and our homepage should be that. There we go. So we have our navbar, we have a connect Wallet button, which we'll deal with later. We have a nice hero and if we click choose my bike, it should take us to the dashboard page. Awesome, our homepage is finished. So just to recap, we have our main JSX, which is wrapped with this chakra UI, so we can use it anywhere by this chakra provider. Their app JSX, we have route's going on. So our homepage, homepage route is going to display the home component. Our dashboard route is going to display the dashboard component. And then we have a navbar, which is our navbar that's called in the app up here. Because we want that also to be in a router. We have our home component, which is displaying our hero. Because that's what's on the homepage. We have our hero, which we just looked at. And then we have a dashboard which we're going to jump to next. On the dashboard, we're gonna be able to display all of the stats. We're gonna be able to choose their bike and interact with their wallet. This is where all the magic is going to happen. So let's go ahead and build that. 5. Building the Dashboard: Alright, so the next thing we wanna do is build out our dashboard page. Now here's what it's supposed to look like. So we're going to have this welcome statement and we'll have some statistics here. That's gonna be our dashboard, will have a form that allows you to pay What's du will have a form to credit your account, will have a selection of bikes here. So we have three different types of bikes. Some description about each bike and the ability to check out in check and a bike, that's what we're gonna be building. So first things first, let's create the statistics panel. So I'm gonna go back to this chakra templates and I have this Page section called statistics. And we're just going to pull it directly from there. So we're using the one called stats with icon. It's going to look like this. And so click code and just copy that. Then I'm going to create a new component for this. I'm going to call it current totals dot JSX and just paste in that code. And I think this is also TypeScript, so we'll have to remove types. So we'll remove that, will remove the interface. And I think that's all we have to do. So now let's import that into our dashboard component, which is going to be the parent component for these child components. So import current total. And my intelligence is not coming up is telling me we didn't export it. So let's double-check that. Function stats card. Actually we didn't even name it. So export default function, we're going to call this current totals. And let's try that again. Go back to dashboard. Import current totals from current totals. It's in the same folder. And then instead of this H1, let's display the current totals and see what that looks like. And we have an error filter resolved react icons, BS from current totals, JSX does the file exist? And it looks like they're using the React icons NPM package. Let's make sure that's a package. React icons. And yeah, so we can click on this and install it. So right here, npm install, React, dash icons. I'm going to use yarn as I've been doing. Yarn install, React icons. Oops, yarn add, react icons. And let us install, and we should be good after that. Now I'm going to run my server again and refresh. And there we go. We have our three statistics, but we want four and we want to tweak them a little bit. So we want the first one to have a wallet icon. Second one, a money icon. Let's work on that. So let's scroll down to the stats card, components of chocolate or UI. And you'll see here it says like icon BS person, F phi server, go location. What does all this? Well, we can go back to react icons and look this up. So I want a wallet. Which one did we use here? It looks like that. It looks like we use this MD outline account. Now you can tell which library these come from by the first two letters or three letters. So if you see like IO while it's sharp, it's probably this ion icons. If you see MD, It's probably Material Design in our eye is like re-mix icon. So when you actually click on this, it copies that name to your clipboard. You want to go up here and see where it says slash BS slash FI. These are the different libraries here. So we won't MD because this is Md outline account in MD is Material Design. I'm just going to copy this and do import my copied icon name from React icon slash MD. And we should be good there. So I'm gonna go down and change that first one. I'm going to change the icon to the MD outline account balance wallet. And we call this B and B credit, B&B credit. And let's say 0.05. Awesome, looks good. Next we have this money symbol. So I'm gonna go to my react icons and type in money. Maybe. Yeah, here it is, RI, money, dollar circle and it's RIs, so it's remixed icon. So click that and scroll back to the top. And I can probably start replacing these because I'm not going to be using them. So I'm going to paste that here and it's RI, and I'll come down here and paste it in the next one. So paste that. And then I'm gonna change it to B and B do. So B&B do. And I'm just going to put 0.001 just for filler. Then our next icon is this clock. And it's gonna be ride minutes. So I'm gonna go back to my react icon and type in clock. We're gonna go with this one, ai outline clock circle. It's AI. So we need to make sure to put that. But that is my third one. And change this to ride minutes. I'm going to leave that seven. That's good with me. Then we need to add one more. So if you look up here, the simple grid is set up for a three-column base and then one on small screens. But we need to change this to four. So we'll have four columns because we would want for icons. And then I'm just going to copy this and save it to make sure that's right. It's not AI outline clock circle is not defined of course. So let's go up here and paste that. And this is a dy. Then we can get rid of this one and save it and it should work. Now, there we go. So we have our B&B credit or B&B do a ride minutes. And then the last one says bike status and is actually a color. So what we can do is we can first of all make the same bike status. And then we don't need these two, so I'm going to comment those out. We need to add a background color variable so we can come up and take a look at the actual stat parent. And then we'll see here that there are actually prompts being passed in. So title stat and icon correlate to each stats card has a title stat and icon. And then up here we're actually passing in that information. So all we really need to do is add another prop here called BG color for background color. So we're going to pass that in. And these are destructured, so we don't need to go props dot BG color. We can actually just use the variable. We can add another attribute here that says background-color equals BG color. So whatever we pass in as a prop, it's going to change it to that background color. Awesome. Now let's go down. And this last one, we're going to say bg color equals. And let's go ahead and just do red for now. Save it and see if that worked. Yeah, right here we have it now. The background colors red. So none none of the others get a background color because that's not being passed in. It's only being passed in. And this last one. What we can do is we can make this conditional, like if the renter has a bike checked out and we want this to be green. So we'll revisit this when we start putting all the logic together. So I think we're done there with their little dashboard. Oh, actually we got to change this text. So let's change it to welcome your name. Here are your stats and will make your name dynamic later. If you come up here, right here. Welcome. Travis. Here are your stats. Awesome. So again, we're just building out the UI. We don't have anything dynamic going on. We're just making it look nice. So next on our list, we have these two forms, pay your due and credit your account. So let's go back to this chakra templates and see if we can find something. Here's forms. And I don't really want to use these. I want something simple. And when I do forums and react, I like to use React hook form, which is a library that I think is really easy, I think is easier than some of the others out there. If you do React hook form, and chakra UI, you should get a nice example that we can work with. So this is actually from the chakra website. So again, I went to Google, I typed in React hook form and chakra UI. And you're gonna get this URL, chakra UI. Plus React hook for them. So click on that. And let's just grab, let's just copy this here and see what it looks like. So let's create a new component. Let's call it pay form. This is the formula pe with dot JSX. And paste this in and then find our main function called Hook form and just change it to pay for them. And then in our dashboard, and actually I think I'm going to include this in the current totals in kinda keep those together because we're gonna be adding these values to that dashboard. So I'm going to put them down at the bottom here. And what I'm gonna do is I'm going to create a flex component. And I'm going to justify content to the center. And I'm going to align items to also the center. In-between those, I'm going to put the pay form. A form. If I hit Enter, I think it auto imports it for me. If not, be sure you come up to the top and import pay form from a form. In my formatting is all off. Let me format this. There we go. And let's see what that looks like. So I'm gonna save it and I have an issue. Fail to resolve, React hook for him. Okay. Yeah. So we have to do we have to install this library. So let me kill my server and do yarn. Add, React, hook form. I think that's what we say. Or you can do npm install, React hook form. Let's install that first. Alright, run your server again. Let's give it a look. Alright, good. So we do have a little form here that just says firstName. It has a text input for your name and then a submit button. So that's fine. Let's tweak it a little bit to say pay your due and then take a payment. So if we scroll down, we'll see here this is our form. We have a form label that says FirstName. We have an input that has some attributes. Id name, placeholder name, this register, like registers, this value with the hook form. You'll see how this works in a minute and then set some requirements on it. So this is a required field, minimum length must be four. And then there's this error message that can come up if those requirements aren't met. So let's tweak this before we get to form control. Um, I'm just gonna do right above the form control here. And let me format this because I don't like the format either, right above this form control on the return statement. Let's do a text component. This is from chakra UI Text component. And inside of that, we're going to put a font. Font family equals heading and font size. Because we want this to be bigger, we're going to make extra large and font weight. We're going to do 600. And then we're going to put some margin on the bottom. So nb equals four. And let me bring this back up. And in-between this we're going to put pay your do. So we're going to have this above the form or above the input. So all we need to do here really is changed all these occurrences of name to something like payment. So we're going to change this is invalid two errors, dot payment. We'll take the label out completely because we don't need it, because we have the text above the form control here. For the input, we'll do ID payment, placeholder, Let's put payment, capital P payment. We're going to register this value, whatever we enter, we're going to register that as payment. And this is really cool. Like if you did a whole bunch of inputs here, it will create an array of key value pairs of whatever you submit in your form. So it's going to say payment colon, whatever we enter into the forum, it does all the work for us. Required. Yes, it is required. I'm not going to have a minimum length. So I'm going to take that out. Then down here arrows dot name, I'm going to put payment and errors dot name, dot message, change the payment. By the way, you could leave that as name. It'll just say on the output, it'll have the key of name instead of payment. That's kinda confusing. So we're making it payment instead. Awesome. And it has some built-in hook, is submitting, I think it creates a spinner or something. But here's your Submit button. So let's, let's see what that looks like. Actually before we do that, let's go up here and look at the onsubmit function. So they even include that form onsubmit handle submit, on submit. This is a React hook form. Convention here, but you'll see up here on submit, we have a new promise. Now, I don't want this setTimeout. It's just putting in like a filler for us that after three seconds it'll show whatever values we do to make it look real. I don't really want that. I'm going to take that out. I'm going to keep this JSON stringify. But I'm going to take this out. And I'm gonna make this a in an ES6 arrow function. So const onsubmit equals values. Then I'm going to make it a sink. And all I'm gonna do is log the values to the console, console.log. And let's see if this works. Oops, I need them. So JSON stringify these values, save that, and let's give it a whirl. But of course we have an error because we always have an error. Failed to construct text, please use the new operator. So I think it's because we didn't import this text component. So let's add text to our import, chakra UI import. And what else did we use? I don't think we used anything else, so that should work. Save it. And here we go. Pay your do. Let me clear the console and we should see our value come up. So I'm going to put hello and submit. There it is, payment. Hello, key value. So that's good to go, but we don't want for people to put strings in here. We want them to put numbers only and not only numbers, but decimal numbers because we're dealing with B&B. So to do that, we actually come here and we set the type to number. And then because we wanna be able to use decimals, we can add the step attribute and just put any save that. And now we can do like a 0.001, hit Submit, and it submits properly. And if we try to submit without anything, it's going to say this is required. This is required. I won't let us do it. That's what's neat about React hook forms. It does like all of this stuff for you. And once you get used to using it, it's a great library. And just in case you're wondering what this step any is, if I remove it and try to put in that number, I can put in 0.01, but when I hit Submit, it says please enter a valid value. The nearest values are 01, so you can only use whole numbers. You can't use this decimal. So we have to allow this step functionality. So step equals NE. Now that that works, let's go ahead and add the other one, which is the credit your account, where you can add credit to your balance. So we're gonna do the exact same thing. I can actually just copy this page form. I'm going to create a new component and call it add two balanced form that JSX paste that in our other form and just make some tweaks. So instead of pay your do, we'll put credit your account. Then instead of payment, we'll just do credit balance. So I'm going to select all of these actually and do credit balance. Then for the placeholder I want to see and I think that's it. Let's make sure that works. We do have the type and the step there which will need. Let's save that and refresh this page. And of course we need to add the form to our page. You go to current totals and write underpay form, add, add to balance. And we actually need to change this function names that are paid form. Add to balanced form. Then we need to add it to our current totals, right? Underpay form. We need to add the component. Be sure to import it at the top minds gonna do it automatically and to balance form. So there's my component and it is imported up here. Now let's check it out. Great. I have the payer due and credit your account. Now these two look stuck together, see how close they are. Let's give them some separation between each other and with the content above it. I'm going to go to PE form. And then right above this form, I'm going to add flex justify content equals Center. And this is just Flexbox align items in chakras own way center. Then we'll put some padding, so P equals five. And then I'm going to put some margin top equals ten. And I need to do the same thing on the other ones. So I'm just going to copy the first bit. Make sure you come down to the bottom and close that out. And also got to put my closing tag there and also make sure you imported at the top. So make sure you put flex to import that from the chakra library. And then we want to do the same on the ad to balanced form. So right above form, paste to the flex with the closing tag and come to the bottom to paste that. And then up here, added on the import. Let's take a look at that. There we go. So they have some space between them and they have some space above and below. Now, right below this we're gonna be putting three bikes. So we're actually creating what chakra calls a stack here. We're stacking this on top of this, on top of this. So I want to put a stack in the dashboard component. And up here above this, I'm gonna write stack as box, boxes and other convention of chakra. Text align center. Everything is centered. And then we're gonna do some responsive stuff here. And I think I copied this from some other place in the project. Like I said, I don't want to spend a whole lot of time on CSS because that's really not why we're here. We're trying to get this built real quick so then we can get to the fun blockchain stuff. So spacing base eight. And this is just sayings on small screens, using eight on medium is 14. So MD 14. And then PY padding y, which is the top and bottom padding. We'll put base 20 and MD 36. And we'll do a closing tag. And at the bottom, under current totals, paste that closing tag. And then up top you need to import the stack. Imports stack from chakra dash UI slash react. So just use this import statement and save it. And now we have an error. Box is not defined, so we need to import box as well. Save that. There we go. Now you see that our labels and text boxes and buttons are all centered accordingly because we did this stack and everything in this stack needs to be centered. So that looks great. So right under this, we're going to put this row of bikes. So a description and then these two buttons, and we'll be all done in ready to get to the fun stuff. So here under current totals, I'm gonna put flex, justify content equals Center, and align items equals center as well. And my closing tag I'm going to put below in my closing tag, I'm going to put directly below that. In in-between those. I'm going to add this bike components. So I'm just gonna put bike for now. And we're going to have three bikes. So go up here to components, right-click create a new file, and let's call it bike dot JSX. Const bike equals return bike a H1 of bike. Let's export that export default bike. And then in our dashboard, let's add three of these bike and be sure to import it at the top. Import bike from bike. Let's add three of these and make sure it works. Check that out. And box is not defined in the dashboard. It is defined. Let's save that again. Maybe I just need to refresh. Okay, flex is not defined, so be sure to add flex up here as well. Here we go, bike, bike, bike. So we need to replace these with images. I have three images for you to use. It'll be below this video or somewhere, wherever the course content is. And what I can do is I can open up, well, I'll create a folder called assets. Let me open that up in Finder and open up another. And let me find mine. So I'm going to paste in these three items. Bike one, bike to and bike three. Alright, so for our bike, what we're gonna do is create a box. Remember these, these are all flexed. So each one is going to be have this box component. And then the box size equals large margin x, which is left or right. We're gonna put two. So there's some space between it. Close that out. And in-between the box, we'll do an image which is gonna be our image source equals bike, margin, bottom equals ten. In this bike is actually going to be a prop. So instead of props, we're just going to destructure it and put bike. We're going to pass that in as a prop. Let's close this image. It's self-closing. Then we'll do a text component. And here you can just put some Lorem Ipsum. You can find some bike details if you want. I'm just going to do Lorem Ipsum generator for now. And I'll just copy this bit. Again. You can put whatever you want there, paste it in. And I'm going to put on word wrap. So if you go to VS code up to View and click on word wrap. So there's some texts that's going to be under the image. Then I'm going to stack some buttons. So I'm gonna do a stack. Spacing equals 0, direction equals rho, align, center, justify center. And then margin top equals five. Inside of the stack we want to put a button in. Remember we've used a button in the hero. So I'm just going to copy that. Go over here and copy this button. It will make life easier than us typing all this out. Go back to bike and paste that in. So there's my button will change this text to say checkout. And we'll put another one below it. So copy that again and change that to check in and remove the onclick. We don't want to deal with that yet. I'm going to format my my document and save it. And let's actually, let's do this before we check Import button from tracker UI, import box, image, text stack. And I think that's it. Also we want to, well, we're not gonna be able to see our images yet because we're passing it the bikes. Let's deal with that before we check our site. So our bike is a child to dashboard. So here's where we need to define our bike image. So up here I can do import bike. One from I think it's dot, dot slash assets slash bike one dot JPEG because I think the name of the image, copy that twice. And change bike one to bike to change bike 12 by three. So now we can take these and pass them as props. So we can say bike equals bike one. Bike equals bike to bike equals bike three. And so we're passing in each individual bike and we're receiving it as a prop in the bike component. Awesome, Let's take a look at this and see if it works. Great. So our images are here. They should be responsive. We're using Flex. Yeah, they're responsive. And we have some text that we can go back and tweak however you want. And we have a checkout and check-in buttons. Now these are circular and they don't have a space between them, so let's fix that. So under button, we don't need this color scheme, teal, Let's put m equals two to put some margin there. Font size equals small. Font weight equals 600. And then this background should be a total of 500. Remove the rounded and remove this padding x. And then for hover, Let's make it a 300. So it's a little lighter when you hover over it. So I'm going to take all of this and paste it down here. I'm going to paste that here and save it. And now it should look a lot better, except that the text is black. Let's make the text white. Color equals white. To match everything else. Make sure you do it on the other button to save it and boom, it's looking good. Now we should make this bike chain, this logo up here, go to the homepage when you click on it. So let's go to header nav bar, sorry. Let's find out where that is, bike chain, and let's make that a link. So let's put link. Because remember we have React router setup a link to slash, which is our homepage. And then we'll put bike chain in between that. And that will link to the homepage. So save it. And now refresh. And now when we hover over it, we'll see it's a link. We can click on it. And it does not take us to the homepage. Something went wrong. Oh, I see what's going on. It's importing link from chakra UI. And we actually need to import it from React router dom, import link from React router dom. That's what's going on. So we don't need this link here. Let's take that out and how it should work. Yeah, here we go. Bike chain and you see below localhost 3 thousand comes up down here. If we click on it, we go to the homepage. So awesome. I think we're done with the UI and can actually get started now and the logic. So if I'm on my homepage, I can connect wallet, the button there, I can choose my bike to go to the dashboard, which we have set up here. The dashboard gives my B&B credit. B&b do ride minutes in my bike status. I'm allowed to pay my du payment, credit, my account. I can choose a bike down here, check-out, Check-in. And I think I'm good. The only thing really left is when the, when a new user comes onto this page, they don't want to see their dashboard because they haven't entered themselves as a renter in the smart contract yet. So if I come to this app and I've never used it, I need to register myself as a renter. Remember we have that add rent or function. So when they first come here, there needs to be a form where they can add themselves as a renter, but we haven't really put any logic down yet to determine that. So we're going to hold off. And as we get the logic going, when we're actually able to determine whether they are or not. We'll add in that form. So great job pushing through this UI. I know you're more excited with interacting with the smart contract and building out that logic and connecting to the wallet and making transactions, all that fun stuff. But we had to get this out the way and it's now out of the way. And we're going to have even more fun in the next section. 6. Connecting MetaMask and Talking To Our Contract: Okay, so now to the fun part, let's hook our application up to the smart contract and start talking to the blockchain. So before we get into the front end, we need to go back to the contract folder here. And remember when we compile this contract, it created this artifacts folder and a Contracts folder, a bike chain dots soul folder in this JSON file with a bunch of data. And remember we talked about the bytecode and the ABI. The ABI again, is a way to tell your application what functions or methods it can call, what functions that can call and you're smart contract and some other information to do with that. We need to include this in our project, this ABI. So grab the entire array and just scroll down to the end of it and include the brackets and copy it. And now we're going to create in our client folder a file in the source folder called config dot json. And we're going to create just some regular JSON. So curly brackets in here, we're going to put ABI as a key and has a value. We're going to paste in that array. And I'm going to format it. And that'll be our ABI. Now in addition to that, we need to be able to now in addition to that, we need air contract address like where we deployed our contract too. So I'm going to add another key down here after that. So put a comma and type in contract address. And the value is gonna be the address to which we deployed. And I don't remember what that was when I did that. So I'm going to deploy it again. I'm going to cd back to the root folder, cd into my contract folder and run NP x hardhat, run scripts slash sample script.js. We're going to set this network flag for tests net. Remember we set in our hardhat config, actually hardhat config this networks, this object of networks and recreated one called test net. So that's what we're doing. We're deploying were running this sample script or this deploy script onto the test net. So I'm going to hit Enter and let that deploy and then I'll grab the contract address that was deployed to there it is bike chain deployed to this address. I'm going to copy it, go back to my config JSON and paste that as a value to contract address and save it in our contract, we can put it away for now. So open backup the client folder. And we're going, and we're going to get back to this. So what we're gonna do next is we need a way to store state. And I don't really want to deal with redox because this is a small project and Redux is somewhat complicated. So we're going to use something that's a lot easier called the Context API. And this is part of reactant comes with React and it allows us to manage state. So if you've worked with reacted before, you know that we pass props down to children and sometimes that can get like way out of control and we're passing events backup to parents and it's just crazy. So what this context API does is like Redux in that it manages state. But what this does, what this benefits us with is that we can wrap our entire project in this provider and then any component within that provider can access the state. So the state is going to be global and you can access it anywhere. You just bring that context in, in access it. So we're going to set that up and that's actually going to control like all of our functions that we talked to this smart contract with. So if you go to source and right-click and create a new folder, and we'll call it context. Whoops, create a. We're going to right-click on the source folder, create a new folder called context. For some reason it just will not. Let me do that. Here it is, context. So let's right-click on the source folder and create a new folder called contexts. And within that folder will create a file called blockchain context dot js X. And from here we're going to import a few things. So import, React and use state because we're going to use that from React. Next we're going to import that. Config JSON. So we're going to import that ABI and the contract address, and we're going to structure it so we can access both of these individually. So import ABI, contract address from. And then I think it's dot, dot slash config JSON. Good. Then next we're going to be, then next we're gonna be using a package called ethers js. Now a lot of people use Web three js. This package allows us to talk to the blockchain, but I'm next we're gonna be using a package called ethers JS. Now a lot of people I know use Web three JS. I like ethers, JS more and more acquainted with it. So I'm going to use that in this package allows us to talk to our smart contract into the blockchain. So it's very easy to install. Come down here. Let me get back into my client folder. In run Yarn, add ethers, ETA GRS. And while that's installing, I'm going to import ethers. Ethers. Pretty easy. Great. Next, we're going to create a context and we're going to export it as blockchain contexts. So we're going to put Export. Next. We're going to actually create this context. We're talking about the context API. We're going to create this now and we'll set it as a variable and export it. So we can put export, const, blockchain context equals React dot create context. And that's it. Next we'll create our component. Export. Next we'll create our provider component. And if you don't know how to use this, just Google it. And it's pretty easy. You can read up on it and be caught up within a couple of minutes. And just remember there were gonna be using the hooks variation, which is a lot easier in my opinion. Let's do export, const blockchain provider equals. And we're going to destructure our children instead of props. And that looks good. So what we're going to return here, the key to this whole thing is to return this blockchain context dot provider. So let's do blockchain contexts dot and you'll see they have consumer provider. We don't need consumer. We're using hooks, but there's a lot of things you could use here. We're going to use provider. And it's mandatory that you put a value in there, which we don't have at the moment. So I'm going to leave that blank. Actually, let me put this on the next line. We're going to return here the key component in this provider. So we're gonna do return, blockchain context dot, and you see there's a consumer and a provider. If you read up on the context API, you'll read about both were using hooks. So we're gonna be using the provider. And we're going to provide, actually let me just close this out. We're gonna be providing in here a value which we have to provide. But we don't have anything yet. I'm going to leave that blank. And then in-between these will put children because that's what we're passing in. So save that. And then we have this provider here. But we need to go to our main JSX and wrap the entire app in this provider. So I'm going to first import it. Import blockchain provider from dot slash contexts slash blockchain context. And then we're going to wrap this whole thing. So down here I can say blockchain provider and just put it outside of the chakra or UI provider and the entire app. And save that. Now this, these values that we pass in, any values that we pass in here are going to be available to all components that bring in this context. I hope that makes sense. Alright, so let's next go to the ethers, JS documentation. Ethers. Let's just type in ethers JS in the Google search, and then just click on getting started. We're going to follow these instructions. So how do you install it? We already did that. We already imported it. We're not using a script tags, so keep going. So here's the key to this whole package. In my opinion, it's three things. You gotta provider a signer and a contract. So the provider thank, read only. So a provider is a class which I provider in ethers. Let's not mistake that with their Blockchain provider or Context API. This is separate. A provider in ethers is a class which provides an abstraction for a connection to the Ethereum network. It provides read only access to the blockchain and its status. Remember that when you think provider think read-only access to the blockchain. Now a signer is a class which in some way directly or indirectly has access to a private key. Remember, we put her private key to a private key which can sign messages and transactions to authorize the network to charge your account or perform operations. So when you think provider, you think read-only, when you think signer think private key and sign messages, create transactions, make changes directly on the blockchain. So you'll need the signer for that. You've got the provider read-only signer can act and do things. So you've got the provider that's read-only and the signer that is able to transact and make transactions. And then you have this contract. And we're gonna talk about that next. Contracts and abstraction, which represents a connection to a specific contract on the Ethereum network. Smart contract that we deployed so that applications can use it like a normal JavaScript object. So we're gonna be creating this contract object and we're going to be calling all of our functions from it. So the first task here is to connect our wallet to our application and we do that through MetaMask. So be sure you download MetaMask if you don't have it, just go to MetaMask. I don't know why it's dot Zendesk. If you don't have it downloaded and get it set up, there's a million articles out there on how to do that. But I assume since you're taking this course that you already have MetaMask, but just Google MetaMask and go to Download and it's a browser. So be sure you have MetaMask downloaded and setup. Here's ethers sample of how to talk. So here's ethers take on interacting with MetaMask. So remember there's a provider, there's a signer. The provider is the connection to the Ethereum network. So the provider is actually gonna be MetaMask. And then the signer hold your private key and consign things. Remember we entered our private key when we deployed it. And remember our private key is in that ENV file. And we use that when we deploy the contract and then our wallets going to match that private key. You're going to use that same account that you use for your contract. Alright, so let's look at this. Let's go ahead and copy it because we're going to use it. Right? So looking down here, the comments are really helpful. This documentation is really good, in my opinion. But first you have this provider and they went through provide a wraps, a standard web three provider, which is what MetaMask injects As window dot a theorem in the each page. So on this browser page, MetaMask injects something called window dot a theorem into each page. So when we set up this provider, we use, we instantiate a new web three provider, which is provided by ethers. So we do a new ethers adopt providers dot width three provider and we pass in basically MetaMask window data theorem is the MetaMask object. So that's going to be a provider. We say that under the provider variable. Then we can actually use provider to send this. And then we can use the send method to request permission to connect user accounts. Then finally, we can take this provider and call, get signer on it and save that as our Signer. We're actually going to copy this and paste it into our applications. So copy that. And up here at the top, just paste it in. And I'm going to remove all these comments. One thing I'm gonna do is take out this await providers. And we're going to add that in an actual function because we only want it to happen when we click the Connect wallet buttons. So take that out. We have a provider, we have our signer. Now we need the contract. Now this is where it's going to make all the sense to you. So if you keep going down to contracts, it says the contract object makes it easier to use an onchange contract as a normal JavaScript objects with the mat, with the methods map to encoding and decoding data for you. This is great. This contract object makes it just, this contract object makes it so that we can treat all of these smart contract functions is just JavaScript objects. So if you keep scrolling, they give you the best example here. So copy this whole thing and paste it in your application. So I'm going to come down here, copy that in, and we're gonna work through this one by one and it will make sense to you. So instead of dy address, we're not dealing with di we just we're dealing with B&B. So just change that to address and we just put in, what do you think? Well, if you go up, remember we're importing the ABI and the contract address. So our address can actually be contracted dress. Now die ABI, where again we're not using die, so just change this to ABI. And what do you think that could be? Well, ABI. But the problem is we've kinda confused JavaScript. Abi is grayed out, which means it's not going to work. So let's change this to contract ABI. Contract ABI. So we're gonna put here contract ABI. So we have our address defined. We have the ABI. Again, this is a good comment. The ERC-20 contract ABI, which is a common contract interface for don't put that. So let's get rid of that comment. And then finally we have the actual object. Again, change this to contract. Then it instantiates a new contract. So instead of dy address will put address, instead of dy ABI, put contract ABI. And then we pass in our provider. But I'm actually going to pass in my Signer because I'm gonna be doing a lot of transactions. Awesome. So save that. We have all of our info here to talk to her. Smart contract. Now let's run air application. So yarn, run dev. And let's do localhost 3 thousand. And here's our application. So let's do yarn run dev to run our server and open up localhost 3 thousand. And we have some errors, good. Alright, so let's do yarn, run dev to startup or a server. That's gonna be on local host, 3 thousand. So let's open that up. Oops, the Saudi open refresh. And we have an error or the requested module does not provide an export named contract ABI. So something's wrong with that. You guys probably call it that, but it is importing ABI because in our config JSON, it's under the key of ABI, So we got to keep it that. So let's do this. Let's change the VAT, the variable to contract ABI and leave what we're importing as ABI. And then we change down here. Now the problem is that we're importing contract ABI, which is wrong because in their Config JSON, it is a key of ABI. So we have to import ABI. And then we'll call this constant contract ABI equals ABI, which is what we're importing. And then down here we got it right, so we had all kinds of mistakes there. You probably caught it. But make sure you make those changes. Import ABI, save it as a variable called contract ABI, and then pass that into your contract. Let's save it and see if that fixes it. Yeah, there we go. So now what we wanna do is when we click this connect wallet, we want it to open up MetaMask and requests their permission to connect the wallet to our account. Requests permission to connect to one of the accounts. So let's create a function for that, right, under this, I'm going to say const, connect wallet equals is going to be async. We're gonna do a try-catch statement. Try-catch. Here, we're going to say if window data theorem, so if this, this MetaMask object doesn't exist, then we're just going to return a alert and alert. Please install MetaMask. Then next we'll do const accounts. We want to get the accounts from MetaMask, so await provider dot send. Remember in ethers JS, if I still have it up. That was our example, a weight provider dot sinned. And what we want is yf request accounts. That's what we're calling them just for kicks. Let's console dot log accounts. And the first one, because that's gonna be the one that we're currently using, the current account. And let's just leave it there and see that we're consoling that or we're logging that properly. And then down here in the catch, we'll do console.log error. And I'm actually going to do a throw here new error. And let's just say no, a theorem object. And I can't spell the word throw. There we go. So we want to call this when that connect Wallet button is pressed. So how we work with this provider is we take this function name, we come down here and we pass that in as a value, connect wallet. And then where's the button that? Well, the button if we go and components, the button is a navbar. So at the top of navbar we're going to import the provider. So import blockchain contexts from context slash blockchain contexts. So make sure you import it. Then because we're using hooks. We can come down here and type const. And what function are we providing and the provider will connect wallet equals use context, blockchain context. Now you can create multiple contexts in your application. You can have like a user context in a transaction context and things like that. So all we're doing here for this. Component is we're just making available this blockchain context. And we're bringing in Connect wallet. And then down here where we have our button that says Connect wallet, we're going to add an onclick. Onclick equals connect wallet to call that function. And that's how easy it is. So let's save it and check and see if it works. Open the application and there's an error. So the error is used, context is not defined. So we've got to come up here. And where we are not even. And just do an import. Use context from React in, remember when you have a JSX file in now in React, remember when you have, so be sure to import that. Let's save it and try it again. And so when we click this connect to Wallet button, it should open up MetaMask just like that. And I want to connect my BSC test account. So I'm going to click Next. Now if I selected multiple, it's going to put all four into this. So that's why we're choosing the first one. But I'm just going to click on one because that's all I really do. Hit Next. So if I click Connect wallet, it's going to bring up MetaMask as it should. And I'm going to select the account I want to connect. Now. I could collect connect. Now it could connect multiple. And that's why we have the accounts 0, because it's an array of accounts in the first one is going to be your current account. But I'm just going to select one and click Next and connect. And it's going to connect my MetaMask wallet with my application. Great, so we're connected. If we open up MetaMask, we see this little connected light is green. But the problem is we don't know it in our app. It just says while it's still. So I'm going to disconnect and we're going to fix that. So disconnect this account, and then let's go back and do something better with it. So back to the blockchain context. We're going to create some state to store that current account in. So I'm going to come to the very top and do const current account. Set. Current account equals use state. And this is just React Hooks. They use statehood. And all it's saying is the current account is going to be the variable that holds my state in set. Current account is what I use to set this state down here where I consoled the account. I'm also going to save that into the current account state. And you do that by saying set current account, accounts 0. So that's going to save it at, so that's going to save it in there. So that's going to save it as current account. But that doesn't really help us because we need to pass that current account through air provider. So come down here and put a comma and put current account so that we can pass it to our provider and then back to the navbar. And we want to also bring that in current account, make that available to our component. Then down here we can do some logic. So we'll say if there is no current account, note the exclamation mark, then we'll just say connect wallet. This means nothing's connected because there's no current account that hadn't been set yet. Then else we're going to display our wallet address, but we're going to slice it up so that it's like the first five characters, dot, dot, dot, and then the last four characters. Most apps do that. So we're gonna do that too. And we can say we're going to use a template literal. So do the two backticks, dollar sign curly braces. And we'll put current account dot slice. Then 0 to five, so the first five characters. And then we'll put dot, dot, dot. And that's why we use these template literals because we can mix in variables with string values like dot, dot, dot. And then right after that, we'll do the dollar sign. Curly braces in type current account, in type current account, dot slice. And this time we're gonna go to the end and count up all the characters and then just grab the last four. So we can do that by saying current account dot length. This will get the length of that while at address minus four. And that's what we're going to slice. So let's save that and try it out. Refresh. And now let's go to connect wallet. Make sure you disconnect so that you can connect again. Choose your account, click Next. And once I hit Connect, it should say store that in the state and then update my component to show my wallet address. So hit Connect. Look at that already. There's my wallet address, 0 x six to 73 dot dot, dot B F6. But we still have one problem. If I refresh, it's gonna be gone. Now it says Connect wallet, even though I'm still connected. Let's disconnect and fix that. To fix that, we'll need another function back in the blockchain context to check to see if the wireless is connected. So here's how we connect. But when the app first loads, we need to check if it's connected or not. If it is, we need to store the state. Let's create another function. And actually I'll just copy this. And we're going to call this one. Check if wallet is connected. And we'll still do this. We'll check if the MetaMask object is there. We'll do accounts. But in this time instead of e underscore request accounts, we're actually just going to do underscore accounts. So this is going to request the accounts, not permission to use the accounts, but just the accounts in general. So if there's anything connected, it's going to show up here. And then we'll do something here like if accounts dot length is true. So if there is linked on the accounts, then we'll set current account accounts 0. Else console.log. No, no accounts found. And get rid of these two. This time I'm not going to throw an error. But again, all we're doing is getting the connected accounts. And then if there are any, will set the state. If not, we'll just console it out. So we'll know. So this one we don't want to pass to the provider because we don't need it anywhere else. We actually need it when the page first loads. So I'm gonna come down here and add a user effect Hooke. And use effect hooks allow you to run. And use effect hooks allow you to run functions once something loads or once something changes. So at the very end of this, you can do comma, whatever. Like if you're watching a variable whenever that variable changes, this thing will run again. But we're going to put empty brackets here are empty. Empty brackets here, which means it's going to run when the component first loads, finishes loading. We're going to actually put that checkup while that is connected there. That'll run when the page first loads up. Again, when the page first loads, it's going to check if a wallet is connected. If so, it's going to set the state. So let's save that and try it out again. And by the way, every time you load in, by the way, every time you save. By the way, every time I save, it just throws these crazy errors. I'm going to show you how to fix that in a minute. But let's just refresh and test this out. So click Connect wallet. I'm going to connect it again, connect and it sets my address. And now if I do refresh, it stays. It's good to go. If I go to the next page, it's still there. I go to the first page is still there. So that took care of that. Now, just as I was saying, if I save this again, And come back, my page is completely wrecked. And to be honest, I don't know what's going on. For some reason, vite JS is doing a page load, is doing a page reload instead of the hot reload. I don't know if it's a bug or maybe something I overlooked. But other people are complaining online. I think this is a new thing. And if I knew this, I would have used Create React app, but it's actually a pretty easy fix. This guy just listed it here. And what we need to do is go to our vite config and just add in this server configuration. So if you go, if yours isn't doing this, don't worry about it. But if it is go to vite, config js and just add this in, put a comma after this, and do server h EMR true, which is hot module reload, which is what's supposed to be happen in any way I thought. And then do watch. Use polling. True? And that's it. Now save it. And I probably want to restart my server just because it's a config. A lot of times we need to I'm going to restart it and that should take care of the problem. So let me refresh now let me go save and see if it throws that error. I'm going to come over here and click save a couple of times. And there's still an error. What is going on? Server ASMR true, Watch, use polling, true. Alright, server restarted. So let me save it. It's fine. Save it again. Save it here. Save it here again. It actually looks like it's just happening in my provider file. So if I come here to main JSX and hit Save, then everything is fine. But if I go to my provider and do that, save it, it messes it up. Well, I'll try to figure out the answer to this in the future. Me. We'll come back and tell you how to fix it. But it really doesn't matter. Only in development, like if you come here and click around, it never happens. It only happens with this white hot module reload. So I'll figure that out and I'll, I'll post it here in a little bit. Alright, so the last thing we wanna do in this video is we want to try to talk to our contract to make sure we've established that. And once we have in the next video, we'll just go full speed ahead and get everything set up. So let's go back to our blockchain contexts. And let's create a function that gets the balance of their smart contract. So if you remember, we have in our contract folder and our contract, remember we have a function called balance of that returns the contracts balance. Let's try to call that and see if it works. So I'm gonna go to my blockchain context and just do const, get balance equals, equals a sink. And we're gonna do a try-catch. Console dot log error. In up here under try, we're going to say const balance. And remember we have this contract object that allows us to talk to our smart contract. We're going to say contract. We're gonna do a wait because we have an async function. And then contract dot balance of because that's their smart contract function name. Then right after that, we're going to save that in our state. So. Actually, let's just console it out to Ashley. Let's just log into the console. So console.log balance and just see if that shows up. Go back to the project and reload the page, and it should be popping up in our console. It takes a minute to call it an actually no, that's not going to work. Then right after that we're going to set the state, we're gonna put it in the state. Then we can put that in the console to see if it works. Let's go up here and create a new state variable, constant, balance, SET balance. And you see the pattern here. There's the word and then set word equals use state. And so down here, we're going to set balance to balance. Then I'll console.log balance. And this is not being used anywhere, so it's not going to be called. There's none of this is going to work. But just to test it, Let's come down here and call get balanced. When the page loads. Let's save it and refresh our page. And look at that. We get returned what's called a big number. A big number is error amount in way or air amount with 18 zeros on it. That's why it's called a big number. C right here at 0 x 00 is big number true. So the big number is great. It's great to do the work on the contract, but it's not readable. Like we don't want to look and be like I got 1 trillion something of ether. We want to say I have 0.001 or 0.01, B&B or whatever. So there's a helper function. If you go to ethers, JS, and type in utils, and type in utils. And that wasn't helpful. Type in ethers, dot js utils, and click on utilities. And then you should see, and then type in a big number. There it is. And you should see down here, I think it's called parse ether. Yeah, here we go. So there are these, there's these conversions. Ether dot utils, dot format units, ethers utils format ether parse units. And all this does is it just converts this value for us, like the one we're gonna be using is format ether. And this just isn't a good page. Let me, let me copy and paste this. Ethers dot js. Here we go. Ether strings and weigh. The one we're gonna be using is called format ether. And this is when you have way and you want to show it as regular ether or regular B&B or whatever you're used to seeing like the human-readable amount. So formatted amount of way into a decimal string representing the amount of ether. That's what we're going to use. To do that, we'll type in. So to do that, we need to set balance. So to do that we need to put instead of balance, we need to put ethers, dot util, utils dot format ether. And then we pass in the balance. And this is going to set it to this nicely readable format in ether or B&B, not the way 180 formatting. So let's save it and now it should be showing 0. Let's refresh the page. It still says big number. Let's save it again. I don't know, maybe my state It's still showing big number and that's probably because I'm calling balance, which is this. Oh, yeah, that's it's still showing big number. I think my issue is that I named this balance and then I also have set, my state is balanced, which I'm using here. So it's probably using this original number. Let's change this to a balance of just put balance of. And then now we're sure that this is our state variable up here and not this. So that's my bad. So let's call the variable balance of format that and then grab the state variables. So save it and now it should be good. So refresh the page. In the try part of this, we're gonna say const, balance of equals. And we're going to use our contract object. Remember that's how we're going to call all of these smart contract functions will do contract dot balance of, because you remember if you go back to our contract, we have a function called balance of we could call get total duration or set do and we're gonna be doing all of that. But for now we're just going to test this one. So we'll call it. So we'll say contract dot balance of. Then right below that, we're going to set another state variable to hold that value. Let's come back up here and type in, right under this put const, balance, SET balance equals use state. Now you see the pattern here. First one is the variable and the second one starts with set, because that's the variable you use. That's what you use to set this first variable. So we can save this now in our state. So right below this, we'll say SET balance. Balance of in this try block, we're going to get the balance. So let's do a const, contract balance equals and we're going to use our contract object because that's how we talk to these functions in our smart contract. Now we're going to use this contract object that we created here because that's how we're gonna interact with their smart contract. So we'll say contract dot. And if you remember, if you go back to the contracts, you remember we have a function called balance of that returns the contract balance. We also have set do and get total duration. We're gonna be using all of these. But for now we're going to use this balance of. So we'll do contract dot balance of. And then here we're going to save that value in our state. So let's come back up and set a new state variable. So const, we'll call it balance and then SET balance. You see the pattern here. There's the state variable and then you set it with the second one, equals use state. So back down here we'll say SET balance to contract balance. And let's save that. Shoot. In this try block, what we're gonna do is get the balance. So we'll say const. Let's call it contract balance equals await because this is an async function. And then remember up here we have this contract object. This is what we're gonna be using to interact with their contract. So we'll do contract dot in what function do we want to call? Well, if we go back to our contracts, we want to call this balance of function because it returns AIR contract balance. Now, later we'll be calling balance of renter and get total duration and get du and all that fun stuff. But for now we just want to get the balance to make sure that everything's working. So contract dot balance of That's gonna get our balance. And then we want to save that value in our state. Actually, before we do that, let's just console dot log this out, contract balance and see what, see what it returns. And remember this get balanced didn't mean italicized. Remember this get balanced isn't being used. So if you see this, this get balanced isn't being called anywhere, so it's not going to work. So we need to come down here and just add it to our user effect for the time being. Save that and let's see what shows up in the console. So let's go to console and wait for it to return. It takes a minute. There it is. Big number. It returns a big number. Well, that's not helpful. We were thinking it was going to return 0. So what is this big number? Well, if you remember in our contract, remember the value way that had 18 zeros on it? Well, that's what this big number is. It's the way equivalent of ether or the way equivalent of B&B. So if you have 0.01 B&B, well this big numbers like 100000018 zeros. So what we wanna do is convert this into what we're normally used to seeing, which is the decimal amount. And to do that, ethers has these ethers has this utilities package. So if you go to the ethers documentation or if you just Google like either ab.js parse ether or something or format ether. We're gonna be using this format Ether method because you pass in way, it's going to format the amount of way into a decimal string representing the amount of ether. That's exactly what we want. So we're gonna do this utils format ether. And so we need to do, in this time we're going to store it in state because that's what we wanna do anyway. So I'm gonna come up here and create a new state variable, const balance, SET balance equals U state. Then down here we can just put SET balance. And instead of putting contract balance in here, we're going to put ethers dot utils, dot format ether. And then we're going to pass in the way equivalent, which is the contract balance. Pass that in. And that should be it. So if we go back to our project and we reload, and if you haven't used react a lot and don't know about the reactive to 7. Building the Add Renter Form: Now we're gonna get started on our dashboard here, where we can start populating these dynamically. Currently we just have static values, but we need to be able to populate these. We need to be able to make a payment and credit our account. And by the way, up here we have credit and then the payment in here, it's backwards. Let's swap these real quick. If we go to the current totals at the bottom, just swap these two components, add the balanced form before pay for them. That'll fix that. But before we do all that, we need to create a form like this, the way this dashboard is currently, it assumes that the renter has already added themselves as a renter, but we haven't yet. This again is just static text. So we need to put a form here to display if the rent or hasn't added themselves as a renter. And then if they have already, then we'll show the dashboard and their current values. If we try to go in credit the renter and check their ride minutes and all of that, it won't work because remember we have this function in our contract up here that says Add renter. We need to add renter to our mapping of renters here. So that's what they need to do. Essentially, they need to fill out the form to add themselves as a renter, which then allows them to check out a bike. Right before we do that, we have one thing to address. So in the previous video, you, one thing you might have noticed is whenever I was working in his blockchain context file and I made a change or whatever I was doing. And I went to hit Command S to save it, it would actually crashed my page. So let me hit Command S, go back and you'll see my pages crashed. If I open the console, you'll see a whole bunch of errors that relate back to the used contexts hook. Now the reason for that is because in air blockchain context at the top where we create the contexts, we left the argument null or parameter. No, we should put something in here and we're just going to put an empty string. And I'm going to save that. And now let's test it again. So let me refresh this. And I'm gonna come over here and save it a few times. And you should see that my page is fine. So that's an error on my part. Go to the React dot create context and make sure you put in a value, in which case we're going to put an empty string. Alright? So let's create a new form. We're going to call it rent or form dot JSX. And again, we're just going to take the one of these other forms. Let's try the ad to balanced form. And we're just going to copy and paste this in. And then we'll come up to the function name and call it rent or form. Alright, and then we scroll down, you see this credit your account. We want to change this to something different and I'm actually going to come up here above the flex. And I'm just going to put a text field. And in the TextField I'm gonna put as attributes, font-family equals heading. Font size equals 600, or actually x large. And then font weight equals 600. Alright, and make sure you put the closing tag. And then inside of that, we're going to put some texts. We're going to say welcome. And then I'm going to put a line break. And please enter your first and last name to register. You might be like, isn't this a decentralized app? Why do we want somebody's last name or even firstName? But it's just a concept I came up with when I made the app. If you want to change it, feel free to change it. And you'll see we have this error because we, because we can't have multiple tags and a return, we resolve that by doing this open and close empty tags. So put that at the top and a closing one at the bottom in all as well. So we have our texts here. We have a flex and then we have our form. In the form we actually just want the firstName and lastName because can rent remember is gonna be set to true because they're just creating their account. Of course, they can rent. Active will be set to false because they don't have a bike Yet. Then the start time, end time, balance and amount due are all going to be 0. So that's going to be set on the backend, or outside of the forum or outside of the users ability to change that. So we just need a first and last name. So we have already one input. So I have formed control. Let's do it. Let's actually do a label here. So form label in HTML four equals firstName. And we're gonna put FirstName here. This is just a label. And then we have our input, our error message. And then we're going to copy and paste another one of these. So another form label input and error message. So right under the error message, paste another one. And we're going to set these two up. So HTML for firstName. So we're going to again put firstName, take out this type number in step any because we do want characters. Placeholder, firstName. And then everywhere there's a credit balance, just do firstName. And then in the second one, we want last name right here, change this to LastName, lastName, take out number in step. Placeholder is going to be LastName. Register is LastName. And remember I told you that this register, and I'm going to make these not that camel case. I want to make it all lowercase to match with the other ones. But remember I told you about this register. It actually registers the input that you're putting in the fields and puts it in this object that's then sent to wherever you're sending the form, it's pretty cool. That's all I have to do. So lastName, change these two to LastName. And then up here where it says form control, there's a check for is invalid. I want to check if there are errors. Firstname and whoops, and errors last name. So right here we have an error message. So if there's an error in this one or this one, and actually we set it for, and so both of these have to be error-free to pass. So you can't put a field. So you can't put values in one and not the other. And for this one we do want a minimum length. So let's do men length value four. And the message is going to be minimum length should be four. We're going to put that in the next one. Let's save it. And up here where it says credit your account, take out that whole text because their texts is going to be above it. In then in air onsubmit. We're going to console log the values. So let's, I think we're good. Actually, let's see what this looks like. So we haven't put any conditions here if I refresh and actually we haven't even added it to the page. So that's actually going to go in current totals, I think. Nope, it's gonna go in dashboard. So right here where it says current totals. Let's just comment that out for now. Just to see what this looks like. We're going to pull in a renter renter form and be sure you import it, save that and let's take a look at what that looks like. Yeah, so here's FirstName, LastName. So I'm going to add a little space below the first one to make it look a little better. So if I go to the dashboard, actually it's going to be rent or form. So this second form label, I'm just going to do margin top equals four. Let's do three. See what that looks like. Three is not quite enough. Let's try five. Alright, so welcome, please eat ether. I put ether. Please enter your first and last name to register. So let's try Travis and then test. And if I hit Submit, it should log into the console. There it is, firstName Travis, last name, test. It's that easy with React hook form. Awesome. So now we need a way to know if a renter exists or not. And if you remember, in our contract, if we go to the bike chain dot soul, we created this renter exists in all it does is return true if there is a wallet address for that renter and false if not, we're going to use this to determine and that'll help us flip between air form in our dashboard. So good a blockchain contexts. And right where we left off at this Get balanced. And actually you don't need to call the get balanced because nobody really needs to get the balance of the contract but the owner. So we don't want that color, but you can leave it right here under Get balanced, we're going to create a new function called get renter exists. So we're gonna check and see if the renter exists. A sink. And we're gonna do a try catch. And the catch, we're just going to console it. Then up here we're going to do two things. We're going to check if they exist. And if they do exist, we're gonna get their information. So remember in our contract here, we have a function called renter exists. And what that does is it returns true if they have a wallet address and our mapping. So it returns true if they do exist in false, if they don't. If this returns true, then we're gonna go ahead and call this get renter function so that we can get the renters information in stored in our state and do everything we need to with it. So we're actually going to have two functions here. We'll start out with getting renter exists. And actually I don't know why I named it that it's check renter exists makes more sense. So here we're going to say const renter equals await contract dot, and we call that function renter exists. See here on the smart contract. Contract dot renter exists. And we need to pass in air wallet address. And if you recall up here, we're saving that in state under a variable called current account. So copy that, come down here and pass that in. And then we want to set that state. So we want to set the state whether they exist or not. I like to keep things in the state in case I need it. I think in other pages we're going to need to be able to know if that's true or false. So let's create a state variable. So canst renter exists, set renter exists equals US state. And let's put here set renter exists. Renter will pass that in. Awesome. And like I said, if they do exist, we want to go ahead and get their information. So right under this, I'm gonna say if renter, so if renter exists, if that is true, then we're going to call a function called get renter. And let's put in a weight on it. So right below that, I'm going to put const, get renter. Let's create that function equals a sink, whoops, equals a sink arrow. Then we'll do this try-catch, but I'm just going to copy this to save time. And contracted dot. Now, what is their function called for that? It's called get renter and we pass in a wallet address. So here, get renter, we pass in a wallet address and then we're going to set the state. We're gonna save that renter values in their state. So let's come up here and create a new one. Const, renter, set renter equals U state. And down here, we'll just put set renter, renter to save it in our state. Then we can remove that. So now when this component loads, this context loads, we wanted to call check renter exists because we want to know that upfront. So we need to take this and include it in our user effect. So that it's called when this loads. And then that check render exists, saves, saves that true or false in the renter exists state variable. So we can come down here and pass to our provider, renter exists. So that'll tell us true or false. And then let's save that and we'll come back to getting the renter information. But we just want to know now true or false whether they exist. We're going to send this to our provider. And then in our dashboard will be able to test whether we should be showing the form or the dashboard. So up here, we're going to say const, renter exists equals use contexts, blockchain context, and be sure you bring that. You import use contexts from React and also import the blockchain contexts as well. Now we can come down here and say, so we need to check a few things here. We want to check if renter exists. We want to display a spinner. Else, if renter exists is true. We want to display the dashboard. Else display their form. So if we set the default value of the renter exist if we set this to false or something, that wouldn't be any good because that would tell us always to show the form because their rent or doesn't exist. So show the form. But we actually want it to spin before it sets anything. So we want to spinner before it determines, Hey, it's false or hey, it's true. So we can actually do this with the ternary operator. And a lot of people don't like this. I don't mind it because I see it a lot and I'm used to it. But we can do like an if else, else with ternary or if else-if else. And we can do it like this. So a renter exists equals null. Then showSpinner. I'm just going to put this in quotes for now. Else, if renter exists is true, then show current totals. Else show the rent or form. So I know that may look kinda weird to you. If renter exists equals null, then show spinner. And it's usually like else something. But you can say else if renter exists is true, then when you put this question mark here, then show current totals, else show rent or form. So this checks three conditions, null, false, and true. So instead of the showSpinner, this isn't gonna do anything. Let's install some kind of spinner package. I'm gonna go here and just do react to spinner. Spinners. Let's go with that. So yarn add, react to spinners. Start my server. Install that. Awesome. So here we're going to display a spinner. And how do we do that? So we're just going to use this clip loader. So copy this. This is a short clip Loder from this React spinners. Going to paste it up at the top. What else? It looks like. We need to set a state variable loading and set loading. And that's by default going to be true. So that's going to be loading when we start the page. Then that's probably going to correlate to our spinner somehow. So here's our clip loader. There's a color property which we don't want to mess with, or CSS or size, maybe we do want to mess with size, but here's loading equals loading. So let's copy that and put it in error clip spinner. And actually I'm just going to copy this whole thing. And we'll just take out what we don't need to copy that and paste it here. And let's take out color. And let's take out CSS equals override. And I'm thinking 150 is gonna be big. So let's do 75. And then take out this pseudocode and save it and see what that looks like. So let's start our application. Yarn run dev. And let's refresh. We have a big error. Use state is not defined, yeah, so we need to bring in US state. There's used contexts. Just add use state, save it. Awesome. So it looks like we have a spinner and it's not resolving to anything. And then it looks like we're still showing the form. We want to get rid of this form because it's not supposed to be showing. And then we want to center this spinner. So to center the spinner is very easy. We just take this clip loader and just wrap it in this chakra UI Center component. So just put Center and put that at the beginning and then the closing tag at the end of the clip loader. And then we forgot to remove rent or form down here and then go ahead and remove this commented out current totals. Now let's save it and see what happens. So it's refreshed the page and it's just stuck spinning. So that tells us that something is wrong because it should resolve like rent or exists should change in this condition. She should not show this clip loader anymore. It should actually show current totals or rent or form once it resolves. So there's some other issue going on. And you can see that right here, we have an error. That error says resolver or address is not configured for DNS name. This is like one of the most vague errors of ethers JS. It can mean a million things, but I do know in our context, it probably means that in our blockchain context, when we're using this current account, this probably means that this current account isn't set yet when we're calling this. And we can determine that by putting a console log here, current account. And actually I'm going to put backticks and say current account. And then current account just so we know what that is. Let's save it and see what it gives us the current account. So look at that. Current account is blank. So that's exactly what's going on. And to be honest, I don't know the fix at the moment. I have to dig into this to see why, but I'll figure it out and I'll let you know here in the next video. But a quick fix for us now is to come down here to the US effect and add in current account here. Now would use effect does use effect is called when the component loads. It can also be called again when these values change anything in this array. So I can have current account, I can have renter and all this other stuff. When these values change. Or updated in some way it'll cause the call they use effect again. If we put current account in here, if this function is called, there is no current account and it throws an error. Well, when the current account is resolved, It's going to come back and call this again, which is going to call both of these functions. Again. Though it will error, it'll go back and call it again once it is resolved. So we're gonna do that for now just so we can keep moving. I'll give you the fix here in a little bit, but if you save this now it should work fine. So refresh. And there we go. And then you see current account is blank here, but then it shows it again with the address. So that is the issue going on. We'll address that in a bit. But right here it says, Welcome, Please enter your first and last name so it shows that things are working. If we refresh again, it's spins and then it shows, Hey, the renter doesn't exist. So it's making a call, it's returning false and showing our form. So now let's set it so we can actually register as a renter. So right under get renter, we need to make a call to register ourselves as a renter. So let's go back to our contract in find that I think we called it add renter here does add renter. That's what we need to call. And so let's go back here and let's create a new function. I'm going to copy and paste this in. I'm going to call it add renter. And renter. And then we're gonna do contract dot add renter because that's a smart contract function. Then in this ad rent or function, if you come back to the smart contract, we're passing in everything while at address, first name, last name can rent active, start in time balance and do. So. We're just going to pass that directly into our function up here. So put wallet address, FirstName, LastName can rent, active, balance, do start and end. So we're going to pass in all of that when it's called. And so right here in the ad renter, we're going to pass in that information. So I can actually take this, copy it and paste it here. Then when we're making calls to the contract, we can use this nice method called weight. So you can see a weight, add renter weight. And what that does is it stops there until the transaction is finished. So it stays here and waits. And then when the transaction finishes, then it continues to execute code. So we're just going to test that by console log, rent or added. We're actually we can do some fun stuff. We can do firstName added. And then right under that, we're going to want to get that renter information. So we have this function called get renter that sets the renters state variable with the renters information in that get renter is called by this check rent or exists. So all we have to do down here is just call check rent or exists. And that will check that they exist in populate our state with that renters information. So let's save that. We don't want this called when the page loads. So we're going to take the whole function and pass it to our provider. Save that, and then we'll go to a renter form. And we want to bring that provider information that state information into a renter form component. And you've done this a bunch, you know how to do it. It's as simple as const. Add renter equals, use context, blockchain contexts. And be sure to import use contexts from React and import the blockchain context. And then when we go to onsubmit, we're going to call that add renter. Now remember, we're only getting the firstName and lastName from the form. And that's because can rent when a renter has created can rent is true because obviously they're able to rent. Active is going to be false because they don't have a bike Yet. They're just signing up. Balance is going to be 0. The amount due is 0, and the start and end time we're going to be zeros. So they can always be set from here so that the person filling out the form don't need to put in useless information. So in our onsubmit, we're gonna do this. We're passing in the values. We're going to say values. Can rent equals true. And what we're doing here is setting more values in an object. So let me just copy and paste this a couple times. Values, active equals 0, values, balance equals 0. Values do start and end. All equals 0. Oh sorry, active is false. Then zeros, zeros, zeros. So we're populating these because they're always gonna be default. Then we also need to pass in the wallet address. And we don't want the user to have to pass in a while that address and we didn't put it in the forum, so we need to include that as well. So we can bring in the current account here from the blockchain contexts. And we can do this spread operator to create a new values object. So const new values object. What we'll do is we'll have wallet address. Whoops. What we'll do is we'll create an object. The first key value in the object will be wallet address, that will equal current account. Then we can just spread the values out. In this object. This is the spread operator. And what this does is it just adds all of these values, the ones they submitted, including these two, this object. It's really cool. If we console log out new values object. Let's see what this looks like. A fresh, Let's put Travis test, submit and look at this. We have an object that has wallet address, FirstName, LastName can rent, active in all this other stuff. So we have our key values and we're ready to use them. But we don't want to have to be like new values object dot wallet address new values object dot can rent. So let's now use D structuring to pull these out. So const wallet address, FirstName, LastName, can rent. Active balance. Do start in, then equals new values object. This is just the structuring. It pulls all these values out so we don't have to use this dot notation. And finally, the last step is we'll call air wait, add renter will pass all this in. Again, if we didn't do this restructuring, we'd just have to do like this. New values object dot wallet address new values or objects. So this is just a shortcut. You can do that. But I think this looks a lot cleaner. So again, we're passing in our values. We're adding these defaults to it. We're adding our wallet address in creating a new object where D structuring the values out of it. And then we're passing them into our add renter function. Awesome, Let's try this out and see if it adds a renter. So I'm going to say Travis test and click Submit. And it should bring up MetaMask. We have an error. Cannot read property is of undefined reading length. So add renter. Yeah, there's some issue here. So let's let's go back to here instead of. But wait, add rent or let's do a console.log. Save that and see what it says. Travis test. We got some undefined true-false zeros. Alright, so last name is undefined. It looks like that's the issue ever wallet address, FirstName. Lastname is undefined. Let's see what's going on. So if we go to our render form down here. Yeah, I knew I did this out of feeling. Lastname. It's like last capital N. Here is FirstName without the capital N. I'm gonna put these capital ends back just to be consistent. So let's highlight all of this. And do firstName. And then highlight all of the last names. And do it the same way, capital N. And then up here, we need to make sure we have the right things. And those change both of these first name, last name, and save that. And now we should be good. Let's try to console it out again. Travis test, submit and we have wallet address Travis tests true-false 0000. Alright, We're good. Let's change this back to await, add renter, and try it again. Refresh just to make sure I have everything clear. Travis tests and click Submit. This should bring up MetaMask. And here we go. Look at that low gas fee. That's great. I like it. Now. I'll hit Confirm. And let's see. It's probably pending. It's pending now and see how this is still spinning. That's React hook form. The is submitting hook that they added to the form that keeps that spinning until it's complete. Now, look at that. Once we were added, it detected the change and now it shows our dashboard. Isn't that awesome? That's great. Now if I refresh, I should see my dashboard instead. So I got the spinning wheel and there's my dashboard. Awesome. So again, so again, just to recap that, that issue was that we should have been using this camel case, lowercase, first word and then capital, all the other words. That messed up our last name. So we just went back and changed all these camelCase. Change first names to CamelCase. Then up here, just making sure that we're passing in the camelCase version. So great job. It looks like a dashboard is working. It can tell whether we are renter or not a render. So in the next video, we're going to start populating these fields dynamically. We're gonna be able to credit our account, pay our balances, and check out bikes. So we're going to do a big push in the next video. And that'll get us close to the end of our application. 8. Populate dashboard final optimized: Alright, so I redeploy my contract just so I can test that everything is working again. So I'm gonna put Travis test and I'm going to add myself as a renter. So I'll click Submit. Metamask will come up and I'll confirm it. And once that is done, it should show my dashboard. So it's currently pending. There we go. Dashboards up. So before we press through all of these values, which actually won't take as long as you'd think because they're smart contracts done all the work. Before we actually do that, there are two things I want to address. First, we have a little bit of a bug. So if I open my dev tools, so if I come up here to MetaMask in disconnect my wallet. So disconnect and then refresh. You'll see that the spinner will just continue to spin and spin and spin and spin. And nothing will load. We need to fix that. And the way we fix that is we come to the dashboard and remember we put this if else-if else ternary here. Well, we need to add one more condition. So if the problem is, if the renter exists is null, then the spinner spins. But if we don't have an account connected, then the renter exists, is going to be no. So the spinner is always going to spin until we connect a wallet. So to fix that, we just put another condition here. We put end current account. What that does is it makes it so that if the render exists is null and there is a current account, then show the spinner. So if there's not a current account, it's not going to show the spinner because both of these won't match. And then it will move on to check whether the renter exists, which it won't, and it'll show the renter form. So just add that current account and save it. Let's try it again. So let me refresh. And actually I need to bring that in. So up here in my context, need to say current account so that I can access it. So I'll save it. And we should be good now. Yeah, there we go. My wallet is not connected and it's showing my form. Now that's not gonna do anything. If I fill it out, it's going to throw an error. If I put something like that, it's going to throw an error because obviously we don't have a wallet connected. We can't talk to the blockchain or the smart contract. So let's go ahead and connect her wallet. Connect. And now my dashboard will show. Now the second thing we want to address is that issue we were having in the last video. Now remember, whenever we call the current account in these functions, the value hadn't been populated yet in the state, so it would throw an error. And we combated that by adding current account in our user effect. So when that changed, It would call Hughes effect again. Then we would get our value. So remember that we have current account is blank and then we get an error because we're calling a value that doesn't exist yet in them and that populates, then it works. So we talked about that in our last video and we're going to fix that now. We don't want to throw an error every time before it actually runs. So the way that I'm going to address it in this application is to just wrap it in an if statement. So anywhere that we're looking to get the current account, like here, I'm gonna get rid of this console log anywhere we're looking to get this current account. I'm going to wrap in an if current account. So if that exists, only run this. I'm gonna go to my next function that uses current account. And I'm also going to wrap that. If current account then only do this, do these things. I think those are the only two at the moment. What that does is when this loads and it comes here and it tries to get the renter or actually check if the renter exists and it calls render exists in current account isn't set yet in the throws that error. This time, it will check if that current account is set first. It won't be, so it'll skip this. And then down here in the US effect when it gets called, remember we passed it in here. So whenever this changes, it's going to call Hughes effect again. Whenever that happens, it's going to call this function again. And this time it's going to work. Now if we save it and go back and refresh, we don't get that error, we just get this. Something is not supported any longer. And react 18, which is not a big deal, I have to look into that. But we also have this favicon error, which we can fix by going to index.html and just taking out the favicon. I think I need to stop or restart my server for that to take effect. So let me refresh and that error is gone. So I think we're good to get started here. The first thing we're gonna do is populate this BNB credit. So this is air balance, the renters balance. So if we go back to our contract and scroll down, we have this function called balance of renter. That's what we're going to call that's going to check air balance or Air BnB credit that we've put on ERA account balance of Renner. Let's go back to blockchain contexts. And let's do const, get. A renter balance equals a sink. We're gonna do a try-catch in the error console dot log error. Then here we're just going to say const balance equals await. Use our contract object and call the balance of rent or function. We're going to pass in current account. And let's wrap this again in an if statement. If current account, then only do these things. And then we're going to set the state. So we're going to come up here and create a state for this. So we're gonna say const rent, rent or balance. Set. Renter balance equals use state. Here we're going to set the renter balance. Set renter balance to balance. Actually, we need to format this because it's going to return back way. So we need to format this as we did with their other balance that we did at the beginning. So to do that you put ethers dot utils, dot format ether. And we'll pass in balance. We need this to be called when the context is loaded. So we're going to add it to our user effect. We're going to call that and it's going to be setting the states. So we need to pass that state variable onto our provider. So we'll put renter balance. And now that should be available for us to use elsewhere. So then we need to go to our dashboard. Actually, current totals is where we need to go. Current totals. We need to bring in air contexts. So let's do const. Renter balance equals. Use context, blockchain, context. Awesome. Now make sure you import that at the top. So we should have Blockchain context and we should have used contexts important. That's available down here. Now in our stats card, we can change this static number to rent or balance. So let's save that. And let's refresh the page. And we have 0, which has to be right because we don't have a default value set. But to check that, let's go ahead and get this credit your account form working so that we can go ahead and credit our account and make sure that it changes this value up here according to how much we have on the smart contract. So let's jump over to the Add to balanced form. Actually, we need to start out in the blockchain contexts. Let's come here to the bottom. And we're going to call, if we look in our smart contract, we're going to call the deposit function. See if we can find that deposit. Here it is. We're going to call this deposit function. We pass in our wallet address in its payable. The fact that it's payable means that we can also send it an amount of ether or B&B or whatever we're sending in that'll be sent in an object, which I'll show you in a minute. So we have deposit, it's also payable and it's going to add this to the smart contract, but credit the renters account that is at this wallet address. So let's call this deposit function. Let's come back to blockchain context. And I'm just going to copy this function. And I'm going to call it deposit. And I can remove this if let's just remove this Totally. So think about this. Now we're entering a decimal and we want to convert it to weigh or ten to the 1800s. Because in our smart contract, we want to be dealing with way not decimals because solidity doesn't yet support decimals. So we need to convert this the other way. So we've been using Format ether to convert it from way to decimals. Now we need to use a utility function to convert from decimals to weigh. That function is called parse ether. So here we're going to get when I say const B&B value. So the amount that we're going to be passing in. And actually let's put this as a parameter. Value. So B&B value equals ethers dot utils. We're going to format this value two way. So we need to call parse ether. And we'll pass in the value. Once we have that, then we can call our deposit function Const, deposit equals await. Contract dot inner function is called deposit. And we're going to pass in our wallet address, which is current account. And we don't need to wrap this in an if because this doesn't load on page load, it only looks for it when we click the button. So at that point it'll be well loaded. And then after current account, this is where we can pass in the value of how much we're sending to the contract. And I told you this was an object. So let's create a curly braces. And for the key will put value in. For the value, we'll put b and b value because we're passing in this amount here. And then there's this lovely method called weight, where when we're doing this transaction, we start the transaction and we want to wait till that transaction is finished before we move on to the next thing. So to do that, we just put await deposit, which is what we defined above dot weight. And that'll wait until the transaction is finished. Then we want to refresh the balance, the renters balance. So once we credit the account, we want to refresh that number on the page. And to do that, it's pretty easy. We just call get renter balance. Again. This deposit, this is not called when the page loads. It's only called when we submit that form. So let's go down here and send that function to air provider deposit. And then let's jump over to our Add to balanced form. In here, we're gonna go to the onsubmit and values is what we're getting. Let's check out and see again what this submits. So hit Save. Let's see what this log to the console looks like, the test and it's being a little slow. There we go. So if I put 0.1 and submit it, It's going to submit an object with a key of credit balance and a value of 0.1, we don't need this credit balance, we just want the number only. So we're going to D structure that out by going const credit, credit balance equals values. Then we can call await deposit warps. What was that? Await deposit, credit balance. And that should be all we need to do. So let's save that and give it a shot. I always like to refresh my page just to make sure I'm starting fresh. So before you do this, make sure you have some tests B&B in your account. So if I open mine, I have 1.96. If you don't have any, just go to B and B test faucet in Google. Click on the test net.finance.org, then send yourself a B&B. You can send yourself one B&B per day. In here you just put in your wallet address. Click give me BNB and click on the one BNB and it'll send it to you in like five-minutes. It's really cool. But I've already gotten my end for today so I can't send anymore. So I'm going to credit my account with 0.1 B&B. So if I click Submit, we have an error. Deposit is not defined. That's in our ad to balance form is probably because we didn't bring it in. Yeah, we can't call deposit because we haven't brought in our context. So come back up to the top. Deposit equals use contexts. And I'm going to pass in blockchain context and make sure you import these two. Mine does it automatically? I've told you that a million times, but I'm just trying to remind you. So now let's try it again. Refresh the page. And I'm going to credit my balanced with 0.1 B&B. Click submit, and I'll wait for MetaMask. Alright, so my total, so it's a very small gas v, That's why I like BNB. It's 0.0043 B&B. And tack that onto my 0.01. It's very little gas. So let's confirm it. When we do that, it's going to wait. Remember we call that weight method, it's going to wait. And then when that's done, it should refresh Airbnb credit. So click Confirm will watch it here. It's currently cubed. Now it's pending. In our spinner spinning because of that React hook form, built-in hook, I think it's called is submitting, but you'll see now that our B&B credit is 0.01 or 0.1 B&B price. Let's see how much that is. 0.1. B&b is 38 bucks. Great. I liked that balance. That's working. Now let's go to B and B do populate that. So let's go back to blockchain context. And I'm going to copy and paste this down to the next one. If we look in our contract, we have a function called get du. So that's what we're going to call get do. We're not passing anything. And then I'm going to remove this rapid in an if current account. Then we'll do this kannst du equals await contract dot get, do current account. And then we're going to set the state. This is gonna be kind of a recurring pattern for the next few functions. So I'll come up here and create a state variable called do, and then set du equals U state. So I can come down here and do set, do, and I'll set it to the due amount we defined right above that. So don't mistake this do with the state variable do. And we want to call this get do when the contexts loads. So get du. And then that's going to set the due state variables. So we want to pass that to our providers so we can use it in our dashboard. So just pass and do save that, go to your dashboard, not dashboard current totals. And then pass in, do here. So we're going to pass in due to our context. And then on the second one where it's 0.01, we're just going to pass in due and save it and see if that gives us an amount una through us a big error. And it says objects are not valid as a React child, what that means is it's returning a big number, which is an object. So we actually need to parse it, forgot about that. So instead of, instead of do, we need to put ethers, dot utils, dot format ether. Do, and that should fix it. That's gonna give us our decimal amount. And it's already there. Looked at 0, refresh again, 0, cool. And we'll test that in a minute. Let's go ahead and get a ride minutes setup. So what about ride minutes? Where's that at in our contract? So if we go back to our contract, we have this function called get total duration. So we're going to call this, it returns 0 if they haven't checked in their bike yet or they haven't checked it out. L said returns the amount of time they were on the bike. So if they have a start and an end time, it's going to calculate it here. So we need to call this get total duration. So again, I'm going to copy this and paste it in. I'm actually going to call this get total duration. And we're gonna leave this if statement. And we're gonna do the exact same thing here. We're going to say const total duration equals await contract dot get total duration, which is a function in our contract like we just saw. And then pass in the current account. And then we're going to set the state. So let's come up here. And right under this just put const, duration, set the duration equals use state. And come back down here and let's set it. Set duration to total duration. And this is actually gonna be a string. We want to cast it to a number. So let's save that. And we also want to get that when the page loads because it's on a dashboard. So we come down to use Effect, get total duration in that setting the duration. So let's pass the duration state value to their provider. And then just like we did before, let's jump over to current totals and add it here, duration to bring it in. And then down here under ride minutes instead of seven, we're going to put duration. Save it. Refresh my page, and we have Ryan minutes of 0. Now let's set this bike status. So the way I had it set up was this is going to stay red until you check the bike out. If the if the bike is actively checked out, it's going to change to green. Like Hey, you're good to go, enjoy your bike. Once your bike is checked in, your back to red. Red means when your bike is checked back in, you can't check another one out until you pay your balance. Now you may want to distinguish between when they do pay the balance in, when they check the bike out again. You can do that if you want. I'm going to leave it red just for simplicity. So to do that, we need to come down here and see, yeah, we're setting this background color to red. What we wanna do is we want to find out if they're active or not. If they're active than we want to set it to green otherwise read. So let's go back. I think we have that already in air. We have error. Add renter. No, not we have somewhere here. Get renter here it is. We check if renter exists, if they do, we call get renter in populate that renters state variable C where it says Set renter. So we should be able to come down here and just pass the renter amount. So renter and that should give us remember when we add a renter, it gives us the wallet address, FirstName, LastName can rent active balance, all of that good stuff. So we should have that available. So it should just be as easy as passing the renter information, coming to our current totals and adding renter to our contexts. And then instead of red here, we'll say renter dot active. If that's true, then we want to change this to green. Otherwise, red. Save it. Let's test it out. So we've got a big error here. It says cannot read properties of undefined. And what that usually means is that it hadn't populated yet. So it's checking it this state variable before it's populated. So what we can do is also put a check in for renter to make sure that renter is available also. So renter and renter is active in then only green else read. So if we save that, We should be good. Refresh bike status is red. Now when we check it out, this should turn to green. Next, we need to get this form working so that we can pay the amount due. Once we do that and add our bikes will test that all this works. So let's do that one next. So back to blockchain contexts. And I'm going to again copy this, paste it below it. And I'm going to call this make payment. And we're going to pass in a value. Because remember this is payable. We're gonna be sending an amount with this. And let's take a look at the function in our contract. So somewhere it should be where we're making our payment. Here, make payment. So here's our payment function. Remember it subtracts it from our balance, so it makes a payment to the contract and subtract that amount from our balanced it sets can rent back to true because now you can rent a bike again. It sets due to 0 and start and end back to zeros. So it kind of makes your payment and it refreshes you as you were at the beginning. So we're gonna come over here and we'll just call the function make payment. And inside this current account. And we don't need the current account because again, it only runs when we press the button. So I'm going to do kind of like I did up here. I'm going to copy this much. Actually, I'll just copy all of it. Paste it. And so B&B value, this is the value that I'm sending. And then I'm going to call deposit because we're depositing money, we're making a payment. But instead of calling the deposit function, we'll call the make payment function. We'll pass in our wallet address and the amount that we're sending, we'll wait until that's done. Then we need to do several things here. So remember in our contract function, we're doing a bunch of things. We're subtracting from our balance. We're switching can rent back to true in all of these two zeros. So we need to refresh a couple of things. Right, under this, we're going to call a weight get renter. Because we need to refresh our renter. They have new values now, the can rent the balance. All of that is refreshed. So we need to refresh the renter. We need to refresh the get rent or balance. Need to refresh that because our balance is going to change. We need to refresh the duration because we had a riot of ten minutes. We need that to go back to 0, so we need to refresh that. So await, get total duration. And then finally we need to refresh the amount due. So await, get do, because that's also going to be 0. And this only runs when we press a button. So we're going to pass the function to the provider. And then we're going to go to the pay form. And bring in our context. Canst, make payment equals use context. In our context is the blockchain contexts. So again, be sure to import both of these then in air on our summit. So let's try our Submit first, see if it works. So pay your dues 0.1 submit, and there it is. So again, we want to structure this to just get the 0.1. To do that, we'll say const payment. I think that's what we use down here. Yeah, Payment D equals values and then we can call await, make payment. Payment, payment. Let me save it and we could try it out, but we don't have any Mountain Dew. So let's also jumped down to our bikes and make those buttons work. So back in the blockchain context, let's add two functions. One is going to be called checkout, const, check out equals a sink. And the other one's going to be called check-in. So we're going to check out the bike. We're going to check back in the bike. And we'll do a try catch. Console.log the error. In here. We'll say if current account make that check, then only run this will make that check. If that's true, only run this. So we'll start out with const checkout equals await contract dot. And let's see what we got. So we have a checkout and we have a check-in. And you'll note on the checkout, we probably want to refresh the renter because they're going to have new values. And then on the check-in, there's a lot going on. We're changing some renter values, but we're also setting the amount due. So we're calculating how much is due and we're going to set that. We need to refresh these values. So contracts, dot, check out, current account. We're going to wait for the transaction to finish, checkout dot weight. And then we're going to call get renter to refresh that. In down here. I'm going to actually copy this, paste it in. Here. We'll say check in, contract dot check in. Then we're going to await the check-in. Then we're going to call get renter. We're going to call get due to refresh that value and get total duration because we need to set that back to 0. In these, like the other ones are buttons you press. So we're going to pass the actual functions to our provider. And I actually don't need this if current account because it's a button press, it's not going to happen on page load. So let's move these back and save it. And I'm going to pass the checkout and and check in to my provider. And then we're gonna go to dashboard bike. Now it's going to be bike. There we go. So let's bring in the context to our bike component. So const, check out, check n equals, use contexts, blockchain contexts, bringing your imports. And I'm gonna save it. Now there's one thing we should talk about. One thing you can do with your contract is when you check out this bike, you can have it saved the name to your contract or in your state or something like that. So you could display up here the type of bike also that you checked out. I didn't want to make this too complicated and I wanted to leave some things for you to be creative and make your own app out of it. But all of these checkout and check-ins are gonna do the same thing. So if I check out this bike, it's the same as checking out this bike. We don t have to differentiate which bike we're checking out. So it's gonna be the same and each one of these bike components. For the checkout, I'm going to add an on-click. Equals checkout. And for this button, the check-in button, I'll add an on-click saying check-in, calling my check-in function. And then we save that. And I think we're good for those. We can actually try it out. So refresh my page. And I'm going to try to check a bike out. Now there's a lot of stuff that's going to happen here that we can test. So first off, I'm going to check out this bike. Alright. And it's charges me a very miniscule gas fee. B&b price. Let's see how much that actually is. It's like 27, gas v is $0.20. Glad we use to BnB, even though it's testimony. So let me go back to MetaMask. Let me confirm it. So what's going to happen here is when I confirm it, this status should turn green. And it should set a bunch of things that we said in our contract like, can rent should be false, Air start time should be documented, there should be a timestamp for that and all of that, you know, the contract just as well as me, you know, what's going to happen. So I can click Confirm. Now it's pending. Once that pending is done, this should turn green, so watch out for that. That is done. And we are green. Look at that. Or bike is checked out. And what we wanna do now is wait about six minutes, something over five minutes, and then we'll check it back in and see that everything happens properly. So it's 1157 here. So I'm going to come back at like 1203 and we'll check back in at that time. We should have Ride minutes of like six minutes. We should have an amount of B&B. Do remember 0.05 every five-minutes. And from there we should be able to pay or do pay that down to 0 and have our B&B credit reflect the difference. So I'll see you back in about five minutes. Alright, so it's almost time to check my bike back end. Before I do that, I'm going to check my state variables just to see that things changed properly. So go to components. You'll see that can rent is actually false now because it's checked out, so that worked fine. And then true, active is true. Those worked out great. And everything's working properly. Alright, so it's been about 78 minutes. So what we're gonna do is check the bike back in. When we do this and this transaction finishes, I should have my bike status should go to read my ride minutes should be populated with how long I was on the bike in my B&B do should be populated as well. So let's try that. So I'm gonna click check-in and confirm it in MetaMask. And let's check that status. So that's pending. When this is done, we should have values populated. Alright, great. So bike status went back to red. I was out seven minutes in my B&B do is 0.005, which is right. If I was 12 minutes, I would have 0.01. Do remember it's 0.005 every five-minutes. So great. So the final test here is can I pay the amount due and have it reset this and deduct it from my B&B credit. Our state right now is can rent is still false because I haven't paid my dues. And active is false because I'm no longer active on the bike. So let's put in mount do 0.005 and let's try to pay it. So submit and we are making a payment of 0.005 and then gas fees. So hit Confirm and this is going to be pending, but once this is done, my ride men, it should be at 0. My B&B do should be a 0 and my credit should be deducted the amount I paid. It just went through Reimann, it's 0. B&b do is nothing. And B&B credit is this much. So 0.01 minus 0.05 is 0.095. So I still have some credit. I can still check out another bike in our app is working wonderfully. So in the next video, we're gonna do a little clean up and we're going to add a couple of security features that we didn't add from the outset. Once that's done or Apple be finished. You'll be able to show off all of your work. I'll see you in the next video. 9. Optimizing UI and Security Checks: In this video, we're gonna be putting the finishing touches on our application. In wrapping things up, we're going to start out by displaying these require messages on our front end. So if you remember, in our smart contract we have these require statements that if they're not true, then we spit out this message. We need to display them on the front end. So we're going to work on that. Then after that, we're going to implement some security features so that renters can't interfere with other renters information and also some owners stuff that's really important. So push through this lesson because there's gonna be a lot of fun. And as always before we get started on those, we need to fix a couple of bugs. We're going to fix a simple one upfront and another one later on in the video. In the first one goes like this. So if you open up your blockchain context, and you might have noticed this already. If you open up your blockchain context and save it, then this dashboard changes to the ad renters form, which means we're losing our state somehow. So if you go to blockchain context and save it, you'll see that, hey, now we have the add renters form. If you go to your dashboard and just do a console.log, renter exists, you'll see the problem. So save that. And I'm going to refresh the page. And I'm going to save my blockchain context. As soon as you do that, you see over here in the console it says Hot updated, which means Vijay S is Hot Reload happened and then that value is undefined. You see right above it is true. But as soon as this reload happen, it's undefined. Now I've tried to find a good solution for this, and I'm convinced it just has to be some byte JS bug or some issue with Vijay S I just don't know about, but I have an easy fix for us, one that won't impact us much at all. It has to do with a plugin that Vijay S uses. So if you go in the root folder and go to vite dot config dot js. There's this plugin react plugin. So we're importing it up here and we're using it here with React. Now inside of this, we just need to disable the faster refresh. And you do it by writing this an object of key, fast refresh, value false. So we're disabling the fast refresh. If we save that and now go and refresh this page, actually refreshed anyway. You shouldn't have that problem anymore. So I'm gonna go to blockchain context, context, and I'm going to save it here. And I'm going to save it in my page, just refreshes without losing the state. So that's a simple fix. Add that in your config file and we can move forward. Now, just a word of caution if you're making UI changes and want to see them instantly, I think you'll need to re-enable that, but we're currently done with UI changes. So you don't need to worry about this, but just wanted to note it. Again. If you find a solution, please let me know. Or if I find one in the meantime, I'll paste it below this video. Alright, so first, like I said, we want to add these error messages when we have errors. So if we go back to our contract, you remember we have these require statements that say things like You do not have anything to it this time, you do not have enough funds to cover payment, things like that. So if the user tries to do something that they're not allowed to do, than it should pop up an error message. So for instance, if I tried to pay, might do when I don't have anything due. So 0.1 and submit it, I get this error over here in the console. Here it is this object. So it says code message, data stack. All this good stuff. So if we open that up, you'll see we have this data object. And if we open that up, there's a message in there that says execution reverted. You do not have anything due at this time. That's what we want to pull out in display on the page. So to do that, we just need to grab those specific values. So if I go to make payment, which is what we're calling right now, in my blockchain contexts. In instead of console.log error, we're going to say Error dot data. Remember that was the object dot message. So save that and let's try it again. Let me refresh 0.1 and submit, and I should just see the message here it is. Execution reverted. You do not have anything due at this time. So now we just need to display it on the page. Well, one of my favorite packages and react is toast defy. Testify is used to alert the user on certain actions. And there's a million ways that it can display. It can slide in on the page. It can do all of this stuff, but we're just going to keep it simple. So if you go to testify, react there should be an NPM package yet react to testify. It's very easy to set up. You can see right here all the different messages you can use. You can do spinners. You can put icons on it. You have different colors, lots of options. So to install it just got a yarn and react to justify or NPM install. So stop your server, install it, and then start your server backup. In what we're gonna do is we're going to display it through the same context here, the blockchain contexts. Normally you would want to create a new context for this. Like a toaster phi context. Set that up and use that just to alert on messages and errors. But if I start doing that, then we're going to get another hour video of just setting up error messages. So we're gonna do it easy here. But if you were in a bigger project and you wanted to put more time into it, you of course one would want to use a separate context. So if we look at our documentation for React testify, I'm going to click on the demo and the documentation. And you'll see here, we'll just check out positioning toast. Actually, let's go to the next one because that's not very helpful. But what you need to do here is you need to put this toast container on the, on the page you want to display it. And then you can call the toast function. So you can see that better here. So Toast dot success, and then you have your notification, whatever you want to say, and then you pick your position on the page to display it. You can do a toast to access an error, a warrant and info, or some kind of custom toast. So we're going to start out by putting this toast container. Well actually that's imported. We're going to put this on the current totals page because we have the two forms there. The one where we credit our account in, the one where we make a payment. So go to current totals. Then at the top, you want to just put this import statement, import toast container. Then I'm going to grab this example. And I'm going to scroll down and then at the bottom. So here's my current totals function down at the bottom under the box, so that I don't have any kind of styling with it. I'm going to just put that toes container auto close is set to eight seconds. I'm gonna change it to, let's do 3 thousand for three seconds. And then we have multiple parents here. So we need to put an empty tag. One at the top, one at the bottom. My toast container is on that page. So when it's called, it should display on that page. Now I'm gonna go back to the blockchain contexts, and I'm going to call it here with that toast dot error call. So I'm going back to positioning and toast dot error. So I'm going to take out this console dot log message and just replace it with this toast dot error, which again you'll find on the positioning toast part of this page. Then for my error notification, I'm going to put error dot data, dot message. And I wanted to come in in the top right. So let's save that. Now there's one more thing you have to do. You have to import the CSS or it won't look proper or even work properly. So just go up to getting started installation. And they don't mention it here with the installation, but you'll see it imported here. So copy that. And we want to import that on air current totals page because that's where we're displaying that toast container. So up at the top, bring that in, in, save it. And let's try this out. So I'm going to refresh the page just because I like to do that. Now I'll put just the number one and submit. And let's see if we get a toast message. We don't, because toast is not defined. So let's go back to our example and make sure we grab import toast from reactors to fire. Back in air blockchain context, put that at the top. Import toast. We can remove toast container because we're not using that here. We're just using toes because we're calling toast error. So save that and let's try it again. So refresh. Alright, and I'm going to put the number one and submit, and you should see something pop in at the top right. There it is. Execution reverted. You do not have anything due at this time. It looks like at hung up there for a second, but it's supposed to go away in three seconds. But that's great. So somebody comes in and submits it will let them know you do not have anything to do with this time. Let's add one to our credit form. So get du will put the same thing there. You can customize these however you want. There's a million ways to do it. You go to this. Where's it at reactors defy Demo. There's like all kind of things you can look at info success warning error. But yeah, you can select which one you want to see. And then click Show Toast, and it'll show you what it looks like. Different themes. Here's the dark theme and the color theme. Pretty cool if you're using, if you're using promises, you can say promises pending and then promise resolved. Lots of great stuff. So I'm going to grab this and add it to the crediting form. So the deposit. And I'm gonna save that and actually that won't error. I don't know if we have any thing for the pie. We don't have anything for deposit. But let's find something else. Make payment, get renter, check in, Let's do check-in and check-out because those both have require statements. Let's go back. So I'm going to remove that from deposit. It will go to the check-in and check-out and add it there. Awesome. So if I tried to check in a bike that I don't have, I think I'll get an error. Let me confirm that. Check in. Please check out a bike first. Yeah, let's see if we get something there. So I'm going to choose actually let me refresh just to habit of mine and go to check in. And there it is. Please check out a bike first. Awesome. So we have messages and feel free to tweak that however you want to put it on a different side, add some different colors, do a dark theme, whatever. So I think that covers air require statements. We got checkout, we've got to check in acquire require, we got to make payment. And that's it. So that's react to justify have added. Now the next thing we wanna do is add some security features to air Smart Contract. So theoretically if I have someone else's public wallet address and can insert that in some of these functionalities. Then I can check out a bike for someone else in charge, money to someone else's account. I can do things to other people's account. There's no check to say, hey, you can only interact with your address. And I don't think in general anything on the front end you can do that like I don't think I can come here and click checkout and add someone else's wallet address. But still you want to put those checks there. And I think it's good to go through it just so you see that if you go to the bike chain contract, let me give you an example. If I go to checkout and I know someone else's wallet address, I can put their address in and check out a bike and then I can leave it running for a week and then check it back in. And then they had this huge balanced did they had no part in running up? So we would just want to put a check that says, hey, you can only perform these actions on your particular account. And it's really easy to do. We just insert a modifier. So right under Add renter, I'm going to say modifier. Whoops. I'm gonna say modifier is renter. And then I'm going to pass in an address while at address. And then you put these brackets and you say require message dot sender equals wallet address in it. That's not true. You will say you can only manage your account. Then right under that, you have this underscore semicolon. And what that means is continue on with the rest of the function. So how this works is down here. For this checkout function, you would add right here is renter. This is a modifier and you would pass in the while at address. In this is a way of a clean way of adding a repeatable require statement two functions. So when this function is ran, it's going to check first, if this is renter, it's going to pass in this wallet address and it's going to say, does the message sender, the person making this call, match the wallet address, meaning they can only modify their own account. So when you create a modifier, you just tack it on to the function. And I'll show you how that works in a minute when we throw it in remix. But we need to add that to everything that we're adding a wallet address too. So I'm going to put it down here on check in. You can only check in a bike with your address. No one else's rent or timespan is internal. We don't have to worry about that. Get total duration. You only want to get your own duration. And since this one returns something, we're going to put this right after the public. And then this one also returns something and it's public. But this is the get the contract balance. We only want the owner to do this and we're going to deal with this next. But get renters balance, you can only get your own balance. Put that after public set due amount. This is internal, No problem. Call it outside of the contract, can rent a bike, put it there, deposit. You can only deposit via your own address, even though people would like you to deposit to theirs. Make payment. Tack that on the end. Get do put it there. Get renter. You can only get your own information. And renter exists, put it there too. So all this is doing again, instead of putting a require statement repeatedly in every single one of these, we're just putting this modifier in this function statement right here before the curly braces, we're just adding this modifier. You're modifying the function to meet these requirements. Alright, so that's the renter modifier. Now we have two more things and we'll be all done. First, we have to fix a bug. In second, we need to talk about the owner. The owner should be able to see how much money is actually his or hers. And they should be able to withdraw gains that they've made from these transactions. So let's fix the bug first. Now you recall we talked about the logistics behind the smart contract. If someone deposits money, it goes to the smart contract, but it credits their account. So if somebody puts in $10 in there, the only person that's put money in, they put in $10. There's $10 in the Smart Contract, but all ten of that is credited to their account. Now, they spend $5 on a bike and make a payment, then there's still $10 on the contract, but only five of that is credited with them. Well, we made a mistake with make payment. When we make a payment, we're actually just subtracting that amount from the balance. We're not actually sending money to the contract. We're just subtracting it from the balance in the money that's left over is the owners money. So we can't do payable here and we can't use message dot value. In fact, we actually in the blockchain contexts, when we make a payment, we are sending money, this BNB value. So that's a mistake. We shouldn't do that. We should just be subtracting from the credit. In the smart contract, there's a couple of tweaks we need to make. First, take out payable because there's no longer a payable function. Second, Let's put a second, Let's put a U and amount. So we're going to send an amount. When we make a payment, we need to send an amount that's actually going to be deducted from our balance. So we've got an amount here. And then we're going to change this message dot value to amount because we're not actually sending money, we're just deducting from our balance. And that should be all. So when we run make payment, we're going to test this in a minute. We're going to send an amount and that amount is going to be deducted from our balance. Then because we removed the payable factor in added a uint8 amount parameter, we need to update our blockchain context function here and make payment. We're passing in this value object, which is how you deal with a payable function. That's how we pass an amount to a payable function. The only difference because we're bringing in the amount now as a uint8 and not that payable amount, we just need to replace this object with B&B value as the second parameter or the second argument. So be sure you update that in the blockchain context and then jump back over to your contract. Now that segue is perfectly into the owner. The owner, if somebody has $10 and they pay $5 in their account, they have $5 leftover in the other five actually belongs to the owner. So we need to allow the owner of the contract who's going to basically be running the bike store to check their balance. Like how much is their profits? How much of the, all of the money in the smart contract, how much of that is dares, based on people running up bills and making payments and recreating their account and all of that. So there's a couple of ways we can do this. I thought about. So we use mappings. You can't loop through a mapping. I thought about maybe when we add a renter to create an array and just have an array of addresses that we can loop through. But we really don't want to loop through stuff because we might end up having hundreds, maybe thousands of renters and that's gonna be monstrous gas fees. If we got to loop through 11000 renters, I think the best way to address this is to create a new variable called uint8, owner balance. So we have owner balance. And if you think about it, the only time money will go into the owner's balance is when people make payments. Again, if I have $10 on the smart contract and all ten of that is mine and I make a $5 payment, then my balance goes down to five and the other five belongs to the owner. So that's really the only time that we need to be adding to the owner balance. So down here where we make payment, we're just going to add one more thing under this. It's gonna be. Owner balance plus equals amount. So that's gonna be credited to this owner balance. And then backup here where we have the balance of, we want this only to be called by the owner. So let's create another modifier, modifier, only owner. And we don't have any parameters there. And we can require that message dot sender equals owner. Because that's a wallet address. And you are not allowed access to access this. And then we'll do our underscore semicolon to run the rest of the function. And we'll use only owner on air balance of right here on the owner. If we want to add two more owner related functions, one to get his balanced or her balance function, get owner balance. And we'll do view public and let's make it only owner and returns a uint8. And here we're just going to return owner balance. And then we want to do one more function for the owner to withdraw the money. Now you might be like, Man, that's, that's risky because the owner can just rip everybody's money out and run with it. But that's not true because the owner balance is only the money in the account that's not credited to people. So let's do function. Withdrawal, owner balance. This is gonna be payable and public. And we're going to say owner dot transfer, owner balance. Now you see that we have this error here. And it says Send and transfer are only available for objects of type address payable not address. Now we can fix this by just casting this owner S payable. Then finally, we need to set the owner balance back to 0 because we're transferring out that owner balance, which is set up at the top. You went owner balance. We're transferring that amount out to our wallet. Now we need to set that back to 0. So owner balance equals 0. And with that, I think we're done. So select this whole thing and copy it and we're going to paste it into remix so that we can test it out. I'm going to paste it here and compile it. And then make this bigger. Alright, so let's deploy the contract. And I'm gonna, I'm gonna deploy using the first account that's gonna be the owner. So click Deploy. Then let's add a renter. So I'm going to choose the second person. Copy and put it in that wallet address. Want to put the Travis test? Can rent is true. Activists false. Zeros, zeros, zeros 0. So we'll click Add renter. And I'm gonna go ahead and check out a bike for that renter. Bike is checked out. And now I'm gonna go to the third account. So it's gonna be the second renter going to copy that. Paste it here. And I'll put something like Tracy. And I'm going to go ahead and check out a bike. Well, I need to add them first. So make sure you've got the right address for that third person and add the renter. And then I'm going to check out a bike for that renter. Awesome. So we have timestamps, will be able to check it here in a minute. But let's go ahead while we're here and deposit some money. So I'm going to choose one ether and I'll choose the second renter. And they're going to deposit one ether to the smart contract. So right here where it says deposit, make sure this is one ether and then click deposit. Awesome. So they deposited one ether. If I check that renter here, you'll see that they have a start time, so the bikes checked out and they have a balance. Now what happens if I try to switch to the third the second renter here. And deposit using the first renters address, I should get an error. So click deposit. Here we go. You can only manage your account. So that is renter modifier is working. That's awesome. And that's the use case. So if I'm if I'm depositing money, but I'm doing it from a different wallet than my own into somebody else's account. That shouldn't be allowed. That works. So let's actually switch to the right person. So let's actually grab that person's address and deposit an ether as well. So I'm going to click deposit. And I didn't change the address, so make sure you change the address. So click deposit. Okay. So we have to renters with two bikes checked out in each. Renter has deposited money. So in a couple of more minutes, I'll come back and we'll check the bike back in and we'll finish things up. Alright, so before we check these backend, let's actually switch to the owner. And actually now actually before we check back in, check the bytes back in, Let's try to get the balance of the contract with one of the renters. So click balance of and you get an error. You are not allowed to access this. Get owner's balance. You are not allowed to access this. So now let's switch to the owner and see what that is. If we get the balance of we have we have one ether I thought I'd deposited another one. Let's check our renters and see. The first renter has won. The second renter doesn't have any, so I must not have clicked deposit for the other Enter. So let me do that real quick. Or maybe I deposited nothing and maybe I didn't select the 1 eighth. So let's put it in the other renter ending in dB. Make sure I choose that renter. And then put this ether to one and click deposit. An Alpha switch back to the owner. I can check the balance of that's to Eve. So let me actually put this over here to keep track. Contract has to leave. The owner's balance is 0. The owner has 0. Rent or one has, has, has one ether in orange are two, has one ether also. Okay, so that's where we're at and we're going to test this out. Let's check these bikes back in. So I'm going to choose this first render. I'm going to check them back in. Check in. And that renter now has an a Mountain Dew. Then I'm going to check the other render in. Check them in. And then they should have the same amount. Do awesome. In a GAN or balance. Again, let me go back to the owner. The balance should be the same and the owner's balance still should be 0. So let's see what happens when we make a payment. We make a payment the smart contract balance shouldn't change. It should just swap hands to the owner's balance. So this renter here, rent or two O's, this much five to however many zeros. So let's copy that and make that payment. So I'm going to grab this amount. They have five whatever, do however many zeros that is, we don't need to come up here and add that amount in way up here. Because now in the make payment function we accepted as a second argument. So I'm gonna put that and then the first argument was their wallet address. So let's go ahead and make the payment. So make payment and I can only manage my account. So let me switch to the right account. Here we go. I'm gonna go ahead and make the payment. And you see now than when I click renters, they have nothing to do. But they had that five to however many zeros deducted from their balance. Now that amount, that five, however many should now be part of the owner's balance. So let me switch back to the owner. Actually, let me make these changes here. So the balance now for rent or one is this much 995. They've had five whatever deducted from it. And if I switch over to the owner now, I should have that amount in my possession. So switched over to the owner. I'm gonna click balance of and it's the same, nothing changed. That's what we fixed because before we were adding to the balance and deducting from Eric count, which is wrong. So the balance of is still the same. Get owner's balance, Let's click that and there is that amount. So now the owner has this much. And if you add this much with rent or one, we get back to this one to however many zeros, so we know that it's working, everything is working great. And I think that's it. We test it is renter. We tested only owner and EHR contracts working fine. So now all we have to do is since they're smart contract changed, we have to actually redeploy it. So let's do that to get a fresh contract. That's very simple. Just go back to your application, stop your server, go out of your client folder into your contract folder. In before we redeploy, we actually have to compile that new contract. And in fact, let me copy it from here just to make sure I have the latest changes. So copy that into my contract, save it and we need to recompile in, refresh this artifacts folder with new bytecode ABIs, all of that good stuff. So just do NP x, hardhat, compile. Awesome compiled one Solidity file successfully. Now go to your artifacts folder, contracts by chain dots soul and choose bike chain dot json. First thing we wanna do is grab this entire ABI again From bracket two bracket, copy that and paste it in our config dot json in our client folder. Grab all of that, and paste that in. Then we need to update the contract address. So first we need to deploy it. So that's NP x hardhat run and then scripts slash sample script.js. And then for your network, choose test net to redeploy. So click Enter. When we do this, we have a brand new contract. In a brand new application. Basically. There it is bike chain deployed to this address. So copy that and paste it in your contract address. Save it and you're good. So cd dot dot cd client and then yarn run dev and we should have a new application. I'm gonna go to localhost 3 thousand and I'm actually going to disconnect my wallet from it to get a fresh start, to disconnect this account and refresh the page. Choose my bike and it says, Welcome, Please enter your first and last name. So let me connect my wallet first. Connect. Alright. Enter in my name to register as a renter. Travis test. Submit. Deploy that. Awesome. Let's credit the account with the 0.1 B&B. There it is. 0.1 just for kicks. Let's try to check in a bike that we never checked out and we get this warning up here. Please check out a bike first. That's still working. Now let's check out a bike and confirm. And once that's done, we should turn green here because their bikes checked out. Still pending. There it is. We're green. So it looks like our app is working great. We have our dashboard in order. We now have checks so that people can only modify their own accounts. And we have messages popping up to display errors that we get from require statements. And that's all I have for you. I hope you enjoyed this course a lot. If you're looking for some more things to do here, one thing that would be fun is to put a navigation item up here, like a menu item that says admin, that pops up if the owner logs in. Like I thought about doing this, but I don't want to keep the course going and going and going. You've already come a long way. But if let's say since I am the owner, I deploy this contract address, I'm the owner. And we already have the functions in place on a smart contract. So you can put a or you may want to add a function called is owner. And then you can check like if that person is the owner. If so, put an admin menu item up here and when you click on it, there'll be two forms. One where you can click and check your balance into, one where you can withdraw the balance and you should know a 100 per cent how to do that because we did it here and we did it here. And in the smart contract that's already in place, we've already built the function. We just refresh the contract and redeployed it, so it's there. So that's my challenge to you. That'll be a lot of fun to follow up on. But at this point we have a fully functional app. We've done a lot of work. You should congratulate yourself. Feel free to tweak this to make it cleaner. Add some more features to it, some better CSS, whatever you feel like doing, push it to GitHub and show it to the world. Again. Thanks for picking this course up and following along with me as I pieced this thing together. If you enjoyed it, consider leaving a review or shooting me a message, telling me if if you liked it or if you have anything, you would like to see done better in the future. I'd love to hear it. So again, thank you for going through this course with me. Now talk to you later. 10. Owner Bonus Features: So here's a bonus project for you. What we're gonna do is create a dashboard for the owner. The owner would be able to view the contract balance, their balance, the owner balance, and would be able to withdraw the owner balance. So it looks like this. I'm logged in as not the owner. And if I go to dash admin, I'm gonna get a page that says access denied. So what you wanna do is you want to create a route called slash admin. And if you're not the owner, you just see access denied. Now, if you are the owner, let me disconnect this. And I'm going to connect the owner account. Now, you should see a dashboard. So this page is just like the dashboard we have here. There's a title, there's some stat cards, and then there's a form. So it's the same thing here. So if I go back to admin, I have a title, it has some stat cards and then I have a form with no text fields is just a button. And what we'll do here is we'll have the owner balance, will have the full contract balance. And then when we withdraw, withdrawal this owner balance to our wallet. And since the owner balance is part of the entire contract balance, we should see this change to 0.18. So let's try that out. So it's processing. Alright, so I withdrew my 0.01 B&B in my contract balance is now 0.18. So that's your challenge. If you're kinda burnout from the project, you've been working hard at it and you're done and don't want to even deal with this, don't worry about it. It's bonus. But I think it's important if you can, to do it because one, an owner needs to get paid, right? He's building revenue from these bike rentals. He needs to be able to get paid for it. Second, this is a great opportunity for you to take all that you've learned in this course and do something without any assistance. So take all of these skills you've learned and try to do it yourself. Now, below this video, I've put a couple of steps to help you out. Like a couple of steps you should take to get this done. And then finally, I've posted a link to the branch on GitHub with these code changes that you can check out, but don't look at that until you're done. Try to attempt this. Anyway. I think you'll find it a lot of fun. So have at it.