Solana Kit (formerly Web3.js v2) is the modern TypeScript/JavaScript framework for interacting with Solana programs, replacing the legacy Web3.js approach. The migration process involves replacing Anchor provider with Solana Kit's connection, using Kodama to generate TypeScript clients from Anchor IDL, and implementing wallet connections through Solana React. This enables developers to build fully functional frontends that support multiple wallets like Phantom and Solflare while maintaining all existing program functionality.
Modernizing Anchor Apps with Solana Kit: A Step-by-Step Guide
Added:so after our last video 10K rotator asked if QuickNote could also do a video on Salana Kit for Web3JS users and yes Mr rotator yes we can salan Kit formerly known as Web3JS version 2 is the current gen Salana tech for JavaScript and TypeScript made by Anza formerly known as Salana Labs anker is the most popular Salana framework for building onchain apps sometimes called smart contracts so here's what you've been waiting for we're going to take a real application that was built on web3js we're going to move it completely to the Salana kit including all the tests for the back end a front end connecting to wallets like Phantom or Soulflare we'll be fetching accounts from the network and checking it out and displaying the data inside we'll be sending instructions to your Anchor program from your front end and from your tests everything you need to do with TypeScript and JavaScript in a Salana program we'll be doing today with Salana Kit it's all time stamp below let's go so when I was researching for this video I went to look for an existing anchor example to go and update and I found one and I started working on it before I realized that I actually made a mistake that I want you to avoid which is that repo hadn't been updated in 3 years which is a really long time in Salana terms i've said this before but I really think you should try and focus on anything made in the last 6 months in Salana anything older than that you'll have updates to do before you even start learning so really focus your learning on brand new content and with that you should probably subscribe to the QuickNote YouTube channel because we will always have Salana content for the new tech i promise you that so here is our program i've made all the fixes I needed to make to it just so it will work it's just a simple election program it allows you to vote between GM and GN and everyone can only vote once and we will tally the votes in a account that belongs to the program so the program has two instruction handlers they are create election and vote and it's deployed to Salana DevNet has a public key which is the also called the program ID which is the address people can find the program and if Alice comes along and she wants to use our program as long as there's no election already made she can go and run create election and that will create our election so the seed we've used for election is just the text global just cuz it's a global for our program inside election we just store whether the election is open the tally of good mornings and the tally of good nights as a bit of a crypto meme people like to say good morning and good night to each other so if Alice then votes we'll increment the amount of good mornings by one and also to stop her voting again we're just going to make an account with the seed of vote and Alice's own address that records her choice so if Alice tries to run vote again the transaction will fail because that vote account has already been created that's great so what if Bob comes along bob can also see that the GM versus GN discussion is really one of the most critical issues of our time and he has opinions on this so Bob is going to vote for GN so when Bob calls vote with GN as his choice we will increment GN by one the votes are now even and just like with Alice we're going to make another PDA with the seed vote and Bob's address recording the fact that he has previously voted and stopping him from voting again if I was going to make this as a real election program I might want to check for some balance inside everyone's account before I allow them to vote i might want to charge them to vote but this is just a demo app and we want to keep it nice and simple so now you understand how the program works before we dive into the code I want to quickly show you how everything fits together so Anker is still the most popular framework for Salana programs those are called smart contracts on other chains however what has changed is to speak to your program from JavaScript or TypeScript you now use something called Kodama which is made by Anza doesn't come with Anker it's something you installed and it's just a really simple program that takes your anker IDL and turns it into a TypeScript client for your program that used to be done by Ankerjs now it's done by Kadama the final part of interacting with your program in Typescript is done with Salanakit so you can use Salana Kit to interact with Kadama to send instructions to your program but you can also use Salana kit for example to interact with the token program and transfer some tokens around or whatever else so Kadama is the client for your program for TypeScript salana kit is the way you talk to any program on Salana using JavaScript and TypeScript so with that in mind let's take our program that used to use web3js and make it use Salana kit first in the tests and then in the browser so here we are in our existing web 3.js version one project so if I do an anchor test all the tests run and you can see they all finish we've only got a few tests there i'll add a couple more so if we look in our actual tests file we're importing this couple of things from the Coral XYZ anchor package and we're importing this election object that was made for us when we did our anchor build uh so that was created from our IDL we're importing some bits from Salana Web3JS and we have this anchor provider that basically that just gives us a connection to the local cluster for testing there's al also a wallet built into it which is the anchor wallet local payer and we can make other users as needed by just generating key pairs for them so we're going to actually delete everything in that file and save it because we're not going to use any of that we can keep it around if we wanted to see what the old tests were and maybe test the same thing but just for the sake of clarity I'm going to recreate all of this from scratch we're also going to go to our package.json and remove everything cuz we don't need that anchor or JavaScript package anymore we're going to be using Kadama to generate our client we don't need big number because the new Salana kit actually just uses the inbuilt big ins that come with JavaScript we don't need Chai or Mocha because Noode.js has its own testing framework so let's get rid of all of those we don't need prettier well actually probably I'll reinstall prettier in a second and we'll probably want a newer version of TypeScript than what's installed again we don't need Mocha because we have Node.js now if you don't have this already you'll also want type module that allows us to do all the latest and greatest ES6 hotness when I say latest and greatest I mean from 2015 so if you don't if you have type common JS or you don't have this added you'll want this added otherwise you'll run into problems we don't need a TS config because we'll be using TSX which replaces older tools like TS run and has safe modern defaults with tsx we get nice things like top level await so now we've cleaned out our package.json we can install what we actually need which is Salana kit and we're also going to install a highle library which I created called Salana kite it just takes care of doing a lot of the boilerplate work that you would normally use on top of Salana kit it should save you a fair amount of typing if you're familiar with the helpers library for web 3JS this is the modern equivalent of that built on top of Salana Kit i'll let that install i'm going to install some dev dependencies i.e things that will be used to build my software but won't actually be used at runtime they are mpmi-d kodama to generate our typescript client for our anchor program kadama renderers and kadama nodes from anchor which is the specific parts of kadama to support anchor programs typescript and tsx because we want to do everything in typescript the types node package to support Node.js in TypeScript and we're going to read prettier because everyone should always run prettier and always have prettier enabled on save give that a moment to install great so the next thing I'm going to do is just make a little command line TS file that is going to take in the IDL and make a TypeScript module we can use to send instructions for our program so we just make a new file call it create kodama client.ts and I'm going to paste this and you can paste it too this isn't specific to my program will take any anchor IDL whatever is in the target IDL directory load it up throw it into Kadama and create the Kadama client in the dist js client directory it's some real boring stuff one thing that is slightly cool here that I want to point out is that we're using top level await here you'll see in all the the code that I'm creating for quicknote now we're not worrying about all these like wrapper functions if you use tsx and you have type module in your package.json JSON you don't need to worry about things like that so we can actually do things like await load anchor IDL and it just works so once you've made that file run npx tsx create kudama client and it will generate a client so now that we have the ability to create a kadama client I probably want to have that run every time we do a test so I might want to have anchor build and mpxtsx create kadama client ts that will firstly create our IDL for us and then it will go and um recreate the TypeScript client based on that IDL so let's go back to our test directory and we mentioned we cleaned out everything before so let's import firstly our test runner so we're just going to use the one that's built into Node that way we don't have to worry about Mocha and Jest and TS Mocher and TSJ and all that stuff we're just going to use what's built into node already and tsx which is the most common way of running typescript these days so the next thing we're going to do is import some things from the client that kudama just generated for us so we'll firstly import the whole thing as program client and we'll get it from the disj client that's where create kudama client saved it and then we're going to import a couple things which are specific to my program so they'll have different names in your program so for example I have a strct called election so one of the things that Kama will do is generate a little function to go and decode the election strct which becomes get election decoder so if you have something else if you're running an auction program you'll have get auction decoder if you're running a program that has bets you will have get bet decoder etc likewise if you have some constants you're exporting as well they will be in your client and again they will be named after the actual strct so my strct is called election so I have election discriminator finally we'll import our things from Salanicit so we'll be using the key pair signer and address types we'll be using maybe account finally we'll import connect and connection from Salanite connect in Salanakite just gives us a really easy way to connect to any network on Salana with some sensible defaults we can override that if we want to you still have all the flexibility that Salana kit gives you but in this case connecting to DevNet is literally const connection equals connect devet um it's designed to save you a bunch of time and you'll see that throughout this tutorial the next thing I'm going to do after that is just make a little function to quickly stringify objects so I'm going to set up an alias for console log and I'm going to set up a function called stringify which is just JSON stringify but it's set up to also handle big int values because big ins didn't exist when JSON was first created you need to specify some rules about what to do when you see a big int so this just allows us to log objects that use big ins which is the replacement for bnjs if you remember that from web3js version one we no longer need bjs we have big built into JavaScript but we need to tell JSON how to handle them so that's what that function does so the next thing I'm going to do is create just a skeleton for the actual tests so I'll paste that in and really so we're going to describe the election we're going to test that Alice creates an election for the public to vote on we'll test that Alice votes for GM we'll test that Bob votes for GN and we'll add some more tests later right at the beginning we are going to set types we're going to use the first thing is that rather than having what were they called key pairs in web 3.js we now have key pair assigners and they're actually native JavaScript web crypto key pairs you can generate them with a function called generate key pair assigners but we're going to look at a more efficient way to do that in a second we're going to have an election which is an address in web 3JS we actually would have called this a pub key but the funny thing is election was never actually a pub key salana has many different types of addresses some of them are on the curve like Alice's own address Bob's own address and where we're deploying the program to but program derived addresses are specifically not pub keys there you can see election that little dot is off the curve it is not a pub key it's just a Salana address made from a particular seed one of the things I actually really like we also have this connection this is from Salana Kite and all it is is a thin wrapper around RPC and RC RPC subscriptions that runs a couple of factory functions for you so you can spend more time making things and less time typing so the final thing I want to add there is a just a type for get elections all it is is a function that I'm going to create that's going to get a strct of a particular type in my case it's elections in your case it can be anything else so it's an array of maybe an account of whatever type we want we're going to make that function in a second we just specify the type for it here so now that we have that done we can connect to our local cluster and that's going to look a little bit like this so we have our connection which we just await the connect function from kite that's going to do all the necessary work of creating like transports and RPCs for us the default for connect is just to connect to local host but you can specify any other named network or you can specify an RPC an RPC subscriptions URL if you know the URLs or you can specify some custom transport of what you like the whole point with Kite is to have defaults the next thing I'll do is make Allison Bob i could just do generate key pair sign her twice and add some soul to these accounts with awaiting airdrop again I'm just going to use one of the helpers that comes with kite called create wallets that makes multiple wallets in this case two and by default gives them some Salana to play with if you remember in web3js version one we use the anchor provider which has some amount of soul pre-provided but for anything else we'd have to go and create a key pair and do airdrops with Salanakit there are no pre-existing accounts so you do have to make those accounts yourselves but kite has these useful functions just to make those wallets and do those airdrops in one step the next thing we're going to do is calculate the address for election again I'm going to use another little kite helper here it's called get PDA in bump and we just specify our own programs address and our seed so in this case it's just this seed of the string election and that will give us a PDA and a bump address which I'll talk about another time for the string election that's where we're going to save our election account lastly I was talking about this earlier we're going to make a function to get all the elections now this is specific to my program but it will look almost exactly the same for your program just replace the word election for some other strct in your anchor program so get elections as a function and and I'm going to use this thing called get accounts factory which creates a get accounts for some specific strct so I'm going to specify my program address i'm going to specify the discriminator I use for election and I'm going to use get election decoder which I imported before to tell kite how to decode elections that means I can now call get elections and it will get all the elections in the program now I mentioned before there's only one election we're making because our seeds is literally just the word election so there's only one election account but get elections will return an array which will always have one item in it again if you're getting anything else in your own program if you're getting bets if you're getting events if you're getting liquidity pool information you will use get accounts factory to get a function that pulls down all the accounts of that particular type so everything's set up now let's go and create the tests so that llis can create an election so we're going to do that and this is what it's going to look like firstly we need to make an instruction to create an election and again this is specific to this program you'll have something different in your own program but in my anchor program I have a instruction handler called create election so if I want to use create election I can call my Kudama client with program get create election instruction and that will generate an instruction for that create election instruction handler to process so when we run program client get create election instruction we now have an instruction and then we can go and send a transaction from that instruction alice is going to pay and our transaction will go through again this is just using some of the helpers available in kite after that we will log the transaction signature so with just that part complete just making elections it's probably time just to run the test we'll add the other tests in a second but I just want to make sure everything works right now i'm going to pop open an anchor.l and show you the test command I'm running which is npxtsx and we're passing some options to node which is we're using the node test and the test reporter equals spec option these just make the test look pretty and we're just running all the TS files in the tests directory so that means when I run anchor test this is the command that will actually run so if I go back to my command line and I run anchor test you should see that Alice makes an election so I'll give it a second to build and run the test script great so we have Alice creates an election for the public to vote on and we have some kind of effectively empty tests for Alice and Bob votes for GM and GN i haven't actually put anything in there i really should probably throw an error in saying "Hey we need to do this but I'm not going to because I'm going to actually finish those tests for Alice and Bob." I'm going to add some more tests as well so let's actually pop in some real tests for Alice i'm pasting in there but it's not actually a lot of code mainly it's a lot of asserts at the end i've added some more checks cuz I'm a little bit more cautious so we're going to calculate the address for vote again we use get PDA in bump and we use our own programs address and the seeds we're going to use to get the vote account are just the string vote and Alice's own address we're going to get the instruction for vote again this is specific for this program because I have an instruction handler called vote there will be program client get vote instruction and that takes the election account the vote account Alice will be the signer and our choice which is good morning or good night which will also comes from program client that's all there generated for you using Kadama we'll go and take that instruction we'll wrap it in a transaction alice is going to pay for it and we'll send that off so after that our transaction has been made so if I run get elections I'm now going to have an array with all the elections now there's only ever one election so the first thing we're going to assert is that there is only one election the next thing we're going to do is look inside the data for the election account and make sure that the election is open that the amount of good mornings is one the amount of good nights is zero i'm also going to add an extra check which is just to get the logs for that transaction signature and see that we have voted for GM inside the in the logs because I don't know that just seems like a a nice thing to go and check for i'll save that and I will go and rerun my tests there we go so Alice votes for GM has run now you can actually see it takes a lot longer than it took when it was just completely empty the Bob one you can tell goes by really quickly cuz doesn't doesn't have any real content yet but yeah you can see that test is working so let's add Bob's tests and they'll be pretty similar to Alice's tests um they'll just be flipped around a little bit so for example the address for where we will save Bob's vote will be made from the seeds vote and Bob's address the instruction for Bob to vote will be in the same election but we're going to record his vote in a different vote account and where Bob will sign the transaction and Bob is going to choose something different from Alice cuz he likes evenings more than he likes mornings just like before we're going to send a transaction from that instruction and we'll get all the elections again we still expect there to be one election and we'll just make sure that GMs and GN's are now even there should be one each now that Alice has voted good morning and Bob has voted good night we'll do the same thing with the logs as well we just want to check the logs for the transaction and just make sure we see the voted for GN in the transaction logs save that go back to our terminal and let's run this again so all our tests now have some real content in them and they all pass i'm going to add one more test which wasn't in the original program which was just to make sure that Alice can't vote twice or really anyone can't vote twice i'm just going to come in as Alice again and you use the same vote account and the same vote instruction and you'll see when we run that transaction it actually fails and it throws an error and if you look inside that error message you'll see this string account already in use that's because we record everybody's vote in their vote account and if somebody already has a vote account we will throw up an error and we won't allow them to vote a second time so if I flip back to my terminal run all those tests again and all those tests pass great alice can't vote twice so we've taken an app using web3js cleaned out a bunch of legacy code built a TypeScript client to send instructions to our anchor app using Kadama and converted all the tests to use Salan Kit the last part is to add a web front end using Salanicit to sign transactions with wallet apps like Phantom and Soulflare which we'll send to our anchor app before we do that I'm going to put our program onto Salana DevNet the reason for that is not every individual wallet supports local net wallet providers you know who you are so if I do anchor deploy provider a cluster devnet we'll deploy to salana devnet now this is going to take a little bit of devet soul if you don't have some devet soul already you'll want to use the salana foret quicknote has a great salana foret that is ready for you our deploy is successful here's our program ID i've actually done an anchor keys sync already just to double check that the keys in anchor actually match the addresses on Salana DevNet they're all correct so we're going to add a React front end to our program and we're going to put it in the web directory which is pretty much a standard place for it this is an entire React app but I will cover the most important parts so you can build this for your own program the full repo will be linked in the show notes as well as that there's also a standalone example you can copy into the web app in your own programs by default that's just configured to send transactions to the system program but you can use this guide to change that to send transactions to your own programs so in that program we have Salana Kit and Salana React which is the package for rex support for Salana the wallet standard packages which is what provides the abstraction layer between different browser based apps and different wallets plus all the normal React bits and pieces that we need we're going to add Salana kite to save us a little bit of typing and we got some UI package we're going to use the system program that's pretty much about it everything else here is standard React if you look in the web source directory I'm going to show you the file connection context provider because this is the thing that allows us to use our kite connection we're going to wrap this lana RPC URL and RPC subscriptions URL that were provided by our wallet into a kite connection object that we can call from any of our components inside our main component which is a selection component that you see over here we are going to import Salana kit just like in the tests we're going to import our program client that we made with Kandama just like the tests we're going to import this use wallet account transaction sending signer which is the thing we used to sign transactions from the Salana React package a couple more bits from Salana React the most important thing is this connection context which gives us access to our kite connection object with all the factories from Salana kit set up for us so when somebody clicks this get election button it actually runs this function fetch elections which awaits get elections which works exactly like what we saw in the unit tests we have this get accounts factory which will create a get whatever type of structure we need in this case elections and decode it for us and after that we just set elections to the results which is all our elections oh by the way we don't have any elections yet because we've just deployed the program so we're going to create that in a moment i'll show you what create election looks like as well so we need to get the address for our election account we're going to create an instruction to our anchor programs create election instruction handler and then we're going to send it again it looks exactly like what we saw in the unit tests after that we'll run get elections again and set the elections to whatever the results are so here I am in my browser i have a wallet connected and I'm going to hit create election to go and make an election i will approve that transaction spend 16 cents worth of DevNet soul click approve and you can see my balance just updated i'll click get elections again and now we can see it's actually an even match there are zero votes for GM and zero votes for GN so I'm not sure whether you prefer day or night um I don't know i think I'm more of a nighttime guy so I'm going to vote GN i will approve that transaction spend 14 cents of DevNet soul and I'm going to click update election again and you can see it is now 100% everyone is voting for good evening you can also see the raw data from our election account because we're we're showing it here we're using our same JSON serializer you saw before that can handle bigs and you can see the data inside each election is open is true good mornings are zero and good nights are one that's great so what if we connect a different wallet so here I am in Chrome if I connect a different wallet account you'll see the balance is different up the top there and if I go and hit vote GM and I approve that transaction and I update the election again see that votes are now even and of course if I go back to my original browser where I was connected as that first account and I go and update election you will see that it updates there as well so today we've taken an anchor app that was entirely using web3js we've got rid of a bunch of old legacy code uh we've replaced the anchor.js with kadama to create the client for our application and replaced all the tests and all the browser code with new Salana kitbased equivalents so we're going to be doing a lot more with ankor and with salan kit over the next few months my role at QuickNote is purely Salana developer relations and that means I'll be bringing you Salana content continuously so I hope you like this video and I'll see you in the next one
Up Next

Solana Program Derived Addresses (PDA): Derivation Explained
@SolanaTutorials
313 views•2025-03-01

Torrent File Format & Bencoding: A Technical Deep Dive
@AsliEngineering
12.5K views•2022-08-08

Deploy Your Own ERC20 Token: A Step-by-Step Guide
@Quicknode
67K views•2022-12-15

Understanding Ethereum: A Comprehensive Beginner's Overview
@99Bitcoins
3.1M views•2018-06-26
Related Study Plans & Knowledge Roadmaps
Structured learning paths in Blockchain & Crypto
![Serialization and Deserialization [Solana Basics Day6] - Feb 18th '26](https://i.ytimg.com/vi_webp/VVTLc8hASOE/maxresdefault.webp)


![Transaction Serialization [Solana Tutorial] - Apr 7th '25](https://i.ytimg.com/vi/OKdcHvDqdDs/maxresdefault.jpg)



![[Solana Bootcamp Summer 2024] #2 - Build your first Solana Program](https://i.ytimg.com/vi/FFVcC0WmjZ8/maxresdefault.jpg)


![Introducing the New Solana JavaScript SDK @solana/web3.js [Solana Tutorial] - Sept 28th '23](https://i.ytimg.com/vi_webp/FQb0mTFqURI/maxresdefault.webp)

























![Larger Transation Sizes [Solana Tutorial] - Apr 15th '26](https://i.ytimg.com/vi/txsuaMlTeJk/maxresdefault.jpg)

