Building SmartContracts With #Solana and #Rust

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
all right guys i'm back another day another video so first things first i would like to thank everybody who purchased the book and supported the channel um truly grateful for all of your support and for anyone who is still considering buying the book but hasn't yet you can get a 20 discount by using 20 fulls as the discount code so let's get started um so part of the reason why it took me such a long time to get back to making videos is i was doing a lot of research as to which blockchain i wanted to build my next app on so you may recall that i was intending to rebuild dz haven as a decentralized application i didn't like holding on to the bounty funds myself that just did not make me comfortable so you know i want to take advantage of the ability to allow people to control their own funds even if they're staking it somewhere so um after doing some research initially i settled on ethereum because you know it's the most popular solidity as a smart contract programming language is very well known so as i went through the process of learning it i realized that the scalability and the high transaction fees just um aren't gonna do it for this kind of application if any kind of social media application whether it be mine or something else that has the potential of getting you know tens of thousands hundreds of thousands even millions of users is not um 12 14 transactions per second you know it's not going to work and then on top of that the high fees i mean sometimes i was paying twenty dollars for a transaction uh some people have said that they were paying fifty dollars a hundred dollars for a transaction um you know somebody just simply trying to stake their money for an app um obviously those kind of fees just wouldn't work so after doing uh some more research i looked at polka dot i looked at cosmos um i kind of stumbled onto solana um and i realized that actually it's the fastest blockchain in terms of transactions per second that is currently out there it totally basically blows everything else away currently they're at 51 000 transactions per second which is actually um almost identical to visa a centralized product obviously um in terms of other blockchains hedera hashgraph is at around ten thousand and nano is at around seven thousand so in the blockchain space nothing you know even comes close and according to um the solana guys their longer term plan is eventually to get to seven hundred and ten thousand transactions per second um which would actually be even faster than the nasdaq i believe the nasdaq is somewhere around five hundred thousand um and they say that the only thing stopping them is um that all nodes have to be on at least one gigabit ethernet in in order to make that possible so um you know this level of scalability is is just incredible um on top of that because i think at least in part because it's so scalable their fees are just ridiculously low usually it's a couple of cents or less um in my experience it's always been under a penny but um as this as this article shows um you know i'm not the only one who realized this so the attention um to solana has increased substantially and their token has just skyrocketed so um yeah that may change the the cost of transactions but they're still gonna be in you know the few cents range um even with this uh run-up so um i think the answer for me was pretty clear to go with solana and so that's what i've chosen and in this video i intend to um explain some of the con concepts of how smart contracts work in solana and the rules around coding for solana and then i will get into um explaining this example hello world application uh line by line so that it's very clear you know what's going on and then after doing that we'll modify the smart contract and some of the javascript code so that unlike this example which actually isn't sending any data to the smart contract it's simply taking the existing data that's there in one of the related accounts and just incrementing it so we're actually going to modify this sample program to send some information over save it into a related account and then read it back from the client code so that's what we're gonna do today um so let's get started on that so um i talked about how scalable solana is um the sole tokens have just gone bonkers multiple times um you know increases which is pretty common in blockchain so let's get into how we uh start coding for solana so solana is um solana smart contracts which are internally called programs so when you guys start reading the documentation you're not really going to see smart contract you're just going to see programs and that's their name for smart contract but solana smart contracts are written in the rust language now probably most of you guys watching this video aren't familiar with rust but um so that may kind of turn you off possibly but um i would like to say that it's far better that they picked a general purpose language to build their smart contracts with than a specific smart contract language like ethereum did with solidity because once you learn solidity granted there's other blockchains that that use solidity but you're constrained that the only thing you can do is build smart contracts with solidity and that's it right you can't do anything else with that knowledge that you've gained but if you learn how to um code in rust you can basically build almost any kind of application that you want in fact rust in terms of its usage and popularity has also been skyrocketing um similarly to solana so recently facebook has decided to join the rust foundation which is a foundation dedicated to promoting and improving the rust language now why that's super interesting is because amazon web services google microsoft mozilla huawei is a gigantic chinese electronics company all these companies had already joined the foundation and um even even better than that all these companies are internally using rust and building on rust for their own internal systems so what i'm saying is learning rust is actually whether you use solana or not is is actually a benefit to your own career so you should definitely consider it okay so in order to do solana programming you need to have rust installed you also need to have node installed because the client side the only existing client-side framework currently is web3.js solana web3.js and obviously that's written in javascript and the um the projects that you're going to be building are going to be npm packages so you're going to have to install node um install rust and then once you do that you're gonna have to install the cli the solana cli so this is their documentation website it's um overall it's pretty good i think that it needs some more fleshing out certain um i guess edge cases uh certain questions about well you know what do i do in this case or or what does that mean um at a code level at least when i was re reading it it wasn't entirely clear to me which is you know why i'm making this video but um overall it's it's gonna give you a good overview of solana and how to code for it so like i said before you can you're gonna have to install um the cli um it was pretty easy for me i'm on mac os um and linux seems like it's basically the same process but on windows it seems to be a little bit more involved um if you have any uh problems installing or running the command line tools just leave a comment and i'll try to help you out just be aware of one thing once you do the install you're going to have to pick a specific network whether it be the test net the mainnet or the local test net you want to always make sure that your cli and that network are on the same version from what the guys on the team told me um you know it's it's better to be on the same exact version because they're making a lot of changes and sometimes things will break um so try to make sure if you are having problems that you verify um that you're on the same version and i'll show you a couple of ways to do that so once you have um done that i'll show you a couple of things um let's see here so once you do that you'll be able to interact with that cli so as an example if you run this command you're going to be able to see again your local server right so this is running the full solana blockchain but as a test bed on your local machine so it's giving you all the pads related to that and then this is going to be a key path to your own wallet so i believe when you install the the cli you're gonna get this automatically but if that doesn't happen for you you can just um yeah this is the guy so you can create in here it's showing creating a secondary address to an existing wallet but you can create a brand new wallet and put it to a specific path that you want to put it into but i would suggest sticking with the sticking with this default path here um if you need to generate a brand new wallet so um this will get you your local configurations this will get you the version number of the cluster that you're presently um set to okay so my cli is 166 my local cluster is 166 and this shows you which cluster you're pointed at but if you want to point to let's say mainnet or some other cluster then you would use the set command and then point to that that cluster so here i wanted to show you this because um obviously when we're doing uh development we need uh metrics and we need logging information about what's going on right so in order to enable being able to see those you're going to want to have this environment variable set i put it into my bash profile but basically have all these values set or else you might not be able to see certain log traces so then once you've done all of that stuff you want to turn on the local instance of the network right now i just turned it on but there's nothing going to be showing up until you actually start sending instructions to the network one more thing the the solana team calls each network a cluster which is a which was a little bit confusing to me because i have um you know i think about something completely different when i hear the word cluster but basically mainnet is its own cluster they also have a devnet for um when you want to actually deploy out to the network the testnet is sort of the last step of testing before you deploy out to the main net and then of course you have the local net so each of these things are just known as a cluster so be aware of that now initially when i turned on my local cluster um and you know i built my smart contract and i deployed it and i was running it and stuff i couldn't see any logs and i didn't know what the heck was going on so it turns out that additionally you need to run this command in order to see your distinct log statements so this thing is really just showing you sort of um ongoing messages uh that are coming from the runtime the network itself and this is going to show you the explicit log messages that you you know put into your smart contract so when we go into the code i'm gonna show you exactly what i mean but just you know definitely be aware of this because obviously it's gonna be next to impossible to debug your code without logs so this is super important to know okay so we've seen all of the major pieces of what it what is required to get started and then the sample project that i am running is probably the easiest one that they have and you just you know clone it off of kit like this um so this is the one that we're going to be working off of so again it's in the docks in the in solana and let's get started okay so the first thing that i want to show is that in the npm package.json there's a bunch of scripts that you can take advantage of to basically shortcut things like where is it the the build process and kicking off the application so when you run the uh the build for the program itself it's gonna execute this command and dump out the smart contract right here the compiled smart contract so then if you need access to that file you can find it right here in disk programs so if we look at the smart contract itself as i stated before it's using rust as its programming language which again i do think is a plus so before i get into the specifics of what all this code means let's do a quick sort of high level overview of how um executing a smart contract will work so at a high level um the base element inside of solana is something called an account and the account is like an account in any other blockchain so the data that is um [Music] being stored in the blockchain is living inside of the account so you're not just putting data arbitrarily directly into the blockchain you're putting it into an account and that's how it has existence in the blockchain and then of course the accounts also hold the lan ports um the money that the account possesses so kind of the unique thing about accounts within solana is that like i said everything is an account and therefore even this smart contract will actually be living inside of an account so this smart contract um in its binary form is actually going to be the data of some account so that's definitely something to be aware of and then also on top of that um sort of in symbiotic fashion an account that is every single account that exists in solana is actually having to be owned quote unquote uh by a program so just like a program lives has to live or has to gain existence um in solana by living inside of an account every account um if it is to be accessed and modified and used must be owned by a program so this ownership because i want to make this clear is not the kind of ownership that you might think of for some other blockchains which is uh that a human owner um owns an account by being the possessor of the private keys so you still have that concept and that capability but in solana that is known as a holder so the account holder is the human that has access to the private keys for ownership or specifically the owner property that exists in in an account object that has to be some program so the only way that an account's data can be modified or the lan ports the money that is in that account the only way it can be debited is if the program that owns that account again is equal to the owner property of the account is um the one doing those actions so super important uh facts to know and i just wanted to clarify that before we get into the code so then the other thing to note and to be honest when i first found out about this i didn't exactly know what to think about it i thought that it might be a negative but nevertheless um in solana accounts are charged rent in order to exist on the blockchain now initially when you hear that you might kind of think of it negatively because you know you're if you're paying rent you're constantly having to maintain that rent balance in order for your account and its data and even its funds to exist on the network right um but i think that the reason why that is actually very necessary in the case of solana is because their ultra ultra high throughput their transactions per second and then the combination of their extremely low fees uh makes it quite easy to get spam and um really just a bunch of useless data um you know being stored in their blockchain so over time with that kind of throughput which as i said before is only going to grow so they're they're very ambitious about how far they want to take their tps right to 710 000 transactions per second and beyond so you can imagine that over time this could literally be just multiple petabytes and even way down the road exabytes of data right so in order to keep things sane and reasonable and useful in terms of the data that's on the blockchain i think charging rent in order for data to be maintained on the blockchain is the right thing to do so um there is rent that is charged to sustain your your accounts on the blockchain um there is a way to become rent exempt and basically you just have to have a certain minimum number of land ports in the account at all times then they won't charge you rent they won't um debit out any of your balance it'll just stay there um for as long as you you maintain that minimum balance and you know we'll go into the code of how how to discover what that exact amount is because it varies based upon how much data is being stored which of course is fair and and it makes sense but we'll get into that once we look at the specific code um on top of um being charged rent there is this a similar mechanism to ethereum's um compute limits uh in solana so in solana just like any other smart contract any other blockchain um you're gonna be doing you're gonna be performing various tasks um in your smart contract and again uh they call it programs inside of solana so your programs are going to be executing various instructions various commands and um in order to prevent uh performance issues and stalling of the blockchain they they give you a specific compute limit um based upon what you're doing um in the smart contract and that feature is you know no different than just about any other blockchain so just be aware of that and then i'll show you some methods to know exactly how many compute units you have left so during development you won't get you know caught off guard and then end up having your programs mysteriously fail because they're out of compute units so then um let's see here so then how exactly does um the smart contract how exactly do you run and what is the process of running these these contracts so basically um at a high level it's very similar to other blockchains you have a block that is sort of a master container for a set of arbitrary transactions and then of course inside of each transaction you have some metadata some accounts and then the specific instructions that you're going to be executing within that transaction so specifically a transaction contains the following members so it contains an array of signatures that may be needed in order to get the permissions to do various tasks within the transaction for example um crediting the lan ports that is taking it out of one account and then sending it off to another account and then of course writing into the data of an account and modifying that data so you have that and then you have something called a message so the message is um it's made up of multiple parts at the top you have the header the header is basically a um a bunch of metadata sort of like the headers inside of an http request so in that header you're going to have a count of signatures you're going to have a count of read-only addresses that require signatures and then you have a count of read-only addresses that do not require signatures and this is all metadata that is used internally during runtime to make decisions and to check permissioning and stuff like that so then after that you have an array of account addresses now this array of addresses is um required because when you launch your individual instructions those are the calls that are being made to the specific programs that need to do work so those programs will make a claim about what accounts um they're going to be accessing for various reasons during their run so as um a part of the check um those accounts that they claim to need access to must be listed out in the uh total array of all account addresses being accessed in the message so within that transaction um so that's why that is there and then there is a previous block hash that's also going to be there because as um actually i don't know if i mentioned this i think i didn't mention this but basically a big element of how solana works and how solana creates consensus and um maintains its security is by using time as a mechanism in part to do that work so they have something called proof of history as their concept consensus mechanism so they're um so solana is actually a it's in at a general level it's basically a proof of um uh what is that called a proof of stake consensus mechanism so in other words instead of doing a bunch of very um difficult uh math problems in a competitive way like proof-of-work does they have um staking as the main mechanism to allow nodes to participate and perform consensus on the network but in addition they have this other structure called sorry trains going by all right so they have um they have something called proof of history in addition to that um and i'm not going to go into depth into any real depth in explaining this because a lot of it is just way over my head but basically um instead of work this mathematical work time becomes a key element and a key method of creating consensus making sure that the data that is in the transaction and in the block is valid and being able to allow other nodes on the network to check the validity of the block so um providing that previous block hash is just going to be a parameter that the runtime uses to make sure that whatever is being requested during this transaction is neither too old or way into the future so it's just a quick method of of checking that within the transaction itself and again as the name implies it's a transaction so either every single thing within the transaction um completes successfully and if even one uh one instruction fails then the whole thing fails and gets um unwound basically so um that's what the previous block cache is about and then you're gonna have an array of instructions again these are the commands that will be launched from specific programs to do various tasks relevant to this transaction so inside of each instruction you're going to have a couple of different things you're going to have the specific program id so this program id is actually pointing to the account parent that is holding the program inside of its data but you need to reference that so the correct set of calls are being made and then again you have the list of accounts that you're claiming your program is going to need access to so these accounts again must be in that master list that i was referring to before in order for this instruction to be considered valid and then most of the time inside of the program you're going to do various checks um for example the owner check and whatever is specific to you to make sure that your program is acting on the correct set of accounts that they need to be acting on and then you're also going to have a set of parameters called instruction data so that is a binary array it's a u8 um array which is just a set of bytes um they're acting as parameters for your program so that you can execute something unique um to the specific time that the the program is run the the the data is in binary is in a byte array format in order to be open-ended so there is no um rule that you can only send specific types of data you can send any type of data that you like including objects strings json it's all your choice specific to what you need to accomplish in your program so cool that is the high level overview of the mechanics of how these uh programs are called and run and then let's look at the sample program in the example hello world uh project so if you go to program rust um there is a program dash c so you it is possible to write your programs in c um but i would recommend against that i think um as rust continues to gain popularity c and c plus plus are going to be um lesser used in my opinion specifically because of the memory protections that russ provides without sacrificing performance so um that's why i'm focusing on rust in the in this video but basically you go into the folder you're gonna find only one file there this is the um the code for your smart contract from the top if you're not familiar with rust this is just indicating all the libraries that you need access to um in order to make your calls into the salon solana runtime i'm going to explain this and all of the borish stuff in a moment but let's just kind of focus on the the core stuff of the program itself so um this is the entry point for your program so we'll see later that from the client side the javascript code that we're going to basically have a mirror of these three parameters and as you can see one of them is the program id that is the account that your program lives inside of that public address of that account so again i know i sound like a broken record but the program does not stand alone and yes this is representing your program but the program will always live and exist inside of an account which is what this is representing then in addition you're going to have the list of accounts as i mentioned before when i was going through what a transaction is the list of accounts that your specific program um claims to need access to and then you have that data that byte array right here of data that acts as parameters for your program to look at and make decisions on before it does its work so the reason why it's got this underscore in this case is because that's kind of the idiomatic way of indicating that a parameter although labeled is not going to be used and in this case in the in the case of this example project this instruction data is actually not being used at all as i mentioned before but once we go through line by line and describe and explain everything that's happening in all of this code i'm going to be modifying this program so that we can actually send in um actual parameters and make use of them update the data and then retrieve the data um towards the end of this video so moving right along this is the call to do logging so like i was mentioning in the beginning we want to be able to see the things that are happening and in what order they're happening values for various pieces of whatever parameters data whatever it may be so that all shows up you know after i've run this command and the code or the line that executes logging is this guy right here so um if you know rust you might have expected like print line macro instead of this message macro but they give you this instead they don't support print line because they say it's a little bit um not performant but uh if you're not um if you don't know rust um it's okay because uh we're not going to go too deep into rust because the the focus of this video is um solana but i will try and explain so sort of these sort of odd syntax statements so basically whenever you see something that looks like a function but ends in an exclamation what this is is a macro so all that means is that this is sort of a shortcut that points to a multi-line set of actual code like you see here um so it's just a shortcut way of using just a single command to get something that is much more complicated sort of handled for you or written for you by the compiler so that's what this thing is doing right here and with um just about any other printing or logging in in rust we can uh we can do string interpolation so if we did this this object which is you know not real but this object would end up showing up in here the value of it would end up showing up in here so we're able to do things like that with this logging statement if needed so at the very top we're gonna just let the world know that you know we've begun our smart contract it it has begun processing um here what we're doing is um this is an array of accounts that object type is called account info so solana as you've already seen by this array for the list of parameters is very low level and although that makes things you know a little bit harder to code for they do that deliberately for performance purposes and for flexibility purposes right so that the net effect of that is for example when you want to gain access into the accounts um it matters the order in which you place these relevant accounts and um you your smart contract has to be aware of that order and grab the appropriate specific account in the right order in order not to make mistakes so iter is just making this array iterable which just means that you take the first element you or you take the entire array and then you call next on it which gives you the the initial next element then when you're done you call next on it again which gives you the next element and so on and so forth so you're able to iterate through each element in the array and then this just means that you're getting a reference to a a mute immutable version of that array which is only required because we're iterating okay so then we have this iterable array that we grab and then instead of manually calling next next next next next we just use this helper tool this helper function to do that automatically for us so this just means every time this guy gets called it just gives me the immediate next account out of the array so in this case i this is the first time that i called it so of course i'm getting the very first account in this array and then this next call that's being made is it's taking the desired program and confirming that the owner of this account that i want to do something to right and we'll get into that over here but the owner of this account that i want to do something to is this program right so we're verifying that that is indeed the case and then if it's not the case then we log it so that we can see it on the console but we also send this error type to be specific about exactly what the failure was and again if this fails at any point then the entire transaction um that this was living inside of is gonna is gonna exit and unroll itself so let me just turn off the um the discord all right so and as i said before owner does not mean owner like a user with private keys it means the controller of the account the programmatic controller of the account so then okay let's say we pass this point so then what it what is it that we're trying to accomplish in this particular sample smart contract so what we're trying to do is we're trying to take the data that exists in it and again we can put in this is a byte array as well so we can put in whatever type of data that we want and we just have to be able to encode and decode it properly and i'll i'll explain how that works in a moment so that's this this stuff that you see right here but specifically once we get that data in its proper form right we this particular sample is just incrementing a number right so it's a pretty you know useless example but nevertheless it gives you some of the the knowledge about the the basic mechanics of how to do this so all it does is it increments this value this member value which is a part of this type and then once it does that it will so in this case it decoded the data so it went from a byte array arbitrary byte array and then it decoded it into its actual type instance then after doing whatever it is that it needed to do it's now taking it and encoding it back into the data and then we close off by logging that we're done again we have that string interpolation that we're able to send this value and inject it into here so um that's basically what this uh program is doing so let me explain some of this uh serialization stuff so up here you see that we're importing this library and borsch is um borsch is actually an acronym it stands for something like uh binary object serializer deserializer i forget exactly what the acronym is for but basically you get the point it takes a binary format and it either deserializes it or takes some sort of data type and it and it serializes it into the binary format so that's why these guys are being used and then in the case of the actual type um the data object itself is represented inside of inside of the accounts data right here as this object type right here so greeting account and inside of rust in the rust language there's really only um the type struct enum and tuple there is no class concept inside of rust because it's not really an object-oriented language but regardless this kind of um type a struct type is where you can hold data of various kinds so again that data being held is just a number in order to increment the number of times that this smart contract was just executed so it's not actually holding any real worthwhile data but for testing purposes it's it's fine so that's what they're using and then this stuff up here is again um this is a type of macro in the form of um uh an annotation so it's a lot like annotations that you would see in any other language typescript um c sharp java whatever um so basically it allows you to inherit or it allows this guy to inherit functionality from these three types without having to manually write the code yourself so any pre-existing uh function um uh function members or methods that exist in here will just be automatically allowed and applied to this type so inside of rust this is known as traits so traits are basically the same thing as interfaces or in swift they're called protocols so normally there's some manual coding uh with the impul keyword to manually write the code to you know inherit from these different traits but doing this is a shortcut way of basically getting the same effect so by by doing this we give greed a greeting account right here greeting account the power to encode and decode itself from the binary to whatever the type instance may be so one last thing before we exit the program so if you were wondering what this is um this is really an awesome feature in in solana um more than likely other blockchains have it but basically in solana you don't you do not have to create monolithic smart contracts in other words you don't have to create a single smart contract that does you know every single thing that you need your application to do so it's possible for smart contracts in other words to call into other smart contracts whether they be um a smart contract that you created or a smart contract that somebody else created but they make it accessible to um to other people so for whether it be for kind of trimming the amount of work that you have to do as a developer or better structuring your smart contract apps it's possible to divvy up for example your smart contract into multiple smart contracts because depending on the scenario you're not necessarily going to have to run all of the logic in your app at you know any given time right sometimes you may run only a certain set of instructions sometimes you may have to run all of them sometimes you may run some combination um of them including you know other people's functionality whether they they exist already in the run time itself or maybe some other third party created it um but nevertheless this this capability is a simple way of allowing this specific smart contract to be entered into and and controlled by another program so just make sure that if that's what you want that you have this in there and then you also need to put into your cargo.tamal the configuration file of any rust program so this is analogous to package.json in a node application so you need this and then you need um this in order to make that work all right so cool um down here is just the tests for this program but we're not going to get into that stuff in this video um if you do want to see that just leave a comment and i'll make sure to go over that in the next video alright so cool so this is how a smart contract is set up in solana and then if we go to the javascript so ts files are typescript files but effectively the same thing so this is what from the client side is going to be accessing the smart contract sending over instructions you know hey do this run this change this stuff like that um so this code is running off of mostly this library right here at solana web3.js um i do not know if they're working on a swift version of this api it wouldn't surprise me if they are they probably are but it doesn't exist as of yet so if you're wanting to run swift you would have to use the json rpc interface for that if you want to see a video on that i think more than likely i will do a video on that but let me know in the comments if you want to see that so as you can see even on the client side we do have to do the serialization deserialization and i'm going to show you that in a moment as well so um here's the thing uh this is called client right and definitely um running this from the command line this this is you know a client so to speak but just be aware that because this specific code right here does access the file system um which of course you know programmatically isn't allowed in a browser so the code as is is not going to run in say for example a react application um so just be aware that but in a sec in the next video in this series i'm gonna do you know a lot of modifications to this um example code uh because i intend to create sort of a payments uh messaging chat application so we're gonna move all of this code from the command line and we're gonna move it into a react app um to build like a more fleshed out realistic application so we're gonna see that in maybe the second or third video all right so um just like everything else you're gonna need to do some imports uh there's gonna be a lot more imports in the related files but basically if we start from the top the first thing that we need to do is make a connection and the reason for that is like i said we can choose which cluster that is which network that we want to be on for testing purposes right so this is going to make that selection for us and then give us this connection object that we can reuse so that we're always on the right network so then before i get into that let's cover some of these utilities so this is just a mechanism to do sleep because some of these calls since they are going over the network they can take you know a few seconds to actually finish so this guy will allow a pause of some time before continuing so then after that what we're doing here is we're trying to create um i don't want to say account so let me just pick my words carefully here we're trying to give ourselves um a certain number of lan ports money by requesting an airdrop obviously this is not going to work on mainnet this is only for testing purposes and then we're verifying that or we're trying to verify that that was successful now the reason why i wanted to pick my words carefully here is that this account that you see here is not an account okay so i just want to make that super clear this is not a solana account even though that's the name that this thing was given this type was given um this is actually a key pair meaning the private and an object that represents the private and public keys for an account for an account uh which will be created later so if you see this just don't you know assume that that's like a real account because it's not okay so i'm gonna look at my notes just to make sure i didn't skip anything all right so then moving right along we have this configuration information and this is this stuff right here okay it's this stuff right here and like i was saying before about the key path pairing for your own wallet normally this thing gets auto created when you um install the cli i'm i'm not sure because they're making updates all the time i'm not sure if that's still the case but i did show you early on how to you know set up a new wallet if you need to for whatever reason and then um i think i mentioned this before but there are specific pre-existing programs smart contracts on the the network already for you to make use of so this is a very important one the system program uh we'll get into some of the functionality in a bit but this is the id the public address for that system program and and then various other configuration informations so this is where you're gonna find the default wallet uh private keys all right so that's what this code is about so like i mentioned uh file system programmatic file system access isn't allowed on the browser so um we'll get into you know handling all of this stuff and building an app in some of the next videos all right so um the url right we're using the local which is this guy right here so that's what that's about so this is about um configuring and creating a key pair again not the account a key pair that represents the account from which monies land ports will come out in order to pay for all of these transactions that we're about to execute so of course since we're on the local test net you know none of this is real money which is why we were able to um where is that know ask for an airdrop which wouldn't be possible in production but um nevertheless every transaction that you request requires a certain amount of money to be paid for that transaction and we're going to see how to calculate that in a moment but basically we're trying to create or begin to create that account by first getting the private public key pair and the preference in the case of this example although this is not something you have to do is to use your own default wallets um key pair in order to generate that account um but again you don't have to do that if you don't want to and then this function right here read account from file is just you know a function that encapsulates that capability of taking that key putting it to this account type and generating a key pair object out of it which again will later use to create a real solana account existing on the network so this is this module is just acting as a bunch of utilities helper code um for the real meat of the the client side code so if we go in here to establish the payer so like i just said we need to calculate or estimate what the fees are going to be for the entirety of all the work that we want to do so that's what this thing is attempting to do right now and the the system the run time provides this call to give us this little helper object that can help us to make those calculations so if we go line by line here we're calling this function and as the name implies get minimum balance for rent exemption like i said before you have the choice where you can either pay rent in order to keep your um account alive on the network or you can um stake a higher number of lan ports in order to not have to pay rent not have your balance decrease and just have your account remain on the network indefinitely so in order to figure out what that amount would be the um this function requires the size of your account's data which is given by this constant and i'll show you in a moment exactly how that size is known but um let's kind of focus on this local code right here for now so then we add that to the total fees and then next what we're doing here is just an estimate which is why you have this arbitrary 100 number here but basically there's per signature that is required i guess that changes the calculation fee for some internal reason so this is going to give you um what that lan port number is and then this is just there sort of arbitrarily because we're gonna this is a test environment and we're just gonna be you know running this over and over and over again and we're not necessarily gonna recreate the payer account every single time so it's just giving us an extra buffer of of land ports so that we don't have to keep risk restocking it and ask for another airdrop and stuff like that right so we saw this function before it's going to create that again it's a key pair it's not the account so we're going to create that so this guy is doing effectively the same thing let me see if i can find it right so we're requesting the airdrop we're confirming that it was good and then we're giving back the key pair so if this line fails then this will run instead so then either way whichever mechanism ran this is going to check that we have sufficient lan ports because again we might be running this over and over again so we might have run out so then if we do have less than whatever is required right whatever we deemed required then we're going to request another airdrop and confirm it just like we did before so obviously this is just some logging stuff and then let's go back in here so the next thing that we're gonna run is the check program now um i started using this sample project actually a little bit ago and they've uh transformed it a lot they like i said they're they're constantly making changes and and doing work to upgrade various things in the system so they very recently updated this example hello world project so before they were using uh bpf loader.low in order to get your program loaded so that it could execute but now they're not doing that and they're actually manually forcing you to deploy um the the program first and then um you know making it accessible so to explain you know what the heck i'm talking about let me just see here okay so we just ran the compile command i think i showed you that before in the package.json file so after it runs it's going to ask you to actually deploy manually the program right so again we use the cli program and then we deploy to wherever the path is so when you're doing this just make sure that um the you're you're pointing to the right path so assuming that you did that then we'll we'll be able to just go ahead and continue and you know get any relevant parameters program id again is the public address but if it fails then you would see this error which is indicating that you need to deploy the program so before i move on as i just mentioned there's this thing called the bpf loader right so just like there exists the system program that allows you to do certain things like create a new account debit an existing account assuming system program is the owner of that account and things of that nature in order to load a program that has been deployed into the runtime uh the bpf loader as the name says will load the program that you request um into the runtime um as a part of doing that which is required to run your program but as a part of doing that it will mark the program as read-only and it will mark the program as executable so every program that wants to be run needs to be set up as read-only and executable um and when i say every program i'm talking about the account that the program lives in in order for it to become usable and once this these two settings have been tripped once they they've been set then they can never be unset and the program has to has to the program account has to stay in that format essentially forever the other part of the reason why i mentioned this is that there are these flags in every account representing uh whether it's read-only or writable um on top of things like ownership and on top of things like the holders the human holders private key signature you also need the account to be marked as writable before you can actually make modifications to it so if that is not the case then um an account can still be accessed but only as a read only and only for um adding lan ports as opposed to debiting out land ports um which the reason that's open-ended is you know everyone is happy to receive money um without you know having to to ask for it um i'm sure that's the case for you so that's why they they left it kind of open-ended like that um let's see here so moving right along assuming that was successful this call is going to get the actual account living inside of the blockchain based upon the um program id the programs accounts public address right so the real account objects are called account info inside of the runtime and then it checks if this call actually brought something back right and then if it didn't then it makes sure that there's actually a compiled binary of the program itself this guy right here hello world dot so and then if there isn't then it lets you know you know what went wrong and then it handles other issues here's that flag about being executable every program program's account must be executable and then assuming all of that those checkings were successful then you have the program id that resulted in string format displayed in the log so here as the name says we're creating a seed in order to prepare for the actual account info objects creation so we need the owner of the account we want uh some generic seed and then we're just using this as another uh parameter thrown in there and i'll show you where this is reused later so like i was saying before the this this um set of code is going to get run over and over again and so that you're not constantly recreating the same set of accounts you're going to see a lot of these checks um you know to check if the account exists or not and then to create it if it doesn't but basically you have this generated public key it checks to see if that account already exists if it does not exist then it proceeds to try and create it so this is where we're starting to get into some of the the beefier parts of um coding into the run time and accessing the runtime so again we check to see um really the minimum land ports that uh we're gonna need to not have rent collected on us so this greeting account is going to be the account that is written to is written to by the program so we want to make sure that we don't have to constantly pay rent so in order to do that we need to check the size of the data that's going to be in there because that is directly proportional to the amount of rent exception exemption monies that are required and i'll show you how this is calculated in a moment so that's what we're doing here and then we go ahead and create our first transaction and inside of every transaction as mentioned previously there is instructions so the first and only instruction is this guy again the system program can create accounts for us in this case we're using a seed value in order to create the account this guy right here is going to be our payer for this transaction every transaction requires some um amount of payment [Music] um this is the key pair that we would like to be used this is the base amount of lan ports that we want this account to have in order to be exempt from rent this is the size of the data that we're requesting on this account this is the program id that will own and therefore control and access and update this account be aware that the space allocated for an account technically can be updated meaning it can be grown bigger if you need it but currently the solana team recommends that um you don't do that because they told me that it's a very arduous difficult process to do so for now you probably want to be careful about the sizing that you give and make sure that it's right for your needs in the future they did say they're going to make that process easier but if you need to deploy in the immediate term you're going to want to spay pay special attention to this value all right so after setting up or checking that our program is set up we're going to do a quasi say hello and i and i say quasi because nothing ever gets sent of any significance to the program right in the program it's just doing an increment of the data but we're going to use this later to actually send data so in this case we get the account affected we create a new transaction um the transaction is going to have the um the affected account it's not going to be a signer it's going to be writable because you know that's what we're we're intending to do um the controlling program and then any data that might be sent over which again in this case doesn't apply so then we've run it on the same network within embedded within a transaction and then this is who's going to pay for this right so then the last call that's going to be made as you can see here the last call that's going to be made is to retrieve data from that account off of the network so we're going to attempt to get the greeted account so the account info and we're going to do some deserializations and then we're going to attempt to show display that that counter value okay so as i mentioned before we we had to figure out the sizing of the account and we had to uh do some serialization deserialization right so it's very similar to how borish works inside of rust as we saw in when we were looking at the the program itself so let's see here okay so the way that the the team did it and i totally agree with this because they weren't doing this before but but now they are is they made it um static they made everything statically typed so this struct type on the rust side is analogous to this class type on the um typescript javascript site now the reason why it looks a little bit weird is because although it has only this one member in it the um the the borscht the borscht library uh requires this as sort of metadata right so if we had you know two or three members in there then they would all be listed out here in the count of fields and then they would all be set inside of this scope so that's why it looks you know a little bit busier than than perhaps it needs to be with only one one member in it so then um what's happening here is that again borsch requires some additional metadata in order to do a mapping so in this case it needs the type that is coming from the client side and then it needs some mapping information of how that maps to the actual program side in other words the rus code so kind refers to the fact that it's a struct and then fields refers to the name of the member inside of the rust side and then it's type and because you could have more than one member this is an array so these things are being provided to the serializer so that it can properly serialize and deserialize so that each platform will understand according to its own needs so then here we saw this constant before in order to figure out how much money we needed to be rented exempt so we saw that a couple of times and this also is needed to size the actual data size of our account our greeting account so this thing is serializing an array of bytes eight bits is equal to one byte so it's an array of bytes so it's serializing to that destination data type and it's taking out the length the size of it and that's how it knows how much data size is required okay so then um this is like encode decode right so this is encode and then down here you're going to have the decode right so now i got my account info object back i'm ready to deserialize so i'm ready to take it from that binary format tell the bor system hey the account type on this client side is of type greeting account the schema that you need that you understand and recognize is this over here so i want you to convert this to an object that i in javascript land can understand so then it goes about doing that so now we have let me just make it more clear so now we have an actual greeting account object instance so we can have statically typed members right and know what this is supposed to be and console.login so um yeah that was a lot of information um you know i just wanted to be clear because when i was doing this there was like a ton of stuff that i just wasn't getting and i had to kind of struggle and you know google and and all the normal stuff that you got to do so hopefully um this information is helpful and again before we start modifying this smart contract and and the related code if you have any questions and stuff just leave a comment and i'll try to answer them all right guys so this video ended up taking a lot longer than i thought it would so i ended up just refactoring the code myself and i'll just go through the changes that i made so what i did is everything up to here is basically the same and what i did is i'm passing in the data as a a binary instance of this account type from the client side so i am using the previously mentioned borscht serializer deserializer so in this case i'm taking the data as a array of bytes so as a slice and then i'm basically decoding it with this command right here and that gives me an instance of greeting account this call right here is just to make sure that if the decoding fails that i'm able to notify with the log message and then the type of error that occurred and again i have you know multiple log messages and then i take that same instance of the data from the actual account that we need to update and then what i'm doing is i'm taking that data um i'm finding a range in it that is the same size of the um of the instruction data and then i am copying that data into so i'm copying the parameter data into the actual accounts data so copy from slice um the only thing the only reason why i instantiated this basically is because i wanted to make sure through the logs that i'm getting the appropriate data the appropriate values so technically um you don't really have to do this but in part of doing part of doing this i'm also demonstrating that this parameter data that is of type u8 array um it's possible to pass in really any kind of data that you want even um specific object instances so not entirely necessary but still demonstrates the flexibility of this type so after doing that you would have to you would have to build your program and then after you build the program you would deploy it so make sure to do that and you're ready to go as far as the program is concerned and then as far as the code is concerned the changes that i made are right here so um so if you look at this portion with um the greeting size you can see that i actually instantiated the um an instance of the greeting account and i added sort of this placeholder data and then i passed that instance in and the reason why i'm doing this is because that sizing is responsible for the space allocation for the greeter account so the reason why you need to know that is because once you give it a certain um once you give it a certain size uh ultimately these are byte arrays both the instruction and the data so they're statically sized um at definition time and they can't be changed thereafter so what you're going to find at least if your data schema is in the form of some type what you're going to find is when you're passing that data in through this copy command the data sizes have to basically match up or else you'll end up getting various um serialization deserialization issues as you're using the data so um what i was trying to do was pre-allocate um a specific size to my account and then make sure that i'm filling in an appropriate value for the for the for the input so in this case in this sample codes case the input is going to be just a message so the way that i set it up this guy this say hello used to have no parameters so this time because we want to send a string message to the account um save it in the account and then retrieve it later i'm now passing a parameter and then after passing that parameter i create a new instance of the greeting account that we're using as our schema for data being passed back and forth so and then i set the txt member field and then it's that data instance as an object as an entire object that's being passed in so because it has to match to um this schema on the rust side so a struct with a member called txt and a string i can't just pass in this alone so in other words i can't just do this and pass it in this way because the schema is actually um not the same not the exact same so if you remember the schema the real schema for the borsch um serializer looks like this where yes you have a member called txt but the constructor is actually receiving a field object that may contain multiple members and then the schema file which has the mapping between the client side type and then the type on the on the um the program the smart contract so i'm indicating that it's a struct i'm indicating that there's a txt member and i'm indicating the string so those things um those metadata have to go have to ship over to the have to ship over to the um to the program in their correct form and that's why this serialization is necessary and then after that you have to wrap it in a node buffer so that it can go over as a blob basically and be sent over and then in the program itself it gets deserialized um actually it doesn't even need to get deserialized to be inputted but it gets grabbed in and then inserted through this copy command um inside of the uh the data because this is also ultimately a byte array as well um so then when we retrieve it um everything else is basically the same but this uh section and then anytime in here if you are needing to do a deserialization that's where um things will fail if these lengths aren't exactly the same so this issue i think for the most part exists because i am passing um you know actual object instances back and forth so um if the sizing the length sizing is not identical then you can end up getting various issues so this length right here is actually the same length as as this right so you're gonna have to come up with your own mechanism to um how should i say this let's say for example the text that you're submitting is actually shorter than the sizing of your account data object so then when this deserialization happens you're going to end up getting an error so i'll show you that now right so um unexpected three bites after d serialized right so there's an additional set of kind of um empty uh places those three um positions that i deleted so you're gonna have to come up with some sort of mechanism let's say for example underscore right you're gonna have to come up with some sort of mechanism to indicate that you're not using all of the available space and then when it comes to parsing and and handling that that string or whatever type of data that you're um sending over you're gonna you know basically trim out this extra fluff right so just to just to show that this you know is actually working um oh sorry it's longer than right so um yeah that's basically it just uh like i said focus on um doing whatever whatever is appropriate to your needs in terms of your data structure and and the length um there may be some better ways of handling these sizing differences between the um the data the um the account data on the network side and what you're sending over um you know this is kind of hokey but remember because these these types are arrays they have a static length right so there's no way in other words to dynamically resize this account's data right we can't let's say if the instruction coming in is three characters shorter we can't dynamically at runtime make this um account data three c uh three indexes shorter because it's a it's an array so it's it's static in terms of length so that's the core reason for the issue that we're running into so there may be more um elegant ways to to deal with this and in a lot of situations you probably won't need to send over like an entire object like i ended up doing you may be if all you need to send over is strings then you could literally you know just send over um a text right without an entire object and that might work for your specific case but under certain circumstances if you have a more complicated data schema then you know that's not going to work so you're going to have to figure out a way to deal with the the differences in the size of the data versus the um parameters that you might be sending over okay so um that's it um in the next video i'm going to flesh out this uh sample and make it a little bit more um like an actual app so we'll bring in uh react we will um pass messages instead of just sending it to a single account we'll pass messages um between two accounts and also we we will um send money meaning land ports between the the two the two accounts so if you have any questions um definitely leave a comment i will uh try to answer any questions that you have so thanks for watching
Info
Channel: David Choi
Views: 32,060
Rating: 4.931848 out of 5
Keywords: solana, rustlang, javascript, smartcontracts, serum, blockchain
Id: gA7hFdq2h9Q
Channel Id: undefined
Length: 102min 28sec (6148 seconds)
Published: Tue May 04 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.