There are many journeys we can take into becoming a web3 developer. Not all journeys require learning a completely new language and becoming a smart contract developer. In this workshop we will learn how to build our own React UI on top of any existing smart contracts on the Polygon Proof of Stake Blockchain. We will explore a basic overview of blockchains and learn about the advantages of building on Polygon. We will also gain an understanding of what Smart Contracts are, learn how to find existing ones, and learn tools that help us interact with them from a React application.
How to Build UI's for Smart Contracts
AI Generated Video Summary
Today's workshop covered various topics including an introduction to Web3 and smart contracts, an overview of blockchain technology, the birth of Bitcoin and its impact on blockchain, an introduction to Ethereum, Polygon, and wallets, and the process of connecting wallets and interacting with smart contracts. The workshop also included practical exercises on setting up Metamask, exploring block explorers, and interacting with a smart contract. Participants learned about the importance of the secret recovery phrase, the structure of blocks in a blockchain, and the role of gas fees in incentivizing miners. Overall, the workshop provided a comprehensive overview of Web3 development and blockchain technology.
1. Introduction to Web3 and Smart Contracts
Thank you all for coming to my workshop. Today we're gonna be talking about how to build UIs for smart contracts. A little bit about me, my name is Rahat, I'm a developer advocate over at Polygon. I've been a front-end engineer and a freelance engineer doing smart contract work. I'm an Indie hacker and web three enthusiast. Let's make sure you have the GitHub link for what we'll be working on.
Here's a sneak peek. Awesome, cool. Thank you all for coming to my workshop. Huge thanks to the React Summit team for inviting me on here to give you all a little bit more of an introduction on how you can get into sort of the web three space with your existing skills as a front-end engineer.
So today we're gonna be talking about how to build UIs for smart contracts. A little bit about me. My name is Rahat, I'm a developer advocate over at Polygon. Previously been a front-end engineer, I've also been like a freelance engineer doing smart contract work for different small groups and projects. Overall, I'm an Indie hacker and web three enthusiast. These are places you can find me. Gonna be dropping a couple links here and there as we go.
First, I just wanna make sure that you all have the GitHub link for what we're gonna be working on. Let me just grab that real quick. I'm gonna drop that into the chat so that everyone has it. We're not going to be going into the code for just a little bit, but just so you all have it. So you can pull the code and just install everything. You can use Yarn or NPM, doesn't matter. All it is is just a React application scaffolded out with createreactapp. It's also like an additional dependency that we'll talk about a little bit later. So just make sure we all have that. Once we get there, we'll talk more about it.
2. Introduction to Web3 and Blockchain
Today's agenda includes an introduction to Web3 and blockchain, a visual demo of a blockchain, an overview of Polygon, a discussion on wallets and block explorers, coding a UI for a smart contract, and suggestions for further exploration. Web3 is the internet for the individual, supported by blockchain technologies. Blockchain is a distributed database shared among nodes, with data linked by complex puzzles. The blockchain is a permissionless source of truth. A block consists of data that is hashed, and the hash value must meet certain criteria to be considered valid.
So the agenda for today, there's a bunch of things we're gonna be talking about. First, we're gonna do an intro to what exactly Web3 is, as well as blockchain, and we'll define some of those concepts. We'll do a visual demo of a blockchain. Just like a sort of, I guess, not a real implementation of a blockchain, but just to have you understanding how some of the pieces work on a blockchain. We'll do an intro to Polygon. History lesson on why solutions like Polygon exist. We'll talk about wallets. How do we interact with the Polygon blockchain? We'll take a look at what block explorers are. Once we've gotten through those things, that's when we go into the actual coding, because that'll get you kind of set up for success in building out these UIs, as well as understanding how some of the underlying tech works and how to interact with it. After we've gone through coding a small UI for a smart contract, this is a smart contract I built prior to starting this workshop. We'll go over what improvements that you can possibly make for wanting to, if you wanted to continue working on it, what additional features you can add to it, and then an action plan of what are your next steps, what else can you do to explore more in this space.
First off, what is web three? So I broke this down into three phases of the internet. Some people may agree with this, some people may not. Web one, I see as the read-only kind of version of the web, when all you could really do is just post documents online and share that information, right? That was kind of like the beginnings of the internet, when we were able to just paste a document in some HTML and just share information. Web two is like introducing kind of like the reading and writing stages where actual interactions began, where you have services like Twitter, Facebook, et cetera, where you can have like actual content that you can create, you can have some data that is stored somewhere. And these interactions that began are kind of like owned by those specific companies that provide you those services. So like, if you're using Twitter, everything's kind of owned by Twitter, right? Same on Facebook. You don't have any real control over what's done with your data. Web three introduces this concept of the internet for the individual. It's supported by blockchain technologies with native payments and data that is owned by the user. So in my eyes, I see it as inclusive web two. I don't really see a difference really between web two and web three, other than that we just introduced a couple of new technologies and allowed for users to actually own their own data. And we'll talk more about that in a second.
First off, what is a blockchain? So blockchain is a distributed database shared among nodes on a network. Nodes are just fancy term for computers. It's just a whole bunch of computers on a network that has the same copy of this like large database. The data that is on this database are linked by complex puzzles. All of the data can fit together in a specific way, just like a jigsaw puzzle. And we're gonna, when I bring up like the visual representation of the blockchain, hopefully that should make a little bit more sense. There's this concept of consensus, which stops us from changing history. Our distributed database is copies of the blockchain distributed all over the world. If you do something malicious or nefarious on like one copy of that database, there's still like tons and tons of copies around the world that can say no, that specific corrupted version of the data is not correct because the majority of the copies of the blockchain agree that their version of whatever the current state of the blockchain is, is true. We'll also take a look at that in a second. But all this boils down to being, showing like that the blockchain is a permissionless source of truth where we can house different types of data. So we're gonna go into this little demo right now of Anderson Brown remarkably blockchain demo, highly recommend going through this later on. The link to the slides are in the GitHub repo that I shared out, so you can always come back and go through it. We're gonna go to, sorry, it's like a different browser than what I normally use. Cool, Anderson Brown words blockchain demo. I recommend going through this video later. It's gonna go through some of the stuff that we do, but we can go to this like hash value over here. And we're just gonna go break down like the little pieces of a blockchain and go into a bigger kind of like overview of it. At the very core of the blockchain is just like there's this data, and this data is hashed. So, this hashing algorithm is called Asha256hash. Different blockchains use different algorithms to actually hash out the values. That's not too important. The main thing you just really need to know for right now is that if I type in some bit of data like my name, my entire name or hat is represented by this big alphanumeric hash value. If I do something like changing the capitalization of my name, the entire hash value changes. Add an extra space, entire hash value changes, et cetera. Every sort of like combination of different characters has its own unique hash value. So that's how data at the very core is represented on the blockchain. Now let's go into this concept of a block. So a block has a few different pieces of data. A block number, a nonce or a number that's only used once, some data and the overall hash. Now what you'll notice here is that this hash has four zeros at the beginning of it. This is not true for every single blockchain. But for the purposes of this demo and this visualization, what we're going to assume is that if the hash value has four leading zeros, this is a valid hash. This is a valid block. Right now you'll see that the entire block is green. So let me add my name here. You'll see it automatically turned red. It turned red and you'll see that the first four leading values are not zeros. Which means this is an invalid block. The reason it is invalid is because this combination of data, this block number, this nonce, and this data here, all lead up, all like hash down to like this value that does not have four leading zeros. So to make sure that I can actually get the correct nonce that is associated with this data, I hit this mind button. And what's happening in the background is like, it's just trying a whole bunch of different number of values for nonce until it eventually gets up to 55,002. And that is the correct value for my name, this block number and this nonce to get us a hashed value with four leading zeros in it. If at any time, some of this doesn't make sense and you want me to repeat it, anything, you can just drop something in chat or, you know, just raise your hand or something and I will repeat anything. I know there's like a lot of concepts here that may be kind of like far out there or whatever. So this is like one single block on the blockchain.
3. Overview of Blockchain Technology
This section provides an overview of how a blockchain works, including the structure of blocks, the linking of blocks through previous values, and the protection mechanisms against malicious actors. It also discusses the concept of distributed blockchains and the consensus among nodes. The section further explores the addition of tokens to the blockchain and the validation of transactions. The text concludes with a brief explanation of the mining process and the role of gas fees in incentivizing miners.
So this is like one single block on the blockchain. Again, there's a block number, a nonce and a data value. Right now it's just my name, could be anything in here. And all of that should boil down to a hash value that has four leading zeros and that'll tell us that this is a valid block on the blockchain.
So now let's go to the next stage of this, the actual blockchain. So now we have a series of blocks. This blockchain goes up to block number five. So starting from block number five, we see that there is additional information here. And we now have a previous value, right? If you take a look at this previous value, it is actually the same value of the hash of the block that precedes it. So it's linked back to its parent, its parent block on the chain. And that is this true for every single one of these blocks. Essentially, each of the blocks are linked together. This is like a historical link of like what's been happening on the blockchain. This previous value allows you to travel back through different blocks to like see what the state of the data has been in different parts of the chain.
So what happens if I decide, well, let's start with block number five. I do anything here I add stuff, cool, I can remine and get those four leaving zeros just like before. But what happens if I go back to let's say block number three and add some text here, you'll see that not only does this block turn red and no longer have the four leading zeros, but every single block that comes right after it is also invalid. The reason for that is because of these previous values. If I updated and remined this, cool, I can get those four leading zeros and make this a valid block. But now I have to go through and do that for every single block that comes after it. This is what protects a blockchain. This is like the first layer of protection on a blockchain for like malicious or like, you know, bad actors who wanna go in and like change or like alter some data that has already happened in the past.
So if I wanted to like go in and like remind everything and go to eventually cool, you know, I could do that. But then we come to this distributed blockchain. So rather than just like one single chain existing on one computer. The thing that I mentioned before is that these are several nodes, several computers all across the network that have different copies of this blockchain, right? So in this like distributed blockchain I have three computers, three nodes who are running, you know, some version of this data, some version of this actual database. If I do the same thing, I go into block number three and add like Brahal is here. I can go in, I can remind everything. And now all of a sudden I have this blockchain that has been mined, great. If you just take a look at this chain from like the standpoint of this one computer, it looks like everything's good, everything's green, everything's got those four leading zeros for the hash values, cool. It looks like all of this data is fine, but if we think about, like, what is the consensus of the overall network for like what the data, what the state of the data should be. If we look at peer B, peer B does not contain my information on block three. Peer C also does not contain my information on this blockchain, therefore, peer A has invalid data and is not considered to be part of like the actual overall blockchain. So that's sort of just like a very high level overview of like how a blockchain could be implemented. Let's take a look at possibly adding something like tokens to the blockchain. One use case of blockchain technology very popular has been with the use of like cryptocurrency. Here, we're kind of simulating that just by like, creating this ledger of money that as beings like sent back and forth between people. So here we have just like a list of transactions, people sending each other money. Maybe Darcy sends them 25 bucks to Bing Lee, et cetera, et cetera, and go down, whatever. So if I did, so if we kind of like tried to visualize what we did before of saying something like, Oh, Rick didn't send this money to Sam, he actually sent it to Rahat, we mind that, we mind this. All of a sudden like, hey, it looks like, you know, Rahat supposed to have $97.13 added to his account, right? But we go back and look at Peer B and Peer C, no, that's not what should happen because Rick actually sent this $97.13 to Sam, and that is agreed upon by Peer B as well as Peer C. Peer C here, $97.30, Rick to Sam. So we know that we can reject this line of data from the blockchain. I do not have $97.13 that is owed to me in my account. I was the bad actor here trying to change things around and have some sort of attacker or something on this blockchain.
Kayla asked, how many peers need to agree before it's considered a valid chain? For example, if you edit 51% of all peers, would it consider your chain valid or does it check so frequently that you can never do that? So yeah, if you look at like popular blockchains out there like Ethereum or like Polygon, there's just like too many nodes and validators to like actually go in and like edit 51% of those in time to get that like consensus. If you look at like Ethereum itself, like what happens like when you actually do these validations, or Ethereum or Polygon. If you look at like the time it would take for you to go in and like edit something, edit some type of value and data, you still have like several other like hundreds of thousands of transactions also going on, being confirmed by this like distributed network and each of those distributed networks like now have like additional values on there, right? Of like, you know, this is what actually happened like I sent some money to Kayla and then Kayla sent some money somewhere else and then other people are sending money to each other. There's copies of all of that data in so many different instances that it's like extremely, extremely difficult and it would cost like an incredibly large amount of money to actually go in and do that.
There we go. Cool. There is another sort of demo here on Coinbase. We're not really gonna go into that. If you do come back to this blockchain demo and look through these videos, they do go into this a little bit of like how Coinbase transactions would work. But we're gonna go ahead back into the presentation. Hopefully that was a good kind of like overview of blockchain technology. Again, just like Kayla, if you have any questions, please drop them in chat. I'll stop and try to make sure that those questions are answered. Cool. So we have a general kind of like overview of how blockchain technology kind of works, right? One thing that I kind of left out here. If we go back here for a second. This process of like mining, when we have this distributed network and these different peers who are like mining these transactions and validating and making sure that they're correct and like should be added to the blockchain. This requires a lot of computing power, right? So these folks need to be incentivized in some way to actually do this. Cause we're relying on this network of people. These are like regular people who can come in and start doing this. Like you can go in and like learn how to become a validator, like on the Polygon network and contribute to the network in that way. And to do that, there has to be some incentive. Like why am I doing this? Right. So when we're mining transactions and mining like different pieces of data that happen on the blockchain, something you may have heard about if you've like dabbled in web3 at all is like gas fees, right? So this is the reason why we have these gas fees. We, part of that gas fee, depending on what blockchain you're using, will either be like kind of like burned and like used as like a base fee for like the network layer, as well as part of that goes as like a tip to the miner who is actually like validating your data on the blockchain.
4. Bitcoin and the Birth of Blockchain
Bitcoin was created in 2009 by an anonymous person or group known as Satoshi Nakamoto. It introduced blockchain technology, enabling peer-to-peer transfers of Bitcoin tokens without the need for intermediaries. Bitcoin's primary focus is on creating a decentralized financial system in response to the financial crisis of 2008.
This incentivizes, you know, tons of people to go in and like become validators, become miners to like further secure the blockchain. Cool. So, coming back to the presentation a little bit, we now, we'll do like a very brief history lesson. In January of 2009, Bitcoin was created by someone who goes by the name Satoshi Nakamoto. Who this person is, no one knows. This is like, they use like a pseudonymous identity. Could be me, could be one of you, I don't know, but it could be a group of people. No one ever found out who this person is. But they created the Bitcoin white paper, But they created the Bitcoin white paper, which was released in like an implementation of the blockchain where this was like the first time that like someone was able to successfully create used blockchain technology to create like a way to send money back and forth between people. So Bitcoin's like primary function is like this blockchain technology where you can take someone like the Bitcoin, like there's the Bitcoin blockchain and then the Bitcoin tokens. It's for transferring those Bitcoin tokens on the blockchain. So its primary focus is really on like creating this sort of like ethos where folks can have this way of like sending funds back and forth without like a middleman, without a bank, without some intermediary. And again, it was really like a sort of in response to some of like the financial crisis stuff that happened in like 2008 and like people kind of questioning whether we want central banks, whether we want governments to like have so much control over our funds.
5. Introduction to Ethereum, Polygon, and Wallets
In July of 2015, Ethereum was created as a blockchain platform for building decentralized applications (DAPs) using Solidity. Ethereum has undergone ongoing improvements, including testing proof of stake options to reduce energy usage. Polygon, formerly known as the MADIC network, is a leading platform for Ethereum scaling and infrastructure development. It aims to make Web3 more accessible and offers energy-efficient solutions. Wallets, which provide access to the blockchain, are key-value pairs with public and private addresses. They don't hold funds but act as passports to access tokens and data on the blockchain. Interactions with the blockchain are called transactions, and signing is a crucial process. Metamask is a popular wallet that can be downloaded and installed as a browser extension.
In July of 2015, a theorem that was created by Vitalik Buterin. This is a actually confirmed real person who's been at different events and stuff. So he exists and not to say Satoshi Nakamado doesn't exist. We just don't know who they are. But Vitalik has been around and was sort of wanting to do something more with blockchain technology. Ethereum became this sort of like blockchain where rather than just doing financial transactions, you now have the ability to create actual applications on top of the blockchain.
And these applications are called DAPs or decentralized applications. And this is all done using a language called Solidity which is actually pretty similar to JavaScript. And this code all lives on these things called smart contracts. So smart contracts is just a term for just a bunch of code that is written in Solidity and is deployed onto a EVM compatible blockchain. EVM just means like Ethereum virtual machine. Both, so Polygon is like an actual like EVM compatible blockchain meaning like anything you build on Ethereum works without any like configuration or alteration on Polygon. But like beyond that, like initial creation of Ethereum coming from August, 2015 to the present time there have been ongoing improvements made to the Ethereum network. Both in like changes in like how fees are structured, and how much energy and usage the blockchain gets.
Currently as of this year, the Ethereum network has successfully tested several what are called like proof of stake options for changing the way that their blockchain works. It's undergoing several more tests, but the hope is that later this year, Ethereum will be moving to what's called a proof of stake blockchain, which is supposed to reduce energy usage on Ethereum by over 99%. That is still in the works, but in the meantime, there are other options for what you can use for like a more energy efficient and sustainable way of like working with blockchain technology. And in October 2017, that's where Polygon came up. Polygon was formerly known as the MADIC network. So Polygon, we kind of like see ourselves as like the leading platform for Ethereum scaling and infrastructure development. So we provide a lot of different solutions, like what are called layer-two solutions that I'm not gonna go too deep into because you can just like kind of know they exist, but that's like a whole other three-hour presentation to be honest.
And what we're kind of hoping to do is like make Web3 easier for more folks to use. The unfortunate thing with something like Ethereum is that, you know, aside from the high energy usage, it's also something that is priced out and not usable for a lot of folks in most of the world outside of like some of us who may be in more fortunate places in the world and have more access to funds. Gas fees on Ethereum, when there's a lot of folks using it can become very prohibitive to use. And there are quite a few examples of like, and a very mind boggling amount of money that was just kind of like burned out into the world just like use Ethereum because of those fees. Polygon is also already on a proof of stake type of blockchain. We also have recently become a carbon neutral and we're striving to become completely carbon negative. So if you want something like more environmentally friendly, Polygon is definitely a good choice there.
So kind of going into this whole thing of smart contracts, right? So I mentioned before, smart contracts are just, it's just code, right? It's just code that is written, at least in the case of when we're talking about EVM technologies, it's written in Solidity and deployed onto a blockchain like Ethereum or Polygon. So everything that we're going to be working with, like I said, is EVM compatible. So if you ever want to, you know, continue going down this rabbit hole and working on different things, you can kind of like, rest assured knowing that like most popular blockchains probably already support everything that we kind of like go over in this presentation.
First of all, like we have this blockchain, we have, you know, the ability to house like tokens or money and different things on it. How do we actually interact with it as a user? So we have to use wallets. Wallets are kind of like our-
So I personally feel like wallets are misnamed because wallets don't actually like hold, at least in the Web3 sense, they don't hold any funds. They don't hold any actual value other than like a wallet is just like a key value pair. There's a public address that identifies you on the blockchain, and then a private address that gives you access to some part of the blockchain that houses your tokens or houses some information that you have access to. So I view wallets as more of a passport to the blockchain for accessing funds that belong to you or any type of data that belongs to you only you should have access to. Interactions are all called transactions. Transactions are essentially anything that changes the blockchain. So anything that changes some state, adds some new data needs to be needs to go through like some sort of like that mining process or a validation process which costs a little bit of money which is why we call them transactions. And then signing is something that I'm going to be like demoing for you in just a bit.
First of all, what you know, I went over a little bit of what the wallet is but going over again just like three main points to understand and really like keep in mind. It's just a key value pair, public and private address, like I mentioned. They don't hold funds, they just point to them. It's just like a pointer passport, however you want to refer to it of something that exists on the blockchain that you should have access to. And you can kind of see it as like your wallet sort of like manages your identity on chain. Like when we when we dive into the code, there's going to be one section where we take a look at how to connect a user's wallet to your application. And we're going to say we're going to kind of like explore like single sign on and like identity and things like that, on chain through that.
First, though, we have to get set up with our wallets. If we want to start building, we need to make sure that we have wallets ready to go. So this part, if you're able to, I definitely recommend following along and trying this with me. We're going to use and try to download a wallet called Metamask. Metamask is one of the more popular, widely used wallets around. I just dropped a link in the chat. But it's at Metamask.io. When you go to the home page and you go and click download, it should automatically detect what browser you're using. I'm using Chrome, but I'm pretty sure it's like usable on like Brave, Opera, whatever, kind of like whatever you're using. I also have iOS and Android apps. I'm going to go ahead and install Metamask for Chrome, which will just add this to Chrome for me. So now it's just like an extension in the browser, right. So. Let's load. Okay, cool, so I'm gonna hit get started. And when you first opened up MetaMask, you'll be given two options if you want to import like an existing wallet or you want to create a new one. We'll just create a new wallet for now. And then I'm already on my website, so I'm going to go ahead and we'll just create a new wallet for now, whatever, create some password. Create. And that's going to, you know, give you, that's going to take you to this like how to secure your wallet type thing. Definitely recommend looking at that when you have some time. This next part, very, very, very, very important.
6. Secret Recovery Phrase
Your secret recovery phrase is a set of 12 or 15 random words that can be used to import your wallet or gain access to it if you're locked out or on a new device. It's important to keep this phrase safe and secure. You can try to memorize it or use a password manager. Remember to create a new wallet for development purposes to avoid any accidental exposure of sensitive information.
Your secret recovery phrase. Your secret recovery phrase is going to be, I think like 12 or 15 random words. And if you ever need to like import your wallet somewhere, get access to it if you've been like locked out or like you're on a new device, this phrase is going to help you do that. But this phrase would also help anyone else do that. So you always want to make sure that this phrase is like saved or placed somewhere safe. Most people say, you know, try to memorize the phrase. It's very, very difficult to memorize because how long it is. Some people are able to. I'm not very good at that. Or you can use and like store it somewhere like a password manager, like 1Password or whatever. I'm not going to reveal these. I'm going to hit remind me later because I'm not planning to use this wallet ever again after this workshop. I highly recommend that whenever you're developing, you just create a new wallet and do new things with it. Because sometimes when you're developing, like you need to get like the private key and stuff of your wallet and use it in your app. And if you forget to like add a git ignore or anything like that and accidentally commit some keys to GitHub, that's like a bad day. So I'm just going to skip it hit remind me later.
7. Setting up Metamask and Exploring the Blockchain
In this part, we set up our Metamask wallet, added the Polygon network, and obtained test funds. We also discussed the concept of a block explorer and its role in tracking interactions on the blockchain.
And now. Cool. I am. This is this is my Metamask wallet. Brand new wallet that has been made. You can copy like your address from here. I'll just paste mine here. This is like your public address. This is like not something you need to care about. Like not sharing. People can like send you funds here. People can interact with you in this way and find you.
If you click over here, we have will see that right now. By default, we just have the Ethereum mainnet. So we're going to add the polygon network to Metamask. First, I'm just going to pin this so that I have easy access to Metamask from here. Awesome. I'm going to go to PolygonScan.com. On PolygonScan.com, if you go all the way to the bottom, you can click this button, Add Polygon Network, and your metamask will pop up. Hit approve. Switch network. And now if I open up my Metamask, I'll see that I'm on the MATIC mainnet. MATIC is what we used to be called before. MATIC is also the name of our token. So instead of ETH, it'll be all done in MATIC. But now you'll see I have Ethereum. MATIC, but now you'll see I have Ethereum mainnet and thematic mainnet.
But when we're developing and when we're building things out, we don't want to use real money. So what we can do is add a test network to our wallet. And the test network for Polygon can be found at mumbai.polygonscan.com. And if you scroll down, you can hit add Mumbai Network. Hit approve switch network. Now in my Metamask, I'll see that I have the Ethereum mainnet, Polygon test net, and the MATIC mainnet. So Polygon test net is where we're going to be doing most of our work. So we don't have to use any real funds.
Any questions so far? Any question so far, anything that anyone wants me to show you again or we go over, I'll give like 20 seconds for people to catch up or respond. Cool. Looks like folks are okay. Okay. Cool. So we have our polygon test net added to our wallet. So we're almost there. We're almost ready to, like, have a wallet that is good to go for developing. But first we need to add some test funds to our wallet. So we can go to faucet.polygon.technology. And I'm going to drop this link in the chat. I'll also drop the links for— probably should have done this before. But mumbai.polygonscan.com. So this is called a faucet. A faucet is just a place where you can come to in order to receive some Test Network funds to be able to like start developing your applications. None of these have, like, any actual monetary value, but it simulates you actually, like, having some funds to, like, do interactions on a blockchain. What we're going to do is go into our MetaMask, make sure I'm on the Polygon Testnet. I'm going to copy this account. So just copy the clipboard, paste it over here to my wallet address. What kind of token do I want? I'm just going to say I want a MATIC token on the Mumbai network. Hit submit. Cool. And I should receive 0.2 MATIC in a couple of minutes. If you're doing this, and you don't receive any tokens within, like, two to five minutes, just let me know in the chat, drop your address, and I will send you some test tokens to play with. But we'll check on that later. Sometimes it just takes a little bit to sync up properly. But, yeah. So now we kind of like have our wallet set up. At some point we will have some TESTMATIC to use. If we don't, I have reserves so I can distribute that amongst everybody. But we're all set to go. Our wallets are now set up for building. So now let's talk about block explorers, right? So what is a block explorer? It's a UI that allows us to visually track interactions on the Blockchain. If we want to see specific transactions, we want to see how much gas was used. If it failed, we want to check why it failed.
QnA
Exploring Block Explorers and Exercise
If a transaction goes through, we can see the parts of the smart contract called on a block explorer. The blockchain is a ledger, and a block explorer allows us to view it. There are many SDKs available, including Ether's JS, which we'll be using today. Polygon Scan is the block explorer for the Polygon Network. It shows the latest blocks, transactions, and fees. It also provides block confirmations and transaction data. We can explore further by looking at logs. Now, let's do an exercise where you'll look up a contract address on mumbai.polygonscan.com and answer specific questions.
If it went through, we want to see what parts of our smart contract were called in order to facilitate that transaction. All of that information can be seen on a block explorer. The Blockchain itself is a ledger, and a block explorer is one way to view that ledger. It's decentralized, so we can use popular ones or we can build our own.
There are tons and tons of SDKs out there. One of those SDKs is called Ether's JS, which is one that we'll be using today when we dive into the code, that allow you to actually just connect to either the Ethereum or Polygon blockchains and just start looking at transactions and getting and reading data from them if you don't want to depend on a hosted service like one of these block explorers.
Polygon Scan is the block explorer for the Polygon Network. There's a similar one for the Ethereum Network called Ethereum, EitherScan. They work pretty much identically. I think the only difference is the UI branding colors. Otherwise, it's the same thing, really. But let's take a look at Polygon Scan. I'm gonna go back to polygonscan.com. For just this purposes of this demo, I'm gonna switch over to the Maddock mainnet.
Few things we can do here, you can take a look at those the latest blocks. If you recall, those blocks that we looked at before, these are blocks that are coming in and being added. It shows you like who they were validated by, how many transactions are in each of those blocks, as well as like the fee or like how much Maddock has spent to mine or like validate those. These are the latest transactions, so those blocks are gonna hold like a bunch of transactions inside of them. Let's just take a look at this transaction here. This was a successful transaction. The fee that you're getting is $0.25. This was a successful transaction. The fee for this was like 0.002 something. Maddock says here it's like $0 but I think it's actually like a fraction of a penny. So this is like one of the advantages of using a chain like Polygon. It's much more accessible. Fees are fractions of a penny versus like anywhere from like 10, 20, 30 plus dollars per transaction on like Ethereum and net. Cool here, you'll see that I mentioned something like this before of like block confirmation. This kind of ties into I think Kayla's question from before. When you have like blocks being added to the blockchain there are different confirmations. Let me refresh this. Since we've started speaking 25 further blocks after this have actually been created. So there are now 25 confirmations that this specific transaction exists on the blockchain. So when you like look at it that way, it becomes increasingly difficult for people to actually go in and change things within the blockchain. So the more validators you have, the more miners you have, the more secure your blockchain overall becomes. Refresh again, we're now at 43 confirmations. So this is just kind of like going up and up and kind of like being confirmed by many more miners and validators. Some other information you can get from this is like the data that was used as part of this transaction. Not a lot going on here, but let's say like this was me doing some type of CRUD function where I'm like adding some data to the blockchain. This is where I would find what that data is that I actually tried to add. And that'd be under logs. And some other stuff we're not going to really go into. It's not too important, but yeah, I think we can probably end there for now. But we're going to have like a little bit of an exercise on this in just a second. So we've got, actually let's just do the exercise now. So I'm going to give all of you a contract address. They're going to look up this contract on mumbai.polygonscan.com. Let me just make sure I got the right one. Because there were two that I created and one of them had a bug. So I had to redo it. Where'd it go? Okay. All right. I think this is it. I'm just gonna make sure this is it really quick. Bear with me one moment. So I'm gonna go to mumbai.polygonscan.com and I'm gonna drop this address here. Looks like this might not be it. I'm also going to drop a contract address in the chat. So similar to us having addresses for our wallets, smart contracts that have been deployed onto the blockchain have an address as well. So I just dropped an address into the chat. You're going to do is go on mumbai.polygonscan.com and you're going to look up this address. You'll notice that there have been four transactions associated to this address. Your job for the next few minutes is to answer the following questions. What is the wallet that deployed this contract? So you're gonna find a specific address that deployed is, what was the data associated to an answer? So if you look at these methods, there's an answer a function here and you just figure out what was the data that was given to the smart contract within that transaction? And then this tip and withdraw function, let me know how much MATIC was given here as a tip, how much was withdrawn, five minutes, just kind of like dive through, you can open the transactions, take a look at the logs and okay, so does anyone wanna answer the first question, what was the address that deployed this contract? Feel free to drop it in the chat or you wanna come off mute, that's cool too. I don't know if you wanna actually, yes, Lucas, that is the correct address. Can you give us a link or like, where did you find that information? Yeah, I found it on the contract page itself and has a top right section with the contract creator and has a creator address. Yeah, right here, contract creator, contract address. So this address is actually like my main development address. But yes, that is correct. Next question.
Exploring the Contract and Interacting with it
The answer method sent the data 'GM react summit'. The tip and withdrawal amounts were both one magic. The contract is a guest book contract where users can leave messages or answers to a prompt. The contract also has a function for sending tips and a withdrawal function. Solidity code is used, and the answer function takes a string input and adds it to an array. The read contract function retrieves answers, the prompt, the contract owner's address, and previous tips. Solidity reads currency values in the smallest possible denomination. Reading contracts is free, but writing to them incurs costs. Tokens can be obtained through MetaMask, and connecting to the contract through PolygonScan allows for direct interaction. Writing to the contract requires a transaction. Reading contracts does not cost anything. Writing to them incurs costs.
What was the data sent in the answer method? GM react summit, yes. So this one if you just click on the transaction here, I need to do that one because if you look under method, this is the answer method. If you head over to logs, you'll see that the data was GM react summit. Cool.
Last question, how much magic was given as a tip and how much was withdrawn? Yep, tip was one withdraw, was it two? Cool. So tip was definitely one, if we click the tip, we can see that there's a value here of one magic. We go to withdraw, we can see, there's also a value of one magic. So it was one magic each. Cool.
So I purposely kind of like didn't tell you what this contract does just yet. We're gonna be working extensively with this contract for the rest of this workshop. So a few things in here. Coming back, okay. If you click this contract tab in Polygon Scan, as long as there's a little green verified check mark next to the contract, that means that this code is either open source or like completely viewable on the blockchain. So you can actually scroll down and read the code and see what it does, if you wanted to. This is a very like bare bones, not much going on. This is like a guest book contract where like you can go on a website, leave someone messages or answers to like a specific prompt. And additionally, there's also like a function for sending them some type of a tip, if you wanted to. And then there's a withdrawing function that only like the owner of the contract can call and withdraw funds from that contract. So those are actually the most methods here that were being called on that withdraw the tip and the answer. The answer, so this is all Solidity code. This instance of Solidity code should hopefully look very similar to JavaScript and should be hopefully decently easy to follow. But I have this like answer function, which takes just a string, which is an input. And then it pushes that input into an array called answers. And we have this like emit thing, which is like an event. And I'll talk a little bit more about events later, but essentially all we're doing here is taking a string and putting it inside of an array. So if we click on read contract, you'll see, and this is another unfortunate UI error, but if this get answers function, it's part of like the reading for the contract returns like that GM react summit that you also saw before. So this is another way to find it. There's a prompt that people can answer. The initial prompt for this is Sage EM. So we're just telling people, Hey Sage EM when you're coming to this website. You can also see the owner of the address from here, which is that address from before, again, just the prompt once more. And then tips that were given before. So you'll see that tips will occasionally show up as like this very, very, very large number. So in solidity, one thing to kind of like note, and we're gonna see this when we implement the tip function on the front end, is that basically solidity reads all of the values for like currency, like whether it's like in Ether or whether it's in Medic, in the very like the smallest possible denomination, and that's called way. And that's just like a one and 18 zeros. So one and 18 zeros is like one Ether or one Medic. So that's just like a little bit of a gotcha that you have to remember when you're dealing with like funds in solidity. So these are all like the read functions available. I can also do write functions. So I can actually directly interface with this contract from PolygonScan without having to deploy it onto a front end if I wanted to. So to do that, I would hit this Connect to Web 3 button, which will prompt me to connect my wallet. I'm gonna connect using MetaMask. Switch networks. Next connect. Cool, okay. Were folks able to get like MATIC tokens? Was anyone not able? I was not able, so I'm just gonna send myself some right now real quick, so I can... If you were not able to get any MATIC tokens by this point in time, just drop your address in the chat and I will send it to you before like the next part of the workshop where you actually need them. In my case, I need them now, so I'm just gonna do that real quick here. I'm just sending them from like a different account. One moment. Okay. Cool. So yeah. Reading contracts, like I mentioned before, doesn't cost any money. I'm just creating them with Excel and debugging them inside of CSS. That'll be the first step, then I'll come back at the end and get started, doesn't cost any money. That's not a transaction, you're just reading some data or values from the smart contract. Writing to it is what's actually gonna cost some money. So I think I just need to, cool. I'm connected. This is my wallet address. Let's make sure I have some medic now. Still do not. It is always during a live demo that this wants to take forever. This morning, this is quick and easy and painless because no one was watching. Okay. I think it should be good. Okay. Okay, yay, there's 2matic here now.
Interacting with Smart Contracts
Now, let's do another write. We were not able to estimate GaS, there might be an error in the contract and the transaction may fail. The reason for this failure is the 'only owner' modifier in the set prompt function. This is a security measure to prevent unauthorized updates to the contract. It is recommended to build UIs around contracts with a green checkmark, as they have been thoroughly tested. Interacting with a smart contract without a front end allows you to test functions and understand available options. Quick recap: blockchains are distributed public ledgers, and we are specifically working with EVM-compatible blockchains written in Solidity. Wallets are the main method of interaction, and it's important to set up a wallet using Metamask and use test funds. Polygon scan can be used to check code and transaction details. Let's proceed to the coding side.
Cool. Awesome, so now I have 2matic to pay for some transaction fees. First thing I'm gonna do is just do an answer myself. So I did a GM React Summit before. The prompt, I think currently still is agm. You all feel free, if you have that testmatic, to try this out yourselves as well. I'm gonna hit right. And I'm gonna pay some, very small amount of matic for this transaction. It'll be like.003. Yours might be slightly lower, slightly higher. Hit Confirm. And a couple of things can happen. You can view your transaction in your activity. I can see here that it's pending. I can speed it up by adding more gas fees to it. In my case, I didn't really need to. But if I go back to read contract now and hit this reset, I now have React Summit. It looks like someone else, but like a hello there. This UI is not the greatest for looking at some of these, especially like looking at arrays unfortunately. But once we actually do this on the front end, it'll look much, much cleaner.
Let's do another write. So that was like the answer. I can even like set the prompt to be something else. Now, instead of Sage EM, I don't know. Say hello world. I'm not good at thinking about these things on the fly. So, hit write. So cool thing here, we were not able to estimate GaS, there might be an error in the contract and the transaction may fail. I could click. I want to proceed anyway, I'm not going to, because I know this is going to fail. And you'll see here that user denied transaction. The reason that this is going to fail, if we go back to like the code in the contract and we take a look at set prompt, set prompt has this modifier called only owner. In Solidity you have these things called modifiers, which can be added to functions to check for specific things. Only owner is a modifier given to us from a library. And that library is basically checking to see who is the owner of this contract. If you recall, I mentioned earlier that I deployed this contract from my main dev wallet. But this wallet that I'm using right now is one that I created during this workshop. Therefore this address cannot use this update set prompt function. I need to make sure that I'm using that specific wallet. So that's a little bit of a security thing added in there. You don't want people to just go in and update your prompts whenever they feel like it. But this is good for whenever, like if you ever wanted to build a UI around a smart contract. I highly recommend just going for, you know, ones that actually have this green checkmark. Those are probably the only ones you can build UIs around anyway, because you can go in and like check to see like why specific functions would fail. In this case, I should have added another comment regarding this only owner. So my bad, my documentation was not up to par. But this is just like some sample comments of like what type of comments you might see inside of a Solidity contract to like help you understand like what's going on. Cool. So I'm going to reset this again. Awesome, my hi, another GM is in there, there's a hello there and there and there's the GM react summit. I really hope they fix the way that arrays are displayed in here soon. But cool. So that is like how you would interact with a smart contract without the front end. If you just wanted to test things out, if you wanted to serve, like understand what functions are available on that smart contract, definitely keep this link handy. We're going to need it as we're building. Let's go back to here.
Quick recap, before we go into the coding side of things, what are blockchains? Blockchains are distributed public ledgers on an ecosystem of nodes, or just computers on this broad system that have copies of this database. We're specifically working on creating UIs for EVM, compatible blockchain, so these are blockchains written with Solidity code, where smart contracts are written with Solidity code. And you could use a wallet like Metamask to interact with them. Wallets are our main method of interacting with blockchains. A set-up checklist, you should make sure that these things have been done before we go into the code. First, that we created a wallet using the Metamask browser extension, which we went over earlier. Two, that we are not using real money. We have test funds from a faucet. Again, if you need some test funds and did not receive it from a faucet, just drop your address in the chat and I'll make sure to get you some. And third, we can reference Polygon scan for interacting with our smart contract if you want to check the code, if we want to see how, you know, certain things have worked out, why certain transactions failed, et cetera. For now, let's hop into it. Let's actually do some coding. Any questions before we go into the coding side? I see why it has the contract the green check icon. So the reason that the green check icon was there was because when I built this smart contract and I deployed it onto the Polygon test network, I also did a process called the verifying the code.
Setting up Wallet Connection
To connect our wallet and interact with the blockchain, we need to set up the connect wallet feature. We'll create a button that allows us to connect to our MetaMask wallet and display our address. We'll use the aethers.js library to interact with the blockchain. We'll establish a connection between the browser and the wallet by grabbing the Ethereum object injected by MetaMask. Then, we'll create a provider using ethers.providers.web3provider and pass it the Ethereum object. Finally, we'll request permission to connect to the user's wallet using the handle wallet connect function and the eth_requestAccounts method.
So I verified my ownership of the code, I verified that I was the one who actually deployed this and everything. If you do all of that and go through that verification process, which is very quick verification thing, you get this green check and when you have this green check the actual code for your smart contract then becomes public. So people can actually take a look at it. Not necessarily KYC it's more just like from my terminal I deployed a contract and then after I deployed it I verified that I am the owner by like, like essentially what happens with a smart contract is compiles down to what's called Bytecode which is machine readable code. And so I just verified that I have access to that bytecode that I'm the one who built and compiled this smart contract. Which I guess it's sort of in a blockchainy way, K, Y, C, sort of, but not necessarily tied to my identity but to my like wallet. Cool. Awesome. Any other questions before we dive in?
Right. So, I am using VS Code for this. You can use any editor that you like. But the first thing we're going to do is set up this connect wallet feature, right? Like in order for us to interact and do anything on this, like write contract, what we needed to do was connect our wallet. So what we're going to do in our front end is essentially create a button that allows us to do the very same thing where we can connect to our MetaMask wallet and display our address. So in the code, in the GitHub repo that I gave you all earlier, like I mentioned this is just a Create React app with one additional dependency. That dependency is this aethers library, aethers.js. Let me grab that documentation for you all. It's at aethers.io. So you all have it. But aethers.js is just like a library that makes it a little bit easier for us to interact with the blockchain, gives us like a whole bunch of methods essentially to do some of the stuff like connecting our wallets as well as connecting to a specific smart contract. So I'm going to go into app.js. I'm going to remove everything inside of header. I'm going to leave like the default CSS and we'll kind of like work from there. So the first thing I'm going to want to do is import the aethers library. So, to import that, I just do import aethers. And now I need to establish a connection between my browser as well as the wallet, right? Which is that first thing that we saw on Polygon scan. So, to do that, I'm just going to like run through like how you would set up aethers real quick. But the first thing we're going to do here is grab the Ethereum object out of the window. Now, you're probably thinking, hold up, what do you mean, grab the Ethereum object out of the window, that doesn't exist. So, if you're using a Chrome extension, like MetaMask, what happens is MetaMask actually injects an object into the window. So, if I were to go and inspect, go to Console, type Ethereum. There is an Ethereum object apparently in the window. And that's because of MetaMask, it's injecting that in there. It has a bunch of information in here, just about how I'm connected, which chain I'm connected to, and some, just some other information. We're not really gonna go through all of it, but we need access to this object in order to interact with this user's wallet. So, if I head back over to VS Code, I'm de-structuring Ethereum out of the window, and now I'm just checking to make sure that Ethereum actually exists. So if Ethereum, we'll just do like alert. We have metamask. We need to install metamask. Nothing wild going on just yet. I'm going to go ahead and do a yarnstart. And you can use npm as well, I just am partial to yarn. Cool, awesome. So once I load the page it says that I have metamask. Wonderful. So now we know that, you know, we have just that initial connection to our metamask wallet through this Ethereum object. Now I want to actually start leveraging ethers. I'm going to copy and paste these two lines of code. Actually I'll just type them out. So this is from the documentation. So if you go through the Getting Started documentation you can see where I'm getting a lot of this stuff from. But I'm going to create a provider, which is going to give us access to a lot of that functionality from ethers. I'm going to create a new ethers.providers.web3provider and I'm going to pass it the Ethereum object. This is just straight boilerplate connecting to a provider in ethers. Literally, I think copying and pasted from the getting started guide. And then the next thing we have to do is actually request, like this kind of just like detects that a MetaMask wallet exists, but now we need permission to actually connect to their wallet, right? So, this needs to be a, okay. So let's wrap this inside of a function actually. We'll call this like a handle, wallet connect function. The reason I'm wrapping this in the function because this is, it needs to be an async function. So I'm going to repaste everything I had in there. So this is now inside of this like handle wallet connect. And what I'm gonna do is await provider dot send, and inside of this I'm just gonna send two arguments. First is just this eth underscore request accounts, and then an empty array. Again, just boilerplate code. We're not gonna worry too much about what it's all doing completely, but this is how I would request access to the account inside of MetaMask. So let's drop a button in here that handles this. roll it, connect, call it, and we'll just have an onClick handler, which will handle wallet connect. So we have our connect wallet. And when I hit connect wallet, MetaMask is gonna pop up saying, hey, connect with MetaMask, select the accounts to use on this site. So right now I just have one account. I hit next.
Displaying User's Public Address
To display the user's public address in the UI, you need to use the signer and address methods provided by Ethers. Dive into the Ethers documentation to understand how to access the address from the Signer method. Take 10 minutes to explore the documentation and figure out how to display the user's public address after connecting to the wallet.
It's going to tell me what this website is allowed to do. So I'm trying to connect to Localhost 3000. This site will be able to see my address, my account balance and activity and suggest transactions to a group. That's cool. We're gonna hit connect, connecting, wonderful. So to verify that I'm connected on the current website that I'm on, there's this like little green connected circle over here. Cool. So that's step one of, you know, connecting to a wallet. What I want you all to try to do is actually take the, your specific addresses and display it in your UI. How are you gonna do that? I'm gonna give you a couple of hints. So you're gonna need some type of state, you know, use state from React. So I'll give you that part since that part is not too important. So just importing use state from React. So you're gonna grab an address, you're gonna set an address, and to do that, you're going to use two methods given to us from Ethers. Take a look at the signer method as well as the address method given to us from Signer. So when you have both of these when you're able to actually access the address from the Signer method, what you're going to do is create like an h1 down here that just essentially displays the address whenever it is available. So you're gonna have to dive through the documentation of Ethers for a little bit, but I told you already what you need to be looking for, you're looking for Signer and from Signer you're gonna get the address. So your job right now for the next, let's say 10 minutes, dive through the documentation, take a look at Signer and address and figure out how after you have connected and ask permission for access to the wallet to display that person's public address in your UI. So, I'll give you all 10 minutes starting now. It is 1 29 p.m. EST for me, so we'll reconvene at 1 39. I'll just leave those two hands inside of the chat as well and the link to the documentation, so 10 minutes.
Connecting Wallet and Contract
To connect the wallet, we need to get the signer from the provider and the address from the signer. The signer object is obtained by calling provider.getSigner(). The address can be retrieved by calling signer.getAddress(). This address can be used as a decentralized way of tracking identity and enabling single sign-on experiences without relying on traditional OAuth providers. Different types of wallets, such as hardware wallets, can be used to connect to the browser wallet. The next step is to connect to the contract by declaring a contract address and creating a GM contract object that will have the different methods available for interacting with the contract.
Cool, no worries. I can go ahead and show you how that would work out. So, the hints that I gave was that the signer is something you need to get from the provider and then the address is something you get from the signer. So, provider itself has a method called get signer which will return to you a signer object. So, let me say const signer. equals provider.get signer. That is a function, so we just call that function, just returns to us another object with the ones of methods. Then the address is available from the signer. And address, for address, we're going to await signer.get address. Signer.get address returns a promise. So we just need to await it. And then we can just like set, so instead of address, we'll just call it like my address or something. Then we'll say set address, my address. Cool. So if I head back here, connect my wallet, I should now see my address showing up as the H1 value that we had up there. So again, just to recap a little bit. This is, again, according to the Ethers documentation. Signer is referring to the person who is interacting with the wallet that is connected to your site. So we wanna get more information specifically about that person. The information that we find most useful for us, which we'll see why in a second, is their public address. So this is publicly available information. To get that address, we just have this method called signer.getAddress, which returns a promise, which resolves to a string of their address. Then I'm just using this setAddress to set myAddress value to the address value here, which is being used in the H1 on line 23. Any questions there so far?
Okay. Cool. So now we have a way to identify somebody who's connected to our site. Now, this next part we're not gonna do from a coding perspective, but I wanted to introduce this concept to you. This concept is one of the, at least to me, like when I was first learning about Web3 it was one of the coolest things about it, was this concept of signing in with Ethereum. So MetaMask, like I mentioned before, this is for EVM-based blockchains. Blockchains, Polygon is one of them. So we use this. So it's named Sign in with Ethereum for that reason. Sign in with Ethereum just means that you have this address, right? This address that represents like who you are, it's tied to you, your onchain activity, any funds that you have. And we can actually use this address as like a true kind of like single sign-on experience that is not tied to the actual blockchain experience. To like some third party entity, right? Because once you have this wallet and this wallet is yours, this public address is yours, this is how you can be identified on a blockchain. From here, we can use this and replace like some, you know, traditional OAuth providers like logging in with Facebook, logging in with Google, with just like signing in with Ethereum. You know, there's no need anymore to have to trust a like third party service to like manage your data, manage your system. This is like one of the first key components that you can add to an application to make it more decentralized. So you can have like an actual sign in experience that doesn't require someone to create an email, username, password or sign up with like Google, Facebook, Twitter, whatever kind of like OAuth provider that you use. This is like a truly decentralized way of like tracking identity and using that inside of an application. You know what you do with it going forward from there it's kind of like up to you. Like, do you want to go to the traditional route of like, I don't know, saving these wallets as usernames inside of a database having some like JWT token and stuff in there. Whatever, like going beyond that is up to you what your implementation is for like how authentication would actually work for your application. But you don't have to, you know, rely on, you know, any of these providers to just have that single source of like signing in. And you provide like a really, at least in my opinion a really good user experience for signing into new applications because I can just take my wallet and sign in wherever I want. Cool. Any questions on that?
Yeah, I see that when we are using the extension it has some sort of messages to using the hard wallet. So how does this change when trying to like connect to a hard wallet from like the browser? Do we face any permission issues or anything like that? They'll just be like some different like levels of configuration, at least in your code. That's actually going to be one of the things I talk about later in the workshop when we look at like improvements that can be made to specifically to this app. But yeah, we're using a wallet in our browser extension, but there's different types of wallet. You can use mobile wallets, you can use hardware wallets. I actually have a hardware wallet here. This is my ledger, which is basically replacing the Chrome extension in my browser, but you can like link it up to your browser wallet if you want to, and then, you would just basically like approve trend. Like instead of you clicking and approving the transaction of adding things to your wallet in the browser, you would just like do some clicks here and it would connect that way. There are SDKs for helping you to do that. We'll talk a little bit more about what those SDKs are later. Oh, nice, nice. Well, so now we have a way to connect to the wallet. Now, what I want to do is connect to the actual contract that we're going to be interfacing with. So first thing, I'm just gonna go back to a polygon scan and copy the contract address you can click the little clipboard button here. It'll copy it for you. And in here, I'm just going to declare like a variable. We'll call it a contract address and I'm just gonna say, that is this long address here. In like a real world application, you might want to save this in like a dot ianv file or something like that. And essentially, you know, we're not gonna worry too much about like the real world use cases, but yeah this might not be the best way to save your contact address in an actual application, but for the purposes of this workshop and to keep things a little bit easier, this is what we're gonna do. Next thing I'm going to do is create another piece of state. We're gonna call it the GM contract, so GM contract. And this is just going to be an object that is eventually gonna be returned to us that is going to have the different methods available to us from our contract. So if we look at the code or the transactions here, for us to be able to call this answer method, this tip method, withdraw method and everything, we want to have a way for us to get the transaction to have the different types of methods we want some object that has all of those functions. And this is eventually where it's gonna live.
Connecting to the Contract
To interact with the blockchain, traditional HTTP requests like Axios or Fetch won't work. Asynchronous work is involved. When interacting with the blockchain, you need to understand that it's not the same as querying a backend server. It requires a different approach.
How do we get there first? So now that we've got the signer and the address, the next part of the equation is to get connected to the contract. So before I actually do that, we need to kind of like, understand and conceptualize like one thing. Traditionally, when you have a front-end that is like querying some backend server, you would use something like Axios or Fetch to actually interact, read data or post data, whatever, what have you. It doesn't work the same way exactly when you're interacting with the blockchain. You're doing some asynchronous work, yes. And I should probably spell things correctly, but you're not doing like a traditional HTTP requests.
Connecting to the Smart Contract
To interact with the smart contract, we need the contract ABI, which is a JSON file that lists all the available methods and their outputs. The ABI code is essential for establishing a full connection to the smart contract. It is important to ensure that the ABI file is verified. Once we have the ABI, we can create a connection to the contract using the ethers library. This connection allows us to access the methods available on the smart contract.
If we come back to the contract on polygonscan.com and go to the contract tab and scroll down, you'll see this thing called the contract ABI. I'm gonna hit the little copy ABI to clipboard button to copy that and I'm going to drop this into our code. Inside of source, I'm going to create a folder called utils. Inside of utils, I'm gonna say, there's this file called abi.json. I'm gonna post paste that, format that a little bit so you can see it. But now we have this, like JSON file. In order for JavaScript to actually be able to interact with like the byte code, like the machine readable code, we need to have the way that I like to look at it, this is a map of like all of the different methods that are gonna be available to us within this function. So if we take a look at some of the things inside of this JSON object, let's see, different inputs. Let me see if I can find one that's easy to explain. Okay. There's this get prompt. Remember we had this like get prompt function where it like just returned to us a string value of what the current prompt is. So get prompt is a function. What does it output? It outputs a string, and it's a type of function. Does it actually mutate state? No, it's just a view function. It's just to like get some data. Right? So this like, is just this is a JSON object detailing what each and every function inside of the smart contract can do, what it outputs, and whether or not it mutates any state. Cool. You need to make sure that this ABI file is available to you in order to make the full connection to the smart contract, which is another reason why this green check mark is so important because you will only have access to ABI code that is verified. Cool. Questions about ABI code. it's a JSON file and it just lists the methods on the specific contract. That's like, I guess like the simplest way to look at it, hopefully. Cool. So we have access to our ABI. Now to actually establish the connection with this contract.
Interfacing with the Smart Contract
We create a new variable called connected contract using methods from the ethers library. We create a new ethers contract using the contract address and ABI. The signer is used to connect the wallet and interact with the contract. Once connected, we can access the methods available on the smart contract. The contract address and ABI are generated by the person who built the smart contract. The ABI is a JSON object that lists all the available methods. Once a contract is deployed on the blockchain, it is immutable. Upgradable contracts allow for updates by pointing to a new contract. The ABI is generally generated during the compilation process of the smart contract. It is verified on platforms like Polygon scan. Now we can start interfacing with the contract by creating a form component.
So I'm going to create a new variable. We're going to call it connected contract. And I'm going to be using some methods, again, from the ethers library. Again, also available through that documentation link that I sent over. We're going to create a new ethers contract. So ethers that contract, ethers.contract is going to take three arguments. First, the contract address, which we saved up here. Second, it's going to take let me see what it takes. It's going to take the ABI. So this ABI.json needs to be imported. So let's import it up here. Import ABI from jtos. ABI.json. So second argument is going to be the ABI. So we have a connection to, so we have the address of the contract. Where does it exist in the blockchain? We have the ABI. This is our map. This is like the different methods that we want to be able to use on this contract. And then finally we need to pass the signer. Signer again is just the person who is interacting with our wallet. We wanna make sure that they are able to connect to this wallet and actually use it. So once we have these three pieces of information we can have this connected contract object which will give us access to the methods that are available on this smart contract. So I'm just going to, once this is connected say that we are setting the GM contract to the connected contract. And I'll just counsel log out what that looks like here. So we'll just say, counsel log, GM contract. Cool. So let's head back to our, all right, hit connect. Cool, connected. And now you'll see this contract has a whole bunch of things in it. Some of those include the prompt, like getting the prompt, the tips functionality, setting the prompt. The address of the function, this answer function to actually answer everything. So all of the stuff that was available on the smart contract on the UI and polygon scan is now available to us from this object. Does that make sense so far? Any questions up to this point?
What happens if the contract changes a function is added? Would we need to copy the API JSON into our project again or can the contract not change? Awesome question. So generally speaking, the second part of what you said is correct. A contract once it is deployed on the blockchain cannot change. If it needs to be updated, generally you would deploy like maybe a new contract and essentially you'd have to update both the contract address and the ABI code from the new contract. However, there is this concept of upgradable contracts, which again is more of an advanced concept that would require a whole other workshop, but what you can think about it is sort of looking at it this way, is like generally when we deploy a contract onto the Ethereum mainnet, Polygon mainnet wherever, once it's there, it's live, it's done, it's immutable. But there's this concept of proxy contracts, so you can have a contract that can be sort of like updated to point to some other contract and it can inherit like the values and everything from that other contract, right? And then expose like whatever that contract is. While a single contract on its own is like it's immutable, you can create a contract with a function that updates certain pieces of state. So one of those pieces of state could be a pointer to some other contract that has some information, right? So in that way, if you needed to do something like updating because of a bug, which is an issue I had when I was creating the source code for this. You could have it point that proxy point to the new contract, but like on, I guess, like the front end, you would still just be pointing to that initial contract or whatever. And otherwise, once it's on the blockchain, once it's on the blockchain, it's on a blockchain. That's why there's like a lot of things like security audits and things that happened before a contract should be put on to production. They don't always go through those audits, unfortunately, which has caused a lot of unfortunate security things because people don't follow security best practices all the time. But yeah, there are methods of creating upgradable contracts, but generally speaking, once it's on the blockchain, it's immutable. Philip has a question, who creates the ABI, is it Polygon scan or the owner, especially the creator of the contract? So yeah, so that ABI code is generally generated by the person who built out the smart contract. So, when I built this smart contract, I used a tool called hard hat, which is a JavaScript SDK for like creating environments for building your smart contracts. So, when I did the verification of my contract on a Polygon scan, part of that process was like automatically uploading and updating that ABI code. But that, when you compile a smart contract to be pushed out into production, like I mentioned before, you have your smart contract in Solidity. It's a very high level language and needs to be compiled down to byte code that's actually machine readable by the EVM, like the Ethereum virtual machine. So that byte code, when you generate that, you also generate the ABI, which is again that JSON object with all of the methods. So that's exactly like a source map. So that's when you would get that generated and like verify on Polygon scan or either scan depending on where you're building. Awesome questions y'all, awesome. So now we are at the point where we can actually add a little bit of interfacing with the contract. I'm going to, in my source folder create a new folder called components. And inside of components we'll create gmform.js. gmform.js. So let's just. gmform. I'm just making sure we have the scaffolding out. It's going to return for now just an h1. That is, this is the form. Where we'll just say this is an h2, I'm going to move the address down here. So one of the props this is going to take will be address. Oh, yeah. Wrap things. Making sure I spell things correctly.
Building the GM Form and Displaying the Prompt
Wrap things. Making sure I spell things correctly. Default GM form. Displaying the address as long as we find them. We're connected and have an address showing. The first thing we're going to do is build a latitude contract. Let's figure out how to display the prompt first. We create a function called getPrompt and answers. We use useState and useEffect to grab the prompt. We replace the h2 with the prompt. We have established a connection to this contract and have the Sage EM approaching, displaying here.
Wrap things. Making sure I spell things correctly. Default GM form. So now I'm just going to do like a ternary over here. This. I'm gonna show that GM form. It's gonna take that address. So let's remove this h1 over here. And if we don't have it, and we're just gonna deploy that button. Connected wallet, yay. I have the address showing, and this is the form. So we're just displaying the address as long as we find them. We're connected and have a address showing. Nothing blockchain specific there, just some React stuff. So we're gonna continue doing our work inside of this GM form. The other thing I want access to inside of this GM form is going to be the GM contract. Let's pass that down as props as well. Cool, thanks, Steve. Anyways, I'm gonna stop there. I've been talking about this for a little bit, but you can go ahead and start building stuff now and be ready to continue working with the software. So Dawn, are you ready to do that? I'm gonna go ahead and open it up, and then we'll start building it. You know, I like reading about it.
So, the first thing we're going to do is build a latitude contract. So in Factoryprehension, contracts that show up in this website are greeted with a specific prompt. In our case, it starts off with this sayGM prompt. So let's figure out how to display that prompt first. So... Okay. There's a couple of things I'm gonna need during the development of this form is gonna be useState and useEffect. Get out of your act. And what we'll do is that we'll do a useEffect here and then just like onMount of this component, I'm gonna grab that prompt. So whenever someone lands on this component, we should display that prompt. So that prompt we're gonna create a function called getPrompt and answers. For now, it's just gonna get our prompt, we'll do the answer part in a little bit, but getPrompt and answers, it's gonna be an async function. And first thing we're gonna do is getPrompt. So const getPrompt equals await GM contract dot getPrompt. Essentially, any of the methods that you use from the GM contract are always gonna return promises. We always have to wait for reading from the blockchain, transacting with the blockchain, et cetera. So that's why I created this asynchronous function here. And then let's put some state up here. Let's do something like a const prompt and set prompt. And that will be use state. We'll start that off as an empty string. So getPrompt is going to await gmContract.getPrompt. And then we will take the value from there, let's name this something better, or let's just current prompt equals await gmContract.getPrompt. And we're going to set the prompt to be that current prompt. Down here, we'll replace this h2 with the prompt. Again what we're doing, let's make sure that we call this function. So I'm just using this pattern instead of use effect where we define an async function and call it right away. So get prompted answers. Prompt. Okay. Wonderful. Hit connect wallet, something went wrong. Let's see what went wrong. Use date is not a function or is returned value is not a variable. Oh. Did something wrong in here. Prompt, send prompt because use date. Import needs to be adjusted. Oh yeah. Oops. There you go. Thank you Kayla. Cool. So we have Sage EM displaying now. If we recall from before, if we go back to our polygon scan contract and hit read contract, we can see that get prompt returns Sage EM. Cool. So we've established a connection to this contract. We have this Sage EM approaching, displaying here.
Displaying Answers and Adding New Ones
In this part, we will add functionality to display the answers to the prompt. We will retrieve the answers from the smart contract and map through them to display the answer and the address of the person who added it. We will also create a form to allow users to add their own answers to the list. The form will include an input field and a submit button. We will handle the form submission by preventing the default page refresh and wrapping the code in a try-catch block. Transacting with the blockchain can take some time, so it's important to provide feedback to the user during the transaction process.
What I want you all to do now is do the same thing, but for get answers. So the same sort of like method that we used here of like taking like the GM contract, accessing, you know, get answers instead of get prompt, and then iterate through that and get an array that gets returned and display all of the answers below this H2 over here.
So I will give you all, let's say seven minutes for that. For me, it is currently 2.10 p.m. EST. So 2.17 p.m. EST is when we will reconvene. Again, same thing that we did here where we're doing this get prompt and answers, add a couple of lines of code here where same way that we got the prompt, we're now going to get the answers. You're probably going to need to create a new piece of state to hold the answers. And yeah, I will give you all, let's do eight minutes just because I want to make sure we get through the rest of the stuff.
Okay, so I'll go over what we need to add to start displaying the answers. So when we actually get the answers back, there's a couple of things that will be given to us inside of the array that comes back. That's going to be the answer, like the actual data, as well as the answer of like who added that answer, specifically their address. So we're gonna go ahead and display those two things. So inside of getPromptedAnswers, I am going to create a new variable called currentAnswers, is going to just await gmcontract.getAnswers. GetAnswers. We'll have a new piece of state up here. We'll say answerList. answerList, setAnswer in this. We'll just, give each state with an array. And we're going to set the answerList once we have gotten the current answers. So setAnswerList is going to be the current answers. Down here, what we're going to do is display those. All right? So we'll take the answerList, and we'll just map through those. For each answer, we can do two things. Those two things will be the actual, I guess, answer or message, we'll say. That can be accessed through this a.answer, so the actual answer itself, as well as who it's from, which can be accessed through a.from. I'll also just console log out the current answers up here just so we can explore that a little bit as well. Cool, let's head back here. Wonderful, so we have the GM react summit I did this morning. This is from my address. Looks like a couple of you added some stuff here, too, so you might recognize your address up here as well as the message that you gave in here. But if we open up the actual array, so this is an array of tuples or just like an array that has a couple of things that are inside of it. First, we can access, again, the address, who it's from, as well as the answer, and that would be true for each and every one of these arrays. There's two pieces of data in each of them. If you recall on PolygonScan, unfortunately, it looked like this like really weird bunch of data. But thankfully, once we actually get it displaying on our front end, we can format it the way that we like. And this is the information, with the message as well as who it's from. So we've got that side covered. Now, we're reading the data. Now let's actually try to transact. Do some additional messages on here. So we're gonna run through that. See, I think we've got like half an hour, so I'm gonna run through and maybe leave you all with a little bit of homework because there's just a few more slides I want to go through. But we wanted to actually do now a transaction, right? To actually add something to this answer list, I'm gonna create a form. We could create the form probably below the answer list or let's just do it above the answer list. And maybe a form, label. We can put insert a prompt, something and for the input, few things. Let's track this state up here. Maybe we'll say answer, set answer. We'll start that off as an empty string. So this input, we'll just have a value being that answer. Set answer on change. We'll just take the event. Set the answer to be e.target value. Make it a type text. Name it answer. Okay. We'll say it's required. And we'll have a button down here. Type submit. And maybe instead of displaying the prompt up here, the text of the button can be the prompt. And then on submit, we want to take the event. And we'll create a handle submit function now, but I'll just write it out over here first. Handle submit and take an event. So, cool. First thing probably to do in the handle submit is E.prevent default, so we don't have the page refresh when we do, when we do the form submission. And then everything else, we'll just wrap it a try catch. So, I'm gonna put a whole bunch of logs in this just so we understand what's going on as the transaction is happening because transacting with the blockchain can take a little bit of time. In a production environment, what you probably wanna do is update the UI a little bit, maybe add a toast or some type of messaging that says this transaction is currently pending.
Updating State on the Blockchain
To update the state on the blockchain, we create an answer transaction. We await the firing of the transaction and the validation. Once the waiting period is over, we log the transaction and set the answer to an empty string. The transaction confirms that it was added to the blockchain. We can also check the transaction on Polygon scan. To display and update the state in real time, we listen for the new answer event emitted when someone answers the question. Ethers provides a way to listen for events, and we'll be listening for the custom event new answer defined in our smart contract. We create a listener function to handle this event.
For the sake of time, we're just gonna do some console logs. So, console log entering. And, before when we were just reading, I just named these like current prompt, current answers, or whatever. When we do something that requires an update, it's called a transaction. So, a convention here to follow would be to say that this is an answer transaction. And what we're gonna do is await gmcontract.answer, which is another one of the methods available to us that we can check either in the console log or if you go into, where'd it go? Too many tabs open. Answer, which takes the input of string. So, gmcontract.answer is gonna take a string input or just give it that answer that we were tracking up here in this piece of state. This needs to be an async function. And while that's happening, we'll say console.log waiting for answerTransaction. And now this is a weird thing that you need to do whenever a transaction is pending. But there's a couple of things that happens on like the blockchain side, like the transaction actually executes and then it has to be confirmed by someone who's a miner or validator. So we actually need to await twice for both of those actions to actually take place. So first is firing off the transaction. Next is waiting for the validation. So to do that, we would say, await, answerTransaction.wait. This is just a convention that you would follow whenever you're executing a mutation, something that updates state onto the blockchain. You fire the transaction, you await that, and then you also await for the validation of that transaction happening. So once this waiting period is over, we can do console.log transaction.complete. And we'll just log out the transaction itself. Answer transaction. And we'll just set the answer at that point to be back to an empty string. If there's an error, we'll just console.log out that error. So real quick, once again, going through this, cause this is a little weird, ignoring all the console logs for now. I'm creating a transaction, I'm updating some state on the blockchain. So by convention, I'm just naming this answer transaction. I'm awaiting the initial firing of that transaction. I'm going to answer, supplying that answer from the state that I have up here. Then I'm awaiting for that transition to be actually validated on the blockchain. Once that is done, I can then console log out the actual transaction itself. So let's take a look at that. Hello from the browser. Say GM, and now you'll see my metamask pops up because this is a transaction. This is updating some piece of state on the blockchain. So there's going to be a gas fee that I have to pay. Again, in this case, it's 0.001 Matic, which is a fraction of a penny. Did this on Ethereum, this would probably cost like a few bucks. Okay, hit confirm. Now you'll see again, so down here I'm answering, I'm waiting for the answer transaction to actually complete. I can also check in my metamask. That, you know, this was pretty quick. So like the answer is done over here. So let's take a look at these values. So a few things, I get access to seeing how much of like, how much gas I used, there's a nonce. If you recall, like before, from that initial value that we use. And just like other bits of information that we're not going to worry too much about that data, the data is hashed into this like long string here. But what we, this is essentially confirming that this transaction went through and was added to the blockchain. If we take a look over here on polygon scan and go to transactions. Let me just refresh this 33 seconds ago, one second ago, I think maybe some of you may have done this too, but we have some answers that went through. Cool. So we have that confirmation. Now there is one other thing that I have to do to actually in real time display and update this. But for now, let's just refresh and make sure that this works properly. Add another gem again, Hello from the browser. High from the browser. Wonderful. Cool. So now we know that we're able to transact, add things to the blockchain. How do we actually display those in real time? Because if it's not like if we have to refresh every single time to actually read data. So how do we actually update that state? So one thing, and I'm just gonna go through this fairly quickly just because of time. One thing that is part of this contract that I think I briefly mentioned before is that there's an event, right? An event called new answer. And we emit this event whenever someone answers. So whenever someone answers this question on blockchain, an event is fired off. So we need to figure out a way to listen to that event. We know that it's called new answer because that's how it's defined inside of this smart contract. And if we look inside of the function answer, you'll see that we use this emit keyword and this new enter and it sends the address of the person who is currently interacting as well as whatever their input is. So we need a way to listen for that happening and in real time update the state. So Ethers actually gives us a way to listen for events. We're gonna be listening for a custom event that was defined in our smart contract called new answer. So to do that, first thing I need to do is create like a listener function.
Listening for New Answers and Further Improvements
We can listen for new answers by using the on function provided by GMContract. The listener function updates the state by adding a new object to the answer list. However, there seems to be an issue with updating the state correctly. Other improvements to consider include including more wallets, updating the UI with transaction information, learning about the graph for more efficient data reading from the blockchain, and exploring SDKs like Third Web for building decentralized applications without extensive knowledge of Solidity. Collaboration and participating in hackathons are also great ways to dive deeper into the space.
So listener is going to be defined in here. We'll just call it const listener. This is going to take two arguments, a from which is just what addresses is this from and an answer. We'll say console.log new action emitted. Actually no, don't worry about that. And what's just going to happen is I'm going to set the answer list. So I'm going to update the state to be to just spread the current answer list. And just add an additional object with the from and the answer. The reason I'm doing it like that is because in our mapping over here, we're going over looking for answer and from. So adding like the new values inside of an object should basically update that state and then allow us to use that in the state array. So where do I actually go in here? Where do I actually listen for this? In order for me to listen for this, GM Contract has, thanks to Ethers, automatically gets this on function. So that can be done in our use effect. So after get prompted answers, I'm gonna say GMContract.on. So now it's gonna be listening for something. So what do I want it to listen for? I want it to listen for new answers. Because again, new answers is the event that I defined inside of the smart contract. So new answer and the second function is just gonna be the listener function. We defined that, you know, from an answer or the two arguments that we want. These are the arguments that are gonna be supplied from Ethers. And we just need to make sure that we return gmcontract.off. It is like an actual, like, listener function. So we don't want, like, whenever, like, the component re-renders, we don't want multiple, you know, listeners running at the same time. So this will just, like, clear out the old listener. So this is gonna be gmcontract.off, new answer, again, passing in that listener. Cool. So now, let me refresh here. Cool, feel free, y'all, to add a message here while I'm doing this as well. But here is another message. What should happen now is that now, no matter which one of us actually answers in real time, we should see the state updating because we have that listener function. So we can hit confirm. We're answering, waiting for the transaction. Yeah, this is, you know, one of the improvements you can make is like creating something on the UI, a toast or something that says, hey, this is transacting on the blockchain. Please wait for a little bit. Saying, cool. Okay, I probably did something wrong in the actual spreading maybe of the function, but here's another message came up, so that's good. Let me see what went wrong. Answer list, I mean, it looks right. Hmm, okay for some reason I'm like overriding the state, but the listener works. We can probably go in and debug why. It's not, whatever I did wrong when I was updating the state, but the listener works, which is great. We can debug the set state later, but for now some of the other things that you could definitely do, I highly recommend just like going through like the rest of this contract, adding in like, you know, some of the other functionality with the tip and everything else, that could be maybe something you could take away from here and work on kind of on your own. But again, it kind of, it really just works on the same way, right? You now have this GM contract, which was given to us when we connected to the Ethers provider and provided like this connected contract with the contract address, the ABI and the signer. Once you establish, you know, that initial connection, you have access to everything that is publicly available on that contract. Sometimes there are private functions on contracts, which you won't have access to, but anything that is publicly available is just available through this contract object, which you can play around with here. But that said, I wanted to just call out a few more things that we can talk about very quickly. So some improvements that we can make to our front end. You know, first is in including more wallets. So we touched on this a little bit with Philip's question earlier, but there are different types of wallets, right? It's not just like a MetaMask wallet, it's not just wallets that exist inside of your browser. You might have a wallet like this. You might have a wallet on your mobile phone. You can look into different SDKs that help you connect to more types of wallets. A lot of those are built around this Ether's libraries, so like you'll already have kind of like the base knowledge of like how to use Ethers in that case. You can look at solutions like RainbowKit, which helps to connect to multiple wallets. I think under the hood, it uses something called Wallet Connect, which is maybe when you were playing around with Polygon Scan, you might have seen that as like a different option for connecting your wallet. Wallet Connect, I think connects to like almost every possible type of wallet that exists out there. So definitely wanna make sure that if you're building out a UI for a smart contract that you're able to connect to as many different types of wallets as possible. I mentioned this a couple of times is updating the UI with transaction information. Add UI elements like spinners and toasts to help the user understand what is the current state of their transaction, right? Third, this is like kind of like if you wanna really go further down the rabbit hole, learn about the graph. So reading from the blockchain can be pretty slow and like not fun. Like if you saw like the little kind of hacky workaround I had to do to like get real time updates for our state. This can be done much better utilizing something called the graph. So the graph, what it does is it indexes information available on the blockchain and makes it available through that GraphQL API. So if you're familiar with GraphQL, this might be a good way to like just help you do reading transactions from not transact, just like reading data from the blockchain. So rather than having a whole bunch of getters and stuff everywhere, you can have like one uniform kind of like GraphQL API that indexes your smart contract. You can definitely take a look and go down that rabbit hole further if you would like. And like, if you're interested in building like full stack decentralized applications with blockchain, and you don't necessarily like wanna dive into solidity or like learn a whole new language, there are SDKs out there. One of those, one I like to use a lot called Third Web. With Third Web, you can leverage both low and no-code solutions as well as different SDKs for in the JavaScript. They also have SDKs written and like Python and a few other things. And it allows you to create your own smart contacts, contracts without, I think a lot of the time, like you don't really have to know any solidity if you don't want to. So if you don't have a lot of solidity knowledge, but you want to dive in and like start building, this is a good place to start in my opinion. And really just like, if you want to kind of like go forward and like try building some stuff, I think some of the best ways to like really dive into this space is just to go out and collaborate with others and start building. My company Polygon, we're putting, we have a, we have currently going on right now, a hackathon that has last, that is going to last over the next two months. Lots of people still need team members. There's like $500,000 in prizes that we're giving away and different tiers of prizes from different sponsors. So if you want to like dive in, learn a little bit more, start hacking away with other people. This is a virtual hackathon that takes place over two months.
Comments