How to Build Ethereum Dapp (Decentralized Application Development Tutorial)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Interesting, thanks

👍︎︎ 3 👤︎︎ u/Qubitica 📅︎︎ Apr 06 2018 🗫︎ replies

Fantastic channel

👍︎︎ 2 👤︎︎ u/NikoIay 📅︎︎ Apr 06 2018 🗫︎ replies

cool video! interesting info

👍︎︎ 2 👤︎︎ u/ElfinLuff 📅︎︎ Apr 08 2018 🗫︎ replies
Captions
hey everybody this is Gregory from DAP university and today I'm going to show you how to write your first decentralized application on the etherium network I'll show you how to write your first smart contract or will hold an election between two candidates and we will allow accounts connected to the network to vote in our election and we'll watch all the votes come in in real time as they happen we'll write tests against our smart contract to ensure that our code is robust and we'll deploy all the code in our smart contract to a local aetherium blockchain we'll also write a client-side application that will allow users connected to the network to interact with our smart contract and vote in the election but Before we jump into building our decentralized application or dab I want to take a step back and answer a few questions like what is a blockchain and how does a DAP work so if you're familiar with those things already feel free to skip ahead but if not let's examine some key concepts so what is a blockchain let's use an analogy to understand what a blockchain is let's look at a web application so normally when you interact with the web application use a browser and you talk to a central server of our network all of the code to your web application lives on this central server and all of the data lives in a centralized database and anytime you want to use your application you must talk to this central server and because this is how a web application works it's really bad to build a voting application this way here's why for one all of the data in your database could change at any time our vote could change or it can be deleted entirely number two all of the code in your application could change at any time and this means that the rules in the election could change so we don't want to build a centralized web application because of these problems we want to build a decent July's application on the blockchain we want to ensure that our vote is counted that all the votes are only kind of once and that the correct candidates with the most votes is actually going to win the election how does the blockchain solve these problems and why is it a better choice for building our voting application see on the blockchain all the data doesn't lie on a central server but instead the data is decentralized it's distributed across every device connected to the blockchain see the blockchain is a peer-to-peer network of nodes which talk to one another so if you're a device and you're connected to the blockchain you are a node and you talk to all the other nodes and you'll share some of the same responsibilities that a web server might assume for one you'll get a copy of all the data that's shared across the blockchain all this data is contained in bundles of Records called blocks which are chained together to create the public ledger and all the nodes on the network work together to ensure that all the data on the public ledger remain secure and unchanged and this is important for a voting application because it means that we'll always know that our account sent the transaction whenever we vote and that our vote will go to the correct candidate and be recorded forever and because all of the data is shared across devices on the blockchain the blockchain fundamentally is a database and because all of the nodes talk to one another on the blockchain it's also a network so instead of the traditional web model you can think of the blockchain as a network and a database all in one and it's much better to build our voting application on the blockchain in this decentralized way so that we can vote with confidence and that's how the blockchain works but what about the actual code of our decentralized application and why is it better to write this code for the blockchain and we said that all of the data on the etherium blockchain is decentralized and secured now likewise all of the code on the blockchain is shared and also unchangeable the etherium blockchain allows us to write code that we can deploy to the blockchain and nodes on the network will execute this code this is how we'll write the code that governs all the rules of our election all of this code will be secured and unchangeable and this is very important for a voting application because it means the rules of our election won't change how do we write the code of our decentralized application well with something called a smart contract the etherium allows us to write code that gets executed on the etherium virtual machine with smart contracts and this is where all the business logic and our application will lie this is where we'll write all the code it'll be in charge of reading and writing data transferring value and executing any business logic that we program a smart contract is kind of like a micro service that lives on the web if the public ledger represents the data layer of the blockchain then a smart contract represents a layer that reads and writes that data and does stuff with it and talks to other services also it's called a smart contract because it represents some kind of covenant or agreement in the case of our voting application it's an agreement that our votes going to count that all the votes are only gonna count once that they won't change and that the correct candidates going to win a smart contracts are written in the language called solidity which looks a lot like JavaScript and we'll be using solidity to write our smart contracts in this tutorial so just for clarification what is adapt well adapt is a decentralized application and it's decentralized in every way the network is decentralized because it's peer-to-peer the data is decentralized because it's shared across devices in the network and the code is decentralized because it's also shared and executed across devices in the network so let's take a quick look at the structure of the DEP that will be building in this tutorial first we'll have a client-side application written in HTML CSS in JavaScript and instead of connecting this to a back-end web server we will connect it to a local blockchain that we will install and we'll write all of a code to our decentralized application with a smart contract we'll compile our smart contract and deploy it to our local blockchain and we will allow accounts in the network to use our app and vote in the election so we've seen what a blockchain is and how it works we've seen what a DAP is and how adapt works and we've seen that we want to build our voting application in a decentralized way with a smart contract and we want to deploy this smart contract to our local blockchain and with that being said let's jump in and start programming let's take a quick look at the client-side application that we'll be building to interact with our smart contract this is the election results page where we will have a table of candidates and each candidate will have an ID each candidate will have a name and each candidate will have a vote count we'll be able to see the account that we're logged in with this is the account that is connected to the blockchain and we will have a forum where we can select which candidate we want to vote for and we can cast our vote in order to build our dap we're going to need a few dependencies first the first dependency that we need is node package manager or NPM and this comes bundled with nodejs you can see if you have node already installed by going to your terminal and typing node - B if you need to install node you can install it with a command line tool like homebrew or you can go to the node.js website and download it directly the next dependency is the truffle framework truffle is a framework that's going to allow us to create decentralized applications on the etherium network it's going to give us a suite of tools that allows us to write our smart contracts with the solidity programming language it also gives us a framework for testing our smart contracts and it gives us the set of tools to deploy our smart contracts to the blockchain we can also develop our client-side application inside of truffle you can install truffle by going to your terminal and typing NPM install - gee truffle the next dependency is ganache ganache is a local and memory block chain that we will use for development purposes you can install the ganache by going to the truffle framer website and downloading ganache directly the next dependency that we're going to need is the meta mask extension for google chrome now in order to use the blockchain we must connect to it remember I said the blockchain is a network we'll have to install a special browser extension in order to be able to use the etherium blockchain and that's where meta mask comes in we'll be able to connect to our local aetherium network with our personal account and interact with our smart contract by using meta mask since we're going to be using the meta mask extension for Chrome you'll also need to install the Google Chrome browser if you don't have it already to install meta mask you'll need to go to the Chrome Web Store and search for the meta mask plug-in you will add it to Chrome once you've installed meta mask you should to your Chrome extensions and ensure that meta mask is enabled you can also double check to see that it's working by going to your extensions bar and clicking on little fox now the last thing that we need is some syntax highlighting for the solidity programming language that we'll be using to write our smart contract most text editors and IDs don't have syntax highlighting for solidity yet so we'll need to install some I'm using sublime text and I've downloaded the etherium package from package control now that we have all of our dependencies installed let's go ahead and get everything set up so that we can start building our application so find wherever you downloaded ganache and open it once we have ganache started we have a local blockchain running and you can see that ganache gave us 10 accounts whenever it started and each of these accounts has a unique address and each account has been credited with 100 fake ether now this ether isn't actually worth anything on the real aetherium blockchain now these account addresses are unique identifiers that are going to represent the voters in our election now that we have our local blockchain running let's go ahead and set up our app the first thing that we want to do is create a project directory we want to go into that project directory now that we're inside of our project directory we want to actually set up our truffle project now the truffle framework gives us boxes which are just packages of boilerplate code that can be unboxed within our project to get us started faster we're going to be using the truffle petshop box this is a box that's published by truffle for their etherion pet shop tutorial we can unbox the pet shop package by going truffle unbox pet shop so let's go ahead and open up our project and take a look at what we generated if we examine our directory structure here we see that we have a contracts directory this is where our smart contracts will live and we already have a contract inside here called migrations dot soul and this is just a smart contract that's going to handle our migrations whenever we deploy all of our smart contracts to the blockchain and below that we have the migrations directory this is where all of our migration files will live whenever we deploy our smart contracts to the blockchain and if you come from another web development environment you might be familiar with the migrations directory when you have to create a migration to change your database this is the same thing in shuffle so we need a migration to deploy our smart contract the blockchain because when we do this we're actually creating a transaction on the blockchain we're changing its state just like we would change the state of a database and below that we have a node modules directory this is where all of our no dependencies will live we have a source directory this is where we will develop all of our client-side application and a test directory where we'll keep all of our test files also our package JSON where we will specify all of our dependencies and the truffle JS file that's basically going to be the main configuration file for our truffle project now that we've created the project structure for our DAP let's go ahead and start writing our first smart contract now our smart contract is where all the business logic inside of our app is going to live it's where we actually right all the code of our depth that's going to read and write with the etherium blotching it's where we're going to list all the candidates that will run in the election and it's where we're going to keep track of everyone who voted in the election it's also going to be where we write all the business rules that govern our election namely like the fact that the account can only vote one time in the election so let's go ahead and create a new file in our contracts directory called election Seoul now that we're inside of our contract file notice that the contract file name is capitalized the first thing that we need to do is declare their version of solidity that we will be using and we do that like this and the next thing that we will need to do is declare our contract now the first thing that we want to do is to create some kind of smoke test to ensure that we have everything set up properly we just want to make sure that we set up our contract correctly that it can be deployed and that it's going to respond to the kinds of things that we expect it to respond to so we're going to need a couple of things we're going to need a constructor we need something that's going to get run whenever we initialize our contract upon migration and what we're going to do inside this constructor is we're going to just set the value of a variable for now we're going to set the value of a candidate name and so we need to have a way to store this candidate name value and we need to have a way of reading it so let's go ahead and write our constructor we tell solidity that we are writing a constructor by defining a function with the same name as the contract now our constructor is going to get run whenever we deploy our contract to the blockchain and for that reason we need to declare a public so inside of our constructor we're going to just store the value of a candidate and we'll do this by setting the value of candidate equals candidate 1 this variable name right here without an underscore before it is going to represent a state variable and a state variable something that's going to be accessible inside of our contract and is going to represent data that belongs to our entire contract so we can create a way to actually store this value and read this value by declaring a state variable now what we've done here is we have declared a variable of string type and we have declared it public now what that's going to do is give us a state variable that can be stored as a string and when we have declared a public this state variable is going to be assigned a getter function so solidity is going to get it as something for free that allows us to just read the value of this variable instead of having to define some sort of reader function ourselves all right now that we've created a way to initialize our smart contract with the basic value let's see if we can actually interact with it in the console in order to do this we're going to need to create a migration to deploy our smart contract to a local blockchain so that we can actually interact with it in the console to do this we'll go to the migrations directory and see an initial migrations file will use this migration file as a reference point for creating our own migration to do this we'll need to create a new file in the same directory and we will need to prepend it with the number two we number all of our files in the migration directories so that truffle knows the order to run them in now that we've copied the code from our initial migrations file let's take a look at and examine its parts and see what we need to change for our own purposes first we'll see that migrations is referenced in three places we'll see that it's reading the migration contract out of the project directory its assigning it to a variable called migrations and it's referencing that variable here so we'll go ahead and change all those to election which is the name of the contract that we just created and let's see what it does so on the first line what we can see is that we have this artifacts right here this represents the contract abstraction that is specific to truffle and this will give us an election artifact that represents our smart contract and truffle will expose this so that we can interact with it in any case that we want to so in the console when we write tests or when we use it in our front-end application and we can see down here that we've added a directive to deploy our contract with this function now that we've created our migration file let's see if we can run the migration we'll do this by typing in truffle migrate all right now our contract was migrated and deployed to the blockchain so if you're depending on your truffle version you might see some warnings here these are just compilation warnings so not actually errors and these errors come from the migration project that came sorry the migration contract that came with our project and basically it's saying that some of the functions have not been they have not declared the visibility of these functions so you can address these errors by declaring the visibility of these functions like so or you can just ignore these warning for now and continue on alright now that our contract is deployed and our local blockchain is running let's try to open the truffle console and interact with our smart contract so we can open the truffle console by typing truffle console now let's get an instance of our smart contract so that we can see if our deployment worked and see if it responds to the types of things that we expect it to respond to now we do this like so election dot deployed then function and this is going to be the instance of our contract and we will assign the instance to an app variable all right now what did we just do so election here is the variable name that we defined inside of our migration file and we can get a copy of this deployed abstraction with this deployed function now because of the asynchronous nature of smart contract development developing them relies heavily upon the use of JavaScript promises if you're unfamiliar with JavaScript promises they're basically a way of handling the eventual result of an asynchronous operation in this case the deployed function is going to be an asynchronous operation and we need to rely upon promises because I can't just go I can't just call the employed function and expect the result to be assigned to our app variable this won't actually return our app instead it's going to return a promise and we have to call the then function on the promise that will get executed once the promise finishes and that promise will take a callback function where we can inject the instance of our application and assign the instance to an app variable that's how we'll actually get access to our app once it's deployed so now that we stored our app into a variable let's play around with it and see what it responds to so we can take our app and we can get the address and if you examine this address it looks a lot like the account addresses that we saw when we looked in ganache and we can also see that we can retrieve the value of the candidate that we stored when we defined the state variable candidate and set it when we initialize our contract see candidate 1 this was the value that we set in the constructor and we can verify that the constructor was run whenever we deployed our contract because that's where we set the value and note that this is a function not a variable and that's because we got this getter function for free from solidity by declaring this state variable public and we didn't actually have to define this function ourselves all right and there we have it that's our smoke test we can see that we've created the basic smart contract and that we've deployed it successfully and that we can interact with it in the console but before we go on and start building out the rest of our smart contract I want to show you something else that happened when we deployed it now if you open up ganache we can see that the balance of the first account and our list has changed by 0.5 either now let me explain why reads on the blockchain are free but writes on the blockchain cost gas now we'll talk about gas more in depth later in this tutorial but for now just know that whenever we deploy a contract to the blockchain it's going to cost aetherium and in our development environment ganache defaults to debiting that aetherium amount from the first account in the list really quick before we move on I realized that I've been using solidity aversion 0.4 dot 1:1 and let's change this to 0.4 dot 2 since that is the version of solidity that comes with this version of truffle now that we've come to a stopping point let's go ahead and commit our changes I'm going to put a link in the description of this video to the code up to this point in the tutorial so if you want to follow along and check out your code against what I have on my screen you can click that link in the description of this video if you download the project from that link just make sure that you run npm install to install all of your dependencies before trying to continue on with a tutorial and i'll also say that you can subscribe to the channel if you'd like to see more videos about developing decentralized applications on the etherium network let's go ahead and build out our smart contract to list all of the candidates that we want to vote for in the election when we created our smoke test we created a way to store a single candidate to our smart contract and we created a way to read this candidate when we declared this string variable public we got a candidate's function for free from solidity and we stored this single candidate to this variable whenever we initialize our contract with the constructor what we want to do now is create a way to store multiple candidates in our contract and we want the candidates to have more than just a name we want the candidates to keep track of how many votes that they've received and we'd also like to reference the candidates by ID let's clear out what we have so far and sketch out what we need to do that you so here are the things that we need we need a way to model a candidate we need a way to describe what I can that it looks like that it has a name that it has a vote count that it has an ID and we need a way to store the candidate that we've modelled and we need a way to fetch that candidate from storage and we also need to track how many candidates there are in storage and I'll explain why in a minute this is how we're going to model the candidate inside of our contract solidity allows us to create our own structure types and we're going to do that for our candidate here we can do this with the keyword struct followed by the name of our new type in this case candidate we can specify that this structure has an ID of an unsigned integer that it has a name of a string type and that it also has a vote count that is also an unsigned integer now just declaring this struct won't actually give us a candidate we would have to instantiate this struct and assign it to a variable before we can stick it in storage the next thing that we need is a place to store our candidates we need a place to save one of these structure types that we will instantiate I want to do this with a mapping a mapping in solidity is like an associative array or a hash where we associate key value pairs with one another we declare this mapping with a map and keyword and we pass in the types that we expect for each key and value pair in this case the key will be an unsigned integer and this will correspond to the candidates ID and the value will be a candidate structure type now this is the way that we will store our candidates and just like we saw earlier when we did our smoke tests we can declare this mapping public and solidity will generate a candidate's function for us that will allow us to fetch our candidates from this mapping one thing to note is that when we add a candidate to this mapping we are changing the state of our contract and writing to the blockchain this is our way that we will persist these candidates to storage and this will be interacting with the data layer of the blockchain and the last thing that we need is a way to keep track of how many candidates that we have created in our election and I'm going to do this with a counter cache now let me explain why in solidity there's no way to determine the size of this mapping and there's also no way to iterate over it either that's because in this mapping any key that we haven't set of value for will automatically return a default value in this case and empty candidate for example if we had two candidates in our election and we tried to look up candidate number 99 which doesn't exist the value returned a blank candidate and it will do that for any arbitrary value that we throw in there for which we have not stored a value and that makes it impossible to determine how big this mapping is and that's why we're going to use a counter cache here because we want to keep track of how many candidates there are so that we can fetch every possible candidate from the mapping and determine how many there are and we'll use this candidates count state variable to keep track of how many candidates exist in our mapping and we will increment it each time that we add a candidate to our candidates mapping and this is going to be very helpful when we want to access each candidate within our mapping inside of a loop for example if we wanted list all of the candidates and we know that our candidates count is five we can iterate over each integer one two three four five to access each candidate within the mapping inside of a loop the next thing that we need is a way to add a candidate to our mapping I'm going to do this with an add candidates function let me explain this code you see our we declare our function add candidate and this function takes one argument of a string type this is just going to be the candidates name and note that this is a local variable not a state variable and that's why we prepend it with an underscore and we will declare that this function is private and we make this a private function because we don't want this to be accessible to the public interface of our contract we don't want anyone else to be able to add a candidate to our mapping and add a candidate to the election we only want our contract to be able to do that because we're going to call this inside the constructor momentarily so what happens when we execute this function the first thing that we do is increment the candidates count and we do this with the increment operator now this is just going to add one to whatever value existed previously and they candidates count and the first time that we call this if the candidates count was zero which is the default for an unsigned integer it will be one and we do this at the very beginning of our function because we want candidates count to represent the ID of the candidate that we are creating within this function so let's create our candidate we create our candidate first by referencing the candidates mapping that we defined here and we pass it the key of the ID of candidate that we want to create and we're getting that from candidates account which we just incremented and we assign the value to that key as a new candidate which we're doing here so we will instantiate a candidate of the structure type that we created we will pass it an ID of an unsigned integer which is the candidates count that we increment this year we will pass it a name which is the string argument from our function and we will pass it an initial value of 0 for its vote count because it hasn't received any votes yet finally let's add all of the candidates that we want to exist in the election and we want our smart contract to be in control of this we don't want anyone else to add candidates to our election so we will call the add candidates function inside the constructor and this will get run whenever our contract is migrated and deployed all right so we have added candidates to our smart contract and our smart contract is going to be in charge of how many candidates exists this code is going to get run whenever this contract is initialized and deployed to the blockchain it will add a candidate we will keep track that there are two total candidates with our candidates count and we will store these candidates in our mapping with the key of an unsigned integer that will correspond to the candidates ID and the value will be this candidate structure that we defined this is our way of modeling the candidate it'll have an ID it'll have a name it'll have a vote count and we will get a function for accessing each candidate because we declared this mapping public with a candidate's function which will be payable to pass an integer that will be the candidates ID in order to fetch the specific candidate that we want to vote for now that we have our candidates added to our contract let's try to read them out of the console in order to do this we must ensure that our local blockchain is running we want to make sure that ganache is running and we also want to migrate our contract to pick up our code changes now in order to do this we must run truffle migrate - - reset here's why we need the reset flag remember that all the code and all of the data on the blockchain is immutable it's not supposed to change so whenever we change the code in our smart contract for development purposes we must push a new copy of our smart contract to the local blockchain to get our code changes when we do this we will lose all the state of our smart contract and we will also be assigned a new address for this reason migrations are really only intended to be run once and we must rerun all of our migrations from the beginning with this reset flag to pick up our changes this is a lot like dropping all the tables in your development database and starting from the beginning if you've ever had to do that kind of thing before so let's run our migrations alright and our contract is deployed now let's open the console first we will get a deployed instance of our contract and assign it to a variable let's try to inspect some candidates now we will use this candidates function that we got for free whenever we declared our candidates mapping public and this function isn't really designed to return the entire mapping for our candidates list and if I try to do that you'll see we get an error and the compiler is telling us that we have passed an invalid number of arguments to this function now really this function expects a key from this mapping in this case an unsigned integer and the reason is that this function is designed to reference an individual candidate out of this mapping so if we wanted to do that we could pass it a candidate ID of one to see the first candidate in our lists and we can see the values for that candidate here I can also do the same thing for candidate number two and let's see what happens if I pass some invalid values like 99 we can see that we have a default value return for our candidate structure and the ID is just going to default to zero and the name will be an empty string and the vote count will also be to zero and notice that these are just big numbers in JavaScript because this number can be potentially larger than a value that JavaScript can handle natively and that's one of the main reasons that we define our candidates counter cash is to avoid this problem we don't want to ever get a blank default value whenever we access a candidate we want to know at all times how many candidates exist within our mapping and we only want to reference the candidates from number one all the way up to the value of our counter cash in this case - now let's inspect one of the candidates in our election remember that the candidates function call is going to be asynchronous so I can't just assign a candidate value to the return I can't just assign a candidate variable to the return value of this function that's not going to work instead we have to assign it with a promise inside the callback function now returning the value of the candidate variable that we just assigned here now let's try to inspect the values of this candidate variable you'll see that we can't just call candidate ID that doesn't work and let me explain why so we define our candidate as a struct we modeled it that way we modeled with it to have an ID a name and a vote count but structs in solidity are really just syntactic sugar and the etherion virtual machine is not really aware of them so whenever we created this candidates function and our contract was compiled we got this function for free but the EVM doesn't really know how to build a struct whenever we return a candidate from this mapping so instead it's just going to return this set of values and we can access each attribute of our candidate from this set of values by zero-based index like this so if we want to access the candidates ID we must call the first value in this set of values and we can access the name and we can access the vote count and also take a note that if you wanted to convert the candidate ID to a number we just do that like this one and we'll do that same thing for a vote count oops and it's about count is zero all right so that's how we fetch a candidate from our mapping in the console and that's how we can read the values for each candidate now while we're here I wanted to make a mention about voters we've seen that we model our candidate with a struct in our smart contract and we keep a list of our candidates with this mapping so how do we represent voters well remember we want anyone who's connected to the blockchain to be able to vote in our election so voter is going to be modeled by an address of any account connected to the blockchain remember we can see all of these addresses in ganache it gave us 10 accounts for free but we can also have access to these accounts in our console and we do this with a library called web 3 will explain web 3 a little more in detail when we connect our clients that application but for now let's take a look so we have web 3 web 3 has an ETA job jekt oops and this eth object also gives us access to all the accounts that are connected to our network boom you can see these are all 10 accounts that are running in ganache and we can also reference these counts accounts individually now these accounts and the web 3 object are going to be important when we connect our client-side application and when we start voting in the console but for now I wanted to make a mention of them while we're here now that we've seen how our candidates work in the console let's write some tests to ensure that our contract was initialized the way we expect it to let's talk really quickly about why testing is so important when you're developing smart contracts we really want to ensure that our contracts are bug free for a couple reasons remember that all the code on the blockchain is immutable so if our contract has any bugs we must deploy a new copy of it and this new copy will not have the same state as our old contract and it won't have the same address the only thing that we can do with our old contract at that point is disable it and we want to avoid doing any of that if possible another reason is deploying our contract cost gas it triggers our right to the blockchain which costs us ether so we want to minimize the amount of ether we would ever have to pay and the last reason is if our contract contains any functions that right to the blockchain and these functions contain bugs the person who is trying to send this function is going to be wasting ether and it's not going to execute the way that they expect it to so that being said testing our contracts are very important to ensure that they are bug free before we deploy them all right in order to write our tests let's just make sure that we have ganache running and we do and next we will create a file to run our tests I'm going to create an election dot JS file in our test directory here there are a few ways of testing our smart contract we can write tests in solidity but this method is pretty new and we're not going to focus on that in this tutorial instead we're gonna write our tests in JavaScript to simulate client-side interactions with our contract kind of like we saw in the truck a console now truffle comes bundled with the mocha testing framework and the chai assertion library and both of these things are gonna give us everything that we need to write tests for our smart contract let's go ahead and sketch out our tests the first thing that we will do is require our smart contract and this will create an art and artifact that truffle will use to create an abstraction to interact with our contract and the next thing is to declare our contract now when we declare a contract this is going to inject all of the accounts that exists in our development environment and we can use this account for testing purposes the first thing that we will test for is that our contract was initialized with the correct number of candidates and I'm just gonna paste in some code that does that now let's take a look so it and contract for that matter these are all things that we get from the mocha testing framework and this assertion here is something that we get from chai which I showed you a second ago so let's step through this we provide a description that our contract was initialized with two candidates and we fetch an instance of our deployed contract much like we did in the console we get access to that instance here in this callback function and once we have that we're going to fetch our candidates count and this call is also asynchronous so we need to execute a promise chain and inject the value of this count here once we have injected that value we will use this assertion that the value is equal to two now let's save that and run this tests we can run our tests simply by typing truffle tests all right and it pasts tell you what let's change the value of this number here to ensure that our test is working the way we expect all right it failed because we change this number to three and we expect it to be two so it appears that our test is working all right the next thing that we want to test for is that our candidates were actually initialized with the correct values so here we just tested that there are two candidates and now we want to actually check that you know the name is correct and that their vote count is correct and that the ID is correct so I'm just going to paste in this test here and we'll step through it I'm also going to add this so let's take a look at what we got again I'm going to declare it and we're going to provide a description so it initializes the candidates with the correct values and we're going to pass us a function and we will get a copy of our deployed contract and here we're going to actually assign this to an election instance variable which I've declared here and we want this variable to have scope inside of this entire test and here's why we want to access our instance within this promise chain so if we were to try to reference it from this variable it wouldn't work I can't reference instance down here and for that reason we will store it inside of our test so once we have gotten our election instance we will call our candidates function that we got from our mapping and we will try to read the first candidate out of that mapping and again this call is asynchronous so we must use a promise chain with a callback function and pass the candidate in here once we have this candidate we will reference its values by index like we saw in the console and the first value will be the candidates ID we check that it's one the second ID will be its name we check that it is candidate 1 and the third value will be its vote count which is 0 because he has not received any votes yet and next we'll do the same thing for candidates who will call the function with the second candidate ID and check for the same values like so all right now let's run our tests and see the pass boom there we go so let's write some code that will allow us to list out the candidates on our client-side application in order to do this we're going to write some HTML and some JavaScript now one of the reasons that we started with the truffle petshop box when we started our project was to get a lot of boilerplate code for free I'll show you a couple of things that we got for free that will make writing our client-side application much easier the first is an index.html file and you'll see that this has some of the boilerplate code for the truffle pet shop tutorial and we're gonna blow away most of this code and replace it with the code that we will use for this tutorial it also gave us an app dot J's file which again has a lot of code for the truffle pet shop tutorial which we will clear out and we'll use our own code here and it also gave us the Twitter bootstrap templating framework if you're unfamiliar with Twitter bootstrap it basically provides us with a lot of nice-looking and interactive UI elements that we don't have to write ourselves it saves us from having to write a lot of CSS and JavaScript and in fact we won't have to write any CSS in this tutorial now you don't have to be a front-end expert in order to follow along with this part of the tutorial in fact I've tried to keep the HTML very basic and I've also tried to write very vanilla javascript in our app that J's file try to keep it very clear and as simple as possible in order to follow along and I also won't spend a ton of time on the HTML portion of the tutorial because I really want to focus on smart contract and how we interact with it so I'm going to just kind of paste in some template code here if you want a copy of that template code at this point in the tutorial you can click the link in the description below this video to download it alright so I'm going to paste in some template code for this point of the project so let's take a look at what it does first we'll have a title of election results next we'll have a loader template and remember that all of our function calls to our smart contract are asynchronous so we'll want to share the loader while we're making those calls and next we have a Content section and this content section will have a table where we will list our candidates out and it will also have a place to list the address of the current account that is connected to our application next let's look at our app dot JS file which you can see here so I've pasted it in the code for this point in the tutorial so you can see that our app is an object with several functions defined and we will initialize this app whenever the window loads so let's take a look at the code and step through to see what it does first we will initialize our app and when we do this we will initialize web 3 once we initialize we have 3 we will initialize our contract and once our contract is initialized we will render out the content of our application on the page so let's step through each of those functions and see what they do from a high level initializing web 3 basically connects our client-side application to our local blockchain and I'll explain how that works now remember we saw web 3 in our console when we listed out it counts and we will get an instance of web 3 attached to our window from meta mask which we installed when we install the dependencies for this tutorial now meta mask is the extension that turns our Chrome browser into a blockchain browser a browser that can connect to the etherium network and when we login to meta mask it's going to provide us with a web 3 provider when it does we will set this web 3 provider to our applications web 3 provider and if that doesn't happen we will set a default web 3 provider from our local blockchain instance now don't get too hung up on what's happening inside of here essentially just know that this is the function that initializes our connection of our client-side application to our local blockchain once that's finished we will initialize our contract and we do that here from a high level this function loads up our contract into our front-end applications so that we can interact with it the first thing that we will do is load a JSON file of our election artifact and we will use that JSON to generate a truffle contract and this truffle contract is the actual contract that we can interact with inside of our app and we will set the provider for this contract as the provider that we created in the contract function and once that's done we will render our app now a quick note that this get JSON function works for this election JSON file because we're using the browser sync package that came with our trifle box and our browser sync package is configured to read JSON files out of the build contracts directory and we can actually take a look at the JSON file for our contract artifact here yeah and this is actually this is the byte code right here that is compiled and gets run on the etherium virtual machine next we have our render function and this is the function that will lay out all the content on the page now from a very high level this function is going to do two things it's going to display the account that we are connected to the blockchain with and it's going to list out all of the candidates in our election so let's let's examine that further first we're going to declare an election instance variable that we can reference throughout this render function just like we did in our tests next we're going to keep track of the loading template and the content element on our page so that we can show and hide them at different points in the render remember this is gonna be an asynchronous execution so we want to show the loader while this is happening and hide it hide the content on the page for now first we want to load the account we do this with web 3 which we set in our and net web 3 function we use the eth object like we saw earlier when we were accounts and we have a nice function called get coinbase which will provide us with the account that we are currently connected to the blockchain with and if you have ever purchased cryptocurrency from the coinbase website that's where the name comes from now we will inject all right count into this function and if there's no errors we will set the account to the current account in our app and we will simply display this account in the account address section of our application next we want to list out the candidates on the page and we do that here first we get a copy of our deployed contract and we assign it to our election instance variable which we declared here and the first thing that we want to do is get the candidates account now remember we are using this candidates account to keep track of all of the candidates that are in our mapping and this represents all the candidates that are nominated in our election now inside this function we want to use a loop to list out each candidate in our mapping and remember I said we don't have access to all the candidates and our mapping and we cannot iterate over our mapping and that's what we're going to use our counter cash for so we will write a for loop starting at one and we will go from one all the way up to the number of candidates and our candidates count so this could be 10 it could be 100 and we would create a candidate for each value in that range but in this case it's just 2 because that's all we have in our contract so inside this loop we will call the candidates function on our contract we'll pass in the I value inside of our loop this will correspond to the candidates ID so we'll read this candidate from the mapping and we will inject it into this callback function once we're inside of here we will fetch the candidates ID by referencing the first value by index we will reference its name and we will reference its vote count once we have these values we will generate a very basic template that's just going to be a table row with the candidates ID the candidates name and the vote count we'll take this template and we will append it to the table on the page and finally once all that's done we will hide the loader and show all the content that we want to render out all right so that's it for our client-side code up to this point in the tutorial now let's look at a couple of other things we need a way to load this client-side application and our truffle petshop box that we started off with gave us a package called light server which you can see in our package dot JSON file this is the server that we will use to build all of our client-side assets our truffle box also gave us browsersync which i mentioned a minute ago in addition to giving us access to the get JSON function for our artifacts abstractions or our contract abstractions it's also going to just reload the content on the page and it will do that anytime we say something inside the SRC source directory so our index.html or app.js file also while we're here I'm going to clean up a couple of things we don't need that were provided by the truffle pet shop box and I'll just kind of point those out and clean them above screen so I'm going to delete these images I'm going to delete this pets JSON file I'm going to delete these images here all right it's all cleaned up alright so let's take a look at the clients that application that we've built so far the first thing that we want to do is migrate our contract up to this point oops trifle migrate - - reset and the next thing that we want to do is open a new tab so that we can start light server and we can start light server by running NPM run dev all right and there is our page that we've created but you'll notice that it's loading and we don't see any data back yet from our smart contract and that's because our client-side application is running but it's not yet connected to our local blockchain instance and in order to connect we'll need to use the meta mask extension that we installed for Chrome and the dependencies portion of this tutorial the meta mask extension is effectively going to allow us to log into our local blockchain so that we can see data here we'll be able to see our account address and then we'll be able to actually see the candidates who are nominated in this election so let's set up madam mask really quickly the first thing we'll do is we will see some Terms of Service we'll accept those and we'll be prompted to create a new password to login to meta mask once we've entered our password meta mask will give us a seed phrase now it's going to be very important that you copy the seed phrase and store it somewhere the seed phrase will be used to restore your account in case you uninstall meta masks or you lose access to this meta mask client and it's very important if you save this and do not share it with anyone especially if you are ever connected to the main aetherium network and you have real aetherium in your wallet so now that I've copied this agree and now we are connected so we're connected to the main network and we want to do is connect to our local network so we'll go to ganache and we'll check to see which port we're running on in this case I'm running on port 75 45 we'll head back to Mehta mask and we will connect to a custom RPC and the URL of this custom RPC will be HTTP colon forward slash forward slash localhost colon 75 45 and we'll safe boom and there we have it now you may see a different account value here this is bef 5/7 this is a different value so we can ensure that we are logged in with the you may not actually see anything here yet and we can ensure that you'll see results and ensure that we're using the correct account address by importing a new account into meta mask and I'll show you how to do that so if you go to madame masque we can see these account addresses here I'm just going to take account number two here and this is gonna be the account address that we're going to use and I'm going to show the private key I'm gonna copy this private key go back to meta mask and go to this little count symbol here and I'm going to import an account and I'm going to import it from a private key and I'll paste that private key in here all right so we should be connected to account number two here let's refresh the page so this should be a count eight f EF which is exactly what we copied from ganache eight f EF okay so there we have it we have connected our front-end application to the blockchain we can see the candidates that we created in our smart contract we can see their names we can see their vote counts and we can also see the count that we are logged into with meta mask to our local blockchain now if you have any problems seeing this content you may have to trouble she Mehta mask a little bit you can also use the web inspector with chrome to examine to see if you have any console errors you can also download the code at this point in the tutorial with the links in the description of this video below I'm going to go ahead and commit the changes that we've made so far and push them up so that you all can download the code at this point in the tutorial I'm going to add everything that we have so feel free to download that in order to follow along with the rest of the tutorial and you can also subscribe to the channel if you'd like to see more videos about developing decentralized applications with the etherium network the next bit of behavior that we want to add to our smart contract is the ability to cast a vote and if you want to pick up with this section of the tutorial you can download the source code in the description below the video if you're doing that just be sure to run npm install first to follow along in order to cast a vote will go into our smart contract and we will define a voting function and we want this voting function to take one argument an unsigned integer of the candidate ID and we want this function to be public that means we want an external account to be able to call this function we don't want it to be only available to our contract we want it to be accessible publicly so the very basic core functionality of this function will be to increase the vote count for the candidate that we want to vote for we're going to do this by reading the candidate out of the candidates mapping and increasing the vote count on the candidate struct that is returned from that mapping and we'll do that like this so for yeah we want to update candidate vote count first we will reference our candidates mapping can see that's here and here and we will read the value of the candidates struct that we are trying to vote for we do that by taking the candidate ID the ID that was passed in and using that as the key and our candidates mapping which we know will return a candidate struct that will have a vote count and once we read this candidate out we will get it's a vote count and we will increment it by 1 with the increment operator so that's it this is how we will update the vote count for our candidate now keeping track of the candidates vote count is the core functionality of our voting function but there are several other pieces of behavior or stipulations that we want to program inside of our vote function the next thing that we want our function to do is record that voter has voted now remember let's think about our use case for a second this smart contract governs an election and we only want the address of the person who's trying to vote to vote one time the first step in ensuring that that happens is to keep track of the fact that that account has voted so how do we keep track that this account as a voted in fact how do we even know which account is voting when we call this function I mean we only pass in a candidate ID here well when we call this function solidity allows us to pass in metadata to our function so it allows us to pass in more arguments than the ones that we defined here and part of that metadata can be the person who is sending this function or the account that's sending this function and we will observe that when we call the function in the console here in a minute but for now you can know that solidity will give us a special way of accessing the account who's sending this function with MSG sender MSG stands for message and that's going to be part of the metadata that gets passed into this function and sender is going to be the account from which this function call is sent now this is a little bit of magic at the moment but just know that this is how we are going to access the account that is sending this function when we call it so that's how we access the account who is voting but how do we keep track of the fact that they've already voted or that they're voting whenever we call this function also do that we are going to create a new mapping just like we created whenever we stored the candidates who are running in our election so we want a way to store accounts that have voted and we can do that like this so I've created a new mapping here I have to find a mapping that takes a key value pair of an address and it returns a boolean value and this mapping will be public and we will call it voters and remember because it's public we'll get a voters function so this key value pair is simply going to take an account as the key they count address and give us a boolean value so if I add the account address to this mapping and set the value to true that's how we're going to keep track of the fact that the candidate are sorry that the account has voted now if the address does not contain to this mapping this boolean value will default to false now that we have this mapping as a quick look up to see who has voted let's actually add the the address who is voting in this function to that mapping so that we can track the fact that they voted and we'll do that like this we'll do voters so the name of the mapping we just created we will read the account with MSG dot sender and we will set its value to true like that again so we're just referencing our voters mapping we're reading the account out of that mapping and setting its value to true the fact that it has voted all right so there's the very basic functionality of our vote function for now we are just going to increment the vote count for the candidate and we are going to add the sender of this function to the list of addresses that have already voted let's jump into the console and try to actually cast a vote with the function that we just created the first thing that we'll need to do is migrate our contract with truffle migrate - - reset all right and we will open the console with truffle console and we will get a instance of our deployed contract and we will try to cast a vote so when we call this function we're going to need two things we'll need the candidate ID that we want to cast a vote for and we want to pass it an account that we're voting on behalf of now we can see the accounts that are available to us like we saw earlier with web 3 web 3 DTH accounts you can see all of them we also have access to each account in that list so here's the first account now how do we tell our vote function that we want this account right here to cast a vote well I'll show you so we will say app vote we'll pass it I candidate ID will just say candidate ID number one and then we will pass our functions some metadata now remember I said that solidity allows us to provide metadata to our functions beyond just the arguments that we specify and the metadata that I want to specify here is from and this will denote the account that we are sending this function from and I'll assign this to web 3d th two counts zero and this just tells our function that the first account in this list is the one who is voting and whenever we call this function the from metadata is what solidity translates and captures with msg sender right here all right so let's see if it works boom it worked so how do I know that it worked well it looks like it worked but what is this thing right here this is a transaction receipt whenever we write the blockchain we actually are creating a transaction and these are the transactions which are grouped together in blocks which are chained together to make the blockchain and whenever we write a new transaction we get a transaction receipt and we can kind of look through here and see the components of this receipt so we see the transaction hash here and here we see the block cash that was mine to create the transaction I see the block number we see the gas used and a few other things so gas let's talk about gas for a second this is the first time that we've written a function that's called by an account and whenever you know an account calls this function they're gonna have to pay they got to pay gas and aetherium network uses the concept of gas to determine how much the user has to pay when they call this function because you know reads from the blockchain are free but rights cost gas now when we think about gas you want to think about two things gas and gas price now gas is just a unit within itself it's not equal to aetherium now one gas is not one aetherium in order to get the etherium amount we must multiply the gas usage by the gas price now gas can be kind of a complex topic at first so if you're interested in learning more about gas just leave a comment below and subscribe to the channel and I'll be happy to make a more in-depth video explaining gas on the etherium Network alright so there we have it we have successfully voted in the console we've called our vote function with a candidate ID of one and we've passed some metadata into our function we've specified that the account that is sending this function is the first account in our local network and we have access to that account address inside the solidity with MSG Center and we have tracked the account has voted whenever they call this function and we have updated the candidates vote count let's add a basic test for our voting function to do that we'll go to our election JS file and our test directory here and we will add our test here now in order to test this function we want to check for two things the first is that the function increments the vote counts for the candidate that whenever you vote you know the candidate vote goes up by one and we also want to check that the voter was added to the mapping that we created that our contract knows whenever that account has already voted so let's see how that works first we get a copy of our deployed contract we assign it to our election instance that will reference throughout this promise chain we declare a candidate ID which will also reference throughout this promise chain so when we call this function we pass in the candidate ID that we vote for and we pass in the function metadata like we saw on the console and we specify the account who is voting this is going to be the voter and if you remember earlier the accounts come in whenever we create this contract test here so once we cast the vote you know will trigger a promise chain and the return value of the vote function like we saw in the console was a transaction receipt which we'll inject here we're not going to do anything with that receipt just yet but inside this we are going to read our voters mapping that we just created we're going to read the account out of that mapping this will return the boolean value to tell us whether the account voted or not and we will make us assertion that this value is true that the voter was actually you know marked as voted after that we will fetch our candidate out of the mapping and return it here and we will read the number of votes that that candidate has received so far and we will assert that as equal to 1 because we have just called the voting function one time and this candidate should only have one vote at this point all right so let's run our tests boom they passed so now that we can actually cast a vote for a candidate and now that we can keep track of who's voted we want to add some more behavior to our vote function we don't want this function to just be called whenever by whoever we want to add some conditions that will keep these lines from executing if those conditions are met the first condition we want to check for is that the address has not voted before and we also want to check that we are voting for a valid candidate now we've kept track of the voter who has voted already whenever we call this function the first time but if they try to call this function again we want to stop execution before we get here now let's explain how we do that so solidity provides us with require now require will accept some sort of condition and if that condition evaluates to true you know we require something that's true the rest of this code will get executed but if the condition evaluates to false then this will stop execution so again we're looking for some sort of boolean value here and we want to do is we want to effectively require that the address has not voted yet so how do we do that well the first time that an address tries to vote they get added to our voters mapping so we want to check to make sure that the address is not in our voters mapping and we do that like this let's take a look at that for a second so we reference our voters mapping and we try to read the account address as the key which will return a boolean value if they have not voted before this will return false and we'll take the opposite of that with the bang or the exclamation mark and we'll pass that condition to our require statement now that can be a little confusing trying to reason about this for a second because you're taking the opposites of values and you're having to kind of hold a lot of things in your head at one time but this can essentially be read as require that this address is not in this mapping or require that this address has not voted yet next we want to require that we're actually voting for a valid candidate you know if there's only two candidates in our election we don't want to vote for a candidate ninety nine and we'll do that like this so this is another condition that we are passing into our require here and let's take a look at this condition we basically want to take this candidate ID that we're passing into our function as a local variable we want to ensure that this ID is greater than zero because zero is not valid and we also want to ensure that this ID is less than or equal to the candidates count which we've kept track of and our counter cash here so anything from one all the way up to the number of total candidates in our mapping will be valid so if it's not zero if it's greater than zero and it's less than or equal to the candidates count this will return true and we will satisfy our requirement condition and this function will continue execution if the requirement evaluates to false this function will stop execution and throw an exception in the case of voting this is a function that creates a transaction and the sender who is calling this function is sending some etherium as gas now whatever gas would be used to Xu this part of the function is not going to be used since we don't get there yet and that's going to be refunded to the sender but any gas that was used up to this point will not and that's another reason why it's very important that we thoroughly test our smart contracts to ensure that they're bug free now that we've added some requirements to our function let's test them out in the console and the first thing that we need to do is redeploy our contract shuffle migrate - - reset alright and we'll open the truffle console and we'll get an instance of our deployed contract now let's call our vote function and we will vote for the first candidate and we will send this function from web 3d th two counts zero we'll just do the first account for now alright so that worked we got a transaction receipt now let's make sure that we cannot vote again boom we got an exception just like we expected error VM exception while processing transaction revert that's what we wanted so our first requirement worked this account cannot vote twice now let's see if we can vote for an invalid candidate let's say candidate number 99 and let's try to vote from a different account so that we're not triggering the same in fact let's just do count 5 all right we got another exception so that works we cannot vote for candidate 99 and let's just ensure that account 5 is able to vote so that we are extra sure boom that worked all right so let's write some tests for our new requirements I'm just gonna paste those test examples in here again you can get these test examples by downloading the code in the description below the video and let's take a look at the first one so the first thing that we want to test for is that an exception is thrown for an invalid candidate so just like all of our other tests we get an instance of our deployed contract and we assign this instance to a variable here and here's what we'll do we will vote one time for candidate 99 and we know that 99 is invalid because there are only two candidates in our election and we'll do this from account 1 we can check for an error by calling assert fail inside this promise chain and we won't catch this error and inject it into this callback function once we're inside this callback function we can inspect our error object we can check its message and we will check that this message has this substring revert inside of it and we'll say this error message must contain revert you know there are other different kinds of exceptions that can be raised by the etherium virtual machine but in this case we want to specify that it's a revert message then we will ensure that the state of our contract is unaltered whenever this require function is called now the first thing that we're going to do is fetch the first candidate and we want to ensure that it's vote count did not change so whenever this function is called and it stopped execution here we want to make sure that the vote count that not increment so that's what we'll do here well assert that the vote count is still 1 it's 1 because we voted one time already in our test suite and we also want to ensure that candidate number two's vote count is unaltered and will just assert that it stays zero because it has not received any votes yet the next thing that we want to test for is that they can't sorry they account cannot vote twice so in typical fashion we will get an instance of our contract we will start with a candidate idea - we'll do a different candidate this time we will vote once from account number one for candidate number two and we will read this candidate out of the candidates mapping and we'll just make sure that the first time that we voted for this candidate it worked that you know their vote count went up to one you see we're voting for candidate number two it hasn't received any votes yet so after we vote the first time we expect candidate number twos vote count to be one so it accepts the first vote and then we'll try to vote again we'll take our instance we'll call vote with the same value candidate number two from the same account which will be you know accounts an index of one when we do this we will assert that another failure happened and we'll catch this error and we'll check that the index of revert inside this error message exists and we do that just like we did in the previous assertion and after that we will ensure that the state of our contract is unchanged just like we did in the first test example we test that the vote count did not go up for either candidate alright so now that that's written let's try to run our tests and boom they pass we can see it throws an exception for invalid candidates and it throws an exception for double voting now we will allow an account to vote using our client-side application to do this I'm going to paste in some code to update our clients that application you can get this code with the download link in the description below this video now the first thing that we've added is a form that will allow our account to vote and basically this form is going to have a select input and we will append items to this select input that correspond to each candidate in our smart contract and the select input it's going to have an on submit handler that will call a cast vote function that we will define in our app J's file next we're going to update our app that J's file to do a few things first we want to list all the possible candidates from our smart contract in our form select then we want to handle the form submission whenever the account tries to vote and lastly we want to hide the form if the account has already voted so most of these changes have happened inside of our render function so let's take a look you can actually see the get diff markings here the first thing is we've queried for the candidates select that's the select inside the form we've emptied that out and we have entered inside of the loop that we created when we were entering when we were listing out the candidates on the page so inside this loop anytime we reference a candidate by ID in addition to listing them on the candidates table we are going to render a select option inside of the voting form and we're just building a simple template here and lastly we want to hide the form on the page if the account has voted already so after we've rendered all this out we want to access the voters mapping we want to read the current account to see if they exist in that mapping if they exist in that mapping then they've already voted and this will return a boolean value of true and we'll pass that into this callback function if that returns true then we will hide the form so that they can't vote twice and lastly we will add a function to actually vote it'll actually cast a vote with our smart contract and remember we're doing this with our on submit handler that we defined here cast vote and we define cast vote here so let's see what that does we will query for the candidate ID we'll get its value from the selector that the form has selected whenever it's submitted we'll get an instance of our deployed contract we will call the vote function with the candidate ID that we got from the select and we will pass in the function metadata with from and we will say that it's the current account for our app and this will be an asynchronous call so we will execute a promise chain and for now we're just going to hide the content on the page and show the loader and whenever this votes actually recorded we want to do the ops that we want to actually rerender the content on the page but we'll do that momentarily alright now that all of our front-end code is in place let's take a look in the browser first we'll need to ensure that light server is running so that our assets are being served to the browser and we will Chrome and there we have it there is our forum to vote for the candidate and let's try it out so let's try candidate number two all right notice that when we try to catch our vote meta mask will open a confirmation window and this confirmation window basically is checking that you actually want to submit this transaction to the blockchain now remember this is going to cost this account some amount of aetherium and that's expressed in gasps so here's the gas limit and here's the gas price and we have a little conversion fee here that says that this will equal to about two dollars and sixteen cents so we'll click Submit to submit the transaction and a vote boom and we have successfully submitted our vote now we're just going to see this loading screen here we won't actually seen anything come in yet because we haven't we haven't written that in our client-side application so we'll have to refresh the page for now boom there we go you'll notice that candidate 2 received a vote that's one we voted for and the voting form is no longer visible it's hidden because we wrote the code to hide the form if this account has voted already so let's let's try to cast a vote from another account to do that we will go to ganache let's take account numbers let's do four I'll show the key we'll copy that key go back to meta mask we will import an account click import let's refresh once we've done that we can see that we're logged in is this new account you can actually rename this if you want to and will refresh the page alright so we see the vote count and we see the form again so let's try to cast another vote for a candidate number two Oh confirmation submit bla bla bla alright let's refresh the page and there we have it a vote for candidate number two and the forms gone alright now we can successfully cast votes with our client-side application but we want to update this because we don't want to get stuck on that loading page every time we cast a vote we actually want the page to refresh on its own so that we can see the votes come in in real time as they happen now the good news is we can add an event to our smart contract that gets triggered whenever a vote is counted and we can subscribe to this event on the front end to watch the vote come in in real time as it gets going and that's exactly what we'll do in the next section of this tutorial now that we've come to a stopping point we'll commit our changes call this cast votes and again you can fetch the code at this point in the tutorial with the link in the description below and you can subscribe to the channel if you like to see more videos on how to develop decentralized applications on the etherium network now the very last task is to trigger an event inside of our vote function any time a vote is cast now you can follow along with this portion of the tutorial by downloading the source code in the description below the video if you do that just make sure that you run npm install first to install your dependencies now let's head into our smart contract to see how we trigger this event the first thing that we need to do is add an event which is pretty easy in solidity we'll just do that like this we declare an event like this we'll call it a voted event we'll just give it this name and we will use an unsigned integer to index the candidate ID that we will pass into this event next we want to trigger this event any time a vote is cast so anytime this vote function is called we want to trigger this event and that's also really easy just like that we will trigger this voted event and we will pass in the candidate ID that was the only argument to our vote function alright now that we've added that voting event let's make sure that it gets called when we run our tests and that's going to be pretty easy too what we'll do is find our tests where we cast a vote the first time this test that says it allows a voter to vote and we will inspect our transaction receipt and we'll do this so when we inspect this transaction receipt we will do a couple of things well make sure that the transaction receipt has logs and will assure that it has one log and this log will indicate that an event was triggered and we'll dig into this first log and we'll access the event and we will ensure that it's the correct event type that it is actually devoted event that we created it in our smart contract and we will also check to see that the arguments inside of this event contained the candidate ID that we specified and this is that the candidate ID is correct then this candidate ID comes from here and here all right so let's run our test to make sure that they pass and there we have it our test pass now let's update our client-side application to listen for the voted event and to trigger a refresh anytime the voted event is triggered we can do this by adding a new function above our render function and we'll call this listen for events and again you can get this code with the link in the description below the video will also call this function whenever we initialize our contract we'll just do app dot listen for events listen for events and inside of this function we will do a few things first we will get a deployed instance of our contract like we've been doing and we will call the voted event and we will subscribe to this event and whenever this event is triggered we'll log it and we will rerender our application now let's talk about what's happening as far as the arguments go inside of this voted event first solidity allows us to pass a filter to our events and we will not make use of that in this tutorial so we'll just pass an empty object now and then we'll pass some metadata to our event it says from block 0 to block latest this basically means that we want to subscribe to events on the entire blockchain so from the first block to the most recent one and this is how we listen to those events and whenever the events triggered will log it and we'll rerender the app and when the app is rerender dwee will see the updated vote count all right so before we save this and look at it on the front end I want to make a quick note in order for this to work you may have to restart Google Chrome that's because there's a known issue with meta mask if you want to read more about it you can check out this link right here but basically I had trouble subscribing to events the first time that I built this application and I had to actually do some googling and I found this issue with meta mask so if you have the same issue that I do restarting chrome work for me so if you restarted Chrome and you visit your front-end application you'll see this loading page that's because we're not signed into meta mask so you'll have to use the password that you created earlier see once we log in let's change our account back to account number one and let's refresh the page all right so now that we had the front-end reloaded let's try to vote again but just as an exercise let's go to ganache and add a new account so let's do this take the private key and we will import an account we'll call this I just call this account six okay so let's try to keep a vote for candidate one with our new account and let's see if it updates in real time we'll confirm the transaction okay well vote aha so as I was trying to vote we actually ran into an error and I decided to keep this just to as a fun debugging exercise I opened the console and saw that instance voted event is not a function so that means that we forgot to migrate our contract whenever we added the voting event so let's do that now all right so let's try to refresh there we go remember that we will reset all of our data when we rerun our migrations that's because we are deploying a new contract with a completely fresh state and we're still logged in with account number six so let's try to cast a vote for candidate number one again and let's see if it actually updates in real time boom there you have it so our funded application is listening to the new event that we created in our smart contract we're calling that event whenever the voting function is triggered we subscribe to that event and it refreshes our page and updates the vote count in real time after we submitted the form okay so there you have it this is our full-blown voting DAP it allows us to see all these candidates in the election we can keep track of some data about the candidates including how many votes that they've received we can vote on behalf of any account in our local blockchain we can see which account we're logged in as now this is really just a starting point and there's so much more that we can do with this DAP we can extend it to include several different features we can add a timer to our election so that there's actually a limited amount of time for people to vote like you know in a real election and we can wait for that timer to run out before we start announcing the winners of the election instead of just displaying them publicly as the results come in and we can also restrict who might be able to vote in our election like we can allow accounts to register to vote and we could restrict any account that's not registered to vote to not vote in our election if you guys are interested in doing some more videos where we build out those features leave a comment in the comment section below and be sure to subscribe to the channel and as always you can get a copy of this completed code in the description below and you can download that and follow along or make any modifications that you'd like to so I hope you all enjoyed that tutorial let me know what you thought in the comments below and until next time thanks for watching DAP University [Music]
Info
Channel: Dapp University
Views: 401,676
Rating: undefined out of 5
Keywords: ethereum developer, ethereum solidity, dapp ethereum, ethereum app, ethereum development, ethereum dapps, ethereum application, ethereum tutorial, ethereum mist, decentralized applications, ethereum web3, dapp, ethereum contracts, solidity, programming ethereum, ethereum programming language, ethereum coding, ethereum contract, ethereum code, ethereum virtual machine
Id: 3681ZYbDSSk
Channel Id: undefined
Length: 118min 11sec (7091 seconds)
Published: Thu Jan 25 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.