{"id":1962,"date":"2022-02-02T09:10:42","date_gmt":"2022-02-02T15:10:42","guid":{"rendered":"https:\/\/www.becomebetterprogrammer.com\/?p=1962"},"modified":"2022-06-07T09:22:37","modified_gmt":"2022-06-07T14:22:37","slug":"create-solana-smart-contract","status":"publish","type":"post","link":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/","title":{"rendered":"How to Build &#038; Deploy a Solana Smart Contract using Anchor"},"content":{"rendered":"\n<p>In this tutorial, you will learn how to create <strong>a<\/strong> <strong>Solana &#8220;program&#8221;, which is in other words the way smart contracts are called in Solana<\/strong>. Solana programs are written using low-level programming languages. More specifically, <strong>you can write Solana programs using <a href=\"https:\/\/www.rust-lang.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">Rust<\/a> or C and C++ programming language. <\/strong>For this tutorial, <strong>we are going to use Rust<\/strong>.<\/p>\n\n\n\n<p>Solana has emerged as an attractive alternative to Ethereum due to the cost per transaction being cheaper and faster. While the focus of this article is not to mention the differences between using Solana and Ethereum, it is a good idea to have a general understanding of why Solana is gaining popularity quickly.<\/p>\n\n\n\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_2 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\"><p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<\/div><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#What_kind_of_Solana_program_are_we_building\" >What kind of Solana program are we building?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Do_I_need_to_know_Rust\" >Do I need to know Rust?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Setup_Solana_Development_Environment\" >Setup Solana Development Environment<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Setting_up_WSL_and_Node_in_WSL_Only_for_Windows_users\" >Setting up WSL and Node in WSL (Only for Windows users)<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Installing_Packages_For_Solana_Development_Environment\" >Installing Packages For Solana Development Environment<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Installing_Rust\" >Installing Rust<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Installing_Solana\" >Installing Solana<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Installing_Anchor\" >Installing Anchor<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Generate_Paper_Wallet\" >Generate Paper Wallet<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Running_the_localnet_Cluster\" >Running the localnet Cluster<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Starting_a_Project_with_Anchor_Framework\" >Starting a Project with Anchor Framework<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Working_on_the_Solana_Program\" >Working on the Solana Program<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Updating_the_Solana_Program\" >Updating the Solana Program<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Understanding_the_Logic\" >Understanding the Logic<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#What_does_the_program_do\" >What does the program do?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Defining_the_program_errors\" >Defining the program errors<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-17\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Defining_the_Structures\" >Defining the Structures<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-18\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Defining_instructions_in_the_module\" >Defining instructions in the module<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-19\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Build_the_program\" >Build the program<\/a><\/li><\/ul><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-20\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Testing_the_program\" >Testing the program<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-21\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Configuring_to_use_a_specific_cluster\" >Configuring to use a specific cluster<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-22\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Accessing_the_Solana_program_and_executing_instructions\" >Accessing the Solana program and executing instructions<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-23\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Running_the_tests\" >Running the tests<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-24\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Deploying_the_program\" >Deploying the program<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-25\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Configure_devnet_cluster\" >Configure devnet cluster<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-26\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Make_sure_you_are_on_the_devnet_cluster\" >Make sure you are on the devnet cluster<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-27\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Build_the_program-2\" >Build the program<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-28\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Generate_a_new_program_id\" >Generate a new program id<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-29\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Update_program_id_in_Anchortoml_and_librs\" >Update program id in Anchor.toml and lib.rs<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-30\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Build_the_program_one_more_time\" >Build the program one more time<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-31\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Deploy_to_devnet\" >Deploy to devnet<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-32\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Verify_Solana_Explorer\" >Verify Solana Explorer<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-33\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/create-solana-smart-contract\/#Conclusion\" >Conclusion<\/a><\/li><\/ul><\/nav><\/div>\n<h2 class=\"wp-block-heading\" id=\"what-kind-of-solana-program-are-we-building\"><span class=\"ez-toc-section\" id=\"What_kind_of_Solana_program_are_we_building\"><\/span>What kind of Solana program are we building?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>We are going to build Solana program that writes a tweet, and users are able to like the tweet.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"do-i-need-to-know-rust\"><span class=\"ez-toc-section\" id=\"Do_I_need_to_know_Rust\"><\/span>Do I need to know Rust?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>While having previous knowledge in Rust will help you to focus on learning more about the concepts of a Solana program, it is not necessary to know Rust. However, having previous knowledge of a programming language is strongly recommended. We will do our best to break down step-by-step what some of the Rust syntaxes mean.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"setup-solana-development-environment\"><span class=\"ez-toc-section\" id=\"Setup_Solana_Development_Environment\"><\/span>Setup Solana Development Environment<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>We are going to use <a href=\"https:\/\/book.anchor-lang.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Anchor<\/a>, a framework for Solana which is in active development at the moment of this writing. The main purpose of Anchor is to provide convenient tools for developers to write Solana programs instead of spending time working on the tedious parts of the raw Solana programs.<\/p>\n\n\n\n<p><strong>Important Note: <\/strong>Currently, only x86_64 Linux is supported currently in Anchor. Therefore, your OS needs to run on x86_64. For Windows users, you can install WSL (Windows Subsystem for Linux) and follow the instructions to set up the Solana development environment.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"setting-up-wsl-and-node-in-wsl-only-for-windows-users\"><span class=\"ez-toc-section\" id=\"Setting_up_WSL_and_Node_in_WSL_Only_for_Windows_users\"><\/span>Setting up WSL and Node in WSL (Only for Windows users)<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Feel free to skip to the step to &#8220;Installing Packages For Solana Development Environment&#8221; if you are using a machine that runs on x86_64 Linux.<\/p>\n\n\n\n<p>Open the terminal and install WSL.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>wsl --install<\/code><\/pre>\n\n\n\n<p>Once the installation is complete, <strong>restart <\/strong>your computer. Do not proceed to the next step until you restart your computer.<\/p>\n\n\n\n<p>After your computer has restarted, open the &#8220;Windows Features&#8221; and ensure the following options are checked:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Windows Subsystem for Linux<\/li><li>Virtual Machine Platform<\/li><\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"550\" height=\"490\" src=\"https:\/\/www.becomebetterprogrammer.com\/wp-content\/uploads\/2022\/01\/Windows-Features.png\" alt=\"\" class=\"wp-image-2102\" title=\"Enabling &quot;Windows Subsystem for Linux&quot; and &quot;Virtual Machine Platform&quot; windows features\" srcset=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Windows-Features.png 550w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Windows-Features-300x267.png 300w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><figcaption>Enabling &#8220;Windows Subsystem for Linux&#8221; and &#8220;Virtual Machine Platform&#8221; windows features<\/figcaption><\/figure>\n<\/div>\n\n\n<p><strong>If you just checked these two options, you will have to restart your computer again.<\/strong><\/p>\n\n\n\n<p>If these two configurations are were previously checked, you are good to use the Ubuntu terminal in Windows without the need to restart your computer. <\/p>\n\n\n\n<p>Open the search menu, and type &#8220;Ubuntu. You should see an<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1017\" height=\"837\" src=\"https:\/\/www.becomebetterprogrammer.com\/wp-content\/uploads\/2022\/01\/Searching-Ubuntu.png\" alt=\"\" class=\"wp-image-2103\" title=\"Searching &quot;Ubuntu&quot; in the search menu\" srcset=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Searching-Ubuntu.png 1017w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Searching-Ubuntu-300x247.png 300w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Searching-Ubuntu-768x632.png 768w\" sizes=\"auto, (max-width: 1017px) 100vw, 1017px\" \/><figcaption>Searching &#8220;Ubuntu&#8221; in the search menu<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Once you find it, click on it to open the Ubuntu terminal.<\/p>\n\n\n\n<p><strong>Note<\/strong>: If you run into issues when attempting to open Ubuntu terminal, check if Virtualization is enabled in your machine. <a href=\"https:\/\/www.thewindowsclub.com\/disable-hardware-virtualization-in-windows-10#:~:text=ON%20the%20System.-,Press%20F2%20key%20at%20startup%20BIOS%20Setup.,changes%20and%20Reboot%20into%20Windows.\" target=\"_blank\" rel=\"noreferrer noopener\">Check out this article to learn how to enable virtualization<\/a> if you are not familiar with this process.<\/p>\n\n\n\n<p>Time to install <a href=\"https:\/\/curl.se\/\" target=\"_blank\" rel=\"noreferrer noopener\">curl<\/a>, <a href=\"https:\/\/nodejs.org\/en\/\" target=\"_blank\" rel=\"noreferrer noopener\">node<\/a> and <a href=\"https:\/\/nvm.sh\/\" target=\"_blank\" rel=\"noreferrer noopener\">nvm<\/a> (node version manager) in Ubuntu.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>\/\/ 1. install curl\nsudo apt-get install curl\n\n\/\/ 2. install nvm\ncurl -o- https:\/\/raw.githubusercontent.com\/nvm-sh\/nvm\/v0.38.0\/install.sh | bash<\/code><\/pre>\n\n\n\n<p>Prior to installing node using nvm, we are going to verify nvm was installed correctly. To do so, restart the Ubuntu terminal.<\/p>\n\n\n\n<p>In the new ubuntu terminal run the following command to verify nvm.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>command -v nvm<\/code><\/pre>\n\n\n\n<p>If the output from running the previous command returns &#8220;nvm&#8221;, this means it was correctly installed.<\/p>\n\n\n\n<p>Now, install node using nvm.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>nvm install --lts<\/code><\/pre>\n\n\n\n<p>Now, you are good to go.<\/p>\n\n\n\n<p><strong>Follow the rest of the tutorial using WSL (Ubuntu terminal). <\/strong><\/p>\n\n\n\n<p><strong>Note:<\/strong> Remember, from now on you are going to access the Linux subsystem available in your Windows machine. Hence, everything in your Windows machine will not be accessible in your Linux subsystem.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"installing-packages-for-solana-development-environment\"><span class=\"ez-toc-section\" id=\"Installing_Packages_For_Solana_Development_Environment\"><\/span>Installing Packages For Solana Development Environment <span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Time to set up the Solana development environment. We are going to install the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Rust<\/li><li>Solana<\/li><li>Yarn<\/li><li>Anchor<\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"installing-rust\"><span class=\"ez-toc-section\" id=\"Installing_Rust\"><\/span>Installing Rust<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Start with installing Rust using the terminal.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>curl --proto '=https' --tlsv1.2 -sSf https:\/\/sh.rustup.rs | sh<\/code><\/pre>\n\n\n\n<p>Verify Rust was installed correctly as well as the rust compiler.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>rustup --version\nrustc --version<\/code><\/pre>\n\n\n\n<p>It should have installed also <a href=\"https:\/\/crates.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">Cargo<\/a>, which is Rust package manager. To verify Cargo was installed, run the following command.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>cargo --version<\/code><\/pre>\n\n\n\n<p><strong>Note<\/strong>: If you run into any issues, I recommend checking <a href=\"https:\/\/doc.rust-lang.org\/book\/ch01-01-installation.html\" target=\"_blank\" rel=\"noreferrer noopener\">this Rust installation guide<\/a>. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"installing-solana\"><span class=\"ez-toc-section\" id=\"Installing_Solana\"><\/span>Installing Solana<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>To install Solana, I recommend checking <a href=\"https:\/\/docs.solana.com\/cli\/install-solana-cli-tools#use-solanas-install-tool\" target=\"_blank\" rel=\"noopener\">Solana&#8217;s official installation guide<\/a> to install it. Essentially, you should run the following command.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>sh -c \"$(curl -sSfL https:\/\/release.solana.com\/stable\/install)\"<\/code><\/pre>\n\n\n\n<p>Once the installation is complete, verify it was successfully installed.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>solana --version<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"installing-anchor\"><span class=\"ez-toc-section\" id=\"Installing_Anchor\"><\/span>Installing Anchor<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>If you are using a Linux system or WSL (Linux subsystem), you will need to add additional dependencies:<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>sudo apt-get update &amp;&amp; sudo apt-get upgrade &amp;&amp; sudo apt-get install -y pkg-config build-essential libudev-dev<\/code><\/pre>\n\n\n\n<p>Once the dependencies are installed, use Cargo to install Anchor&#8217;s CLI.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>cargo install --git https:\/\/github.com\/project-serum\/anchor --tag v0.24.1 anchor-cli --locked<\/code><\/pre>\n\n\n\n<p>Finally, verify Anchor&#8217;s CLI is installed correctly.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>anchor --version<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"generate-paper-wallet\"><span class=\"ez-toc-section\" id=\"Generate_Paper_Wallet\"><\/span>Generate Paper Wallet<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>For us to test our Solana program, we need to have a crypto wallet. A crypto wallet stores collections of keys used to send and receive cryptocurrencies. For this tutorial, we are going to use a <a href=\"https:\/\/docs.solana.com\/wallet-guide\/paper-wallet\" target=\"_blank\" rel=\"noreferrer noopener\">paper wallet<\/a> generated using the command line.<\/p>\n\n\n\n<p>To generate a paper wallet, we will use <code>solana-keygen<\/code> , which should have been installed when we installed <code>solana<\/code>. However, to verify it was correctly installed, run the following command:<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>solana-keygen --version<\/code><\/pre>\n\n\n\n<p>If you see the version of <code>solana-keygen<\/code>, that means we can start using it. Run the following command to generate a keypair.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>solana-keygen new<\/code><\/pre>\n\n\n\n<p>This will generate a random seed phrase and prompt you to add an optional passphrase. Feel free to add a passphrase if you want, it is ok not to for the purposes of this tutorial.<\/p>\n\n\n\n<p>Once you fill out the information, the terminal should display the public key and a generated seed phrase. <strong>Copy and<\/strong> <strong>save<\/strong> <strong>the seed phrase in a safe place<\/strong>.<\/p>\n\n\n\n<p>The key pair will be generated in the following location:<\/p>\n\n\n\n<p><code>\/home\/&lt;your user&gt;\/.config\/solana\/id.json<\/code><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"running-the-localnet-cluster\"><span class=\"ez-toc-section\" id=\"Running_the_localnet_Cluster\"><\/span>Running the localnet Cluster<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>To run our Solana program, we need to be in a cluster. According to the Solana documentation, <a href=\"https:\/\/docs.solana.com\/cluster\/overview\" target=\"_blank\" rel=\"noreferrer noopener\">a Solana cluster is a set of validators working together to serve client transactions and maintain the integrity of the ledger<\/a>.<\/p>\n\n\n\n<p>In other words, the Solana program cannot run if it is not in a cluster. Currently, Solana has the following clusters:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>devnet<\/li><li>testnet<\/li><li>mainnet<\/li><\/ul>\n\n\n\n<p>It is possible to connect to <em>localnet<\/em>, which is the cluster run in our local machine in localhost. To connect to <em>localnet<\/em>, we will use Solana CLI.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>solana config set --url localhost<\/code><\/pre>\n\n\n\n<p>Now, verify you connected to <em>localnet<\/em>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>solana config get<\/code><\/pre>\n\n\n\n<p>The terminal should display the RPC URL, the Websocket URL, and the keypair path.   <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"421\" height=\"89\" src=\"https:\/\/www.becomebetterprogrammer.com\/wp-content\/uploads\/2022\/02\/Verify-it-is-connected-to-localnet-cluster.png\" alt=\"\" class=\"wp-image-2108\" title=\"Verify it is connected to localnet cluster\" srcset=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/02\/Verify-it-is-connected-to-localnet-cluster.png 421w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/02\/Verify-it-is-connected-to-localnet-cluster-300x63.png 300w\" sizes=\"auto, (max-width: 421px) 100vw, 421px\" \/><figcaption>Verify it is connected to localnet cluster<\/figcaption><\/figure>\n<\/div>\n\n\n<p>By default, it will connect to port 8899 for RPC and port 8900 for Websocket.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"starting-a-project-with-anchor-framework\"><span class=\"ez-toc-section\" id=\"Starting_a_Project_with_Anchor_Framework\"><\/span>Starting a Project with Anchor Framework<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Use Anchor&#8217;s CLI to start a new project. The following command is the syntax to initialize a new project:<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>anchor init &lt;new-project-name&gt;<\/code><\/pre>\n\n\n\n<p>We are going to give the name of &#8220;mySolanaProgram&#8221;.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>anchor init mySolanaProgram<\/code><\/pre>\n\n\n\n<p>This will create a new folder with the name of the project. If you open the folder, you will see a project with the following folder structure.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.becomebetterprogrammer.com\/wp-content\/uploads\/2022\/01\/Folder-structure-of-the-new-Anchor-project.png\" alt=\"\" class=\"wp-image-2105\" width=\"331\" height=\"405\" title=\"The folder structure of the new Anchor project\"\/><figcaption>The folder structure of the new Anchor project<\/figcaption><\/figure>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"working-on-the-solana-program\"><span class=\"ez-toc-section\" id=\"Working_on_the_Solana_Program\"><\/span>Working on the Solana Program<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Notice there is a <em>lib.rs <\/em>file that lives in the <em>programs\/mySolanaProgram\/src<\/em> folder. In there, it lives the Solana program, or smart contract. Notice the file extension finishes in <em>rs<\/em> which means it is a Rust file. <\/p>\n\n\n\n<p>Open the <em>lib.rs<\/em> file using your favorite IDE. You should see a code similar to the following snippet.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>use anchor_lang::prelude::*;\n\ndeclare_id!(\"Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS\");\n\n#&#91;program]\npub mod my_solana_program {\n    use super::*;\n    pub fn initialize(ctx: Context&lt;Initialize>) -> Result&lt;()> {\n        Ok(())\n    }\n}\n\n#&#91;derive(Accounts)]\npub struct Initialize {}<\/code><\/pre>\n\n\n\n<p>If you don&#8217;t have previous knowledge of Rust, this won&#8217;t make sense at all. The first line of code is a way to import dependencies or libraries in Rust. In this case, it is importing the anchor library.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>use anchor_lang::prelude::*;<\/code><\/pre>\n\n\n\n<p>The <code>declareId<\/code> is where Solana stores the address or program id of your program. By default, Anchor generates a program id for us.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>declare_id!(\"Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS\");<\/code><\/pre>\n\n\n\n<p>Then, you will see a <code>#[program]<\/code> section. This is the program module and is where the logic of the program lives.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>#&#91;program]\npub mod my_solana_program {\n    use super::*;\n    pub fn initialize(ctx: Context&lt;Initialize>) -> Result&lt;()> {\n        Ok(())\n    }\n}<\/code><\/pre>\n\n\n\n<p>Finally, there is a <code>#[derive(Acccounts)]<\/code> section. This is where the Accounts struct lives which is where accounts are validated.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>#&#91;derive(Accounts)]\npub struct Initialize {}<\/code><\/pre>\n\n\n\n<p>You might be wondering what a struct is. A struct defines a group of properties. In other words, structs define the structure of the data. It&#8217;s like defining an interface in TypeScript if you have a background in TypeScript. <\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>interface Initialize {\n}<\/code><\/pre>\n\n\n\n<p>While it is tempting to relate structs as classes or objects, these concepts do not exist in Rust. For example, it is not possible to define methods in structs like you would using another programming language. However, it is possible to define functions to access structs.<\/p>\n\n\n\n<p>You will see the methods manipulating the data are available in the module  <code>pub mod my_solana_program<\/code>. This means, our program will have to pass data by reference from the outside in order to modify it.<\/p>\n\n\n\n<p>This is one of the main differences between Solana and Ethereum, as <strong>Solana&#8217;s goal is to separate code and data. This means the logic could be applied to other pieces of data<\/strong>. <strong>That&#8217;s why Solana programs are considered stateless contracts<\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"updating-the-solana-program\"><span class=\"ez-toc-section\" id=\"Updating_the_Solana_Program\"><\/span>Updating the Solana Program<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Update the logic of the program using the following code. I recommend giving it a look and trying to understand what is going on, even if you don&#8217;t have previous knowledge of Rust.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>#&#91;program]\npub mod my_solana_program {\n    use super::*;\n    pub fn setup_platform(ctx: Context&lt;TweetPlatform>) -> Result&lt;()> {\n        let tweet = &amp;mut ctx.accounts.tweet;\n        tweet.likes = 0;\n        tweet.message = (\"\").to_string();\n        Ok(())\n    }\n\n    pub fn write_tweet(\n        ctx: Context&lt;WriteTweet>,\n        message: String,\n        user_public_key: Pubkey\n    ) -> Result&lt;()> {\n        let tweet = &amp;mut ctx.accounts.tweet;\n\n        if !tweet.message.trim().is_empty() {\n            return err!(ErrorCode::CannotUpdateTweet);\n        }\n\n        if message.trim().is_empty() {\n            return err!(ErrorCode::EmtpyMessage);\n        }\n\n        tweet.message = message;\n        tweet.likes = 0;\n        tweet.creator = user_public_key;\n\n        Ok(())\n    }\n\n    pub fn like_tweet(ctx: Context&lt;LikeTweet>, user_liking_tweet: Pubkey) -> Result&lt;()> {\n        let tweet = &amp;mut ctx.accounts.tweet;\n\n        if tweet.message.trim().is_empty() {\n            return err!(ErrorCode::NotValidTweet);\n        }\n\n        if tweet.likes == 5 {\n            return err!(ErrorCode::ReachedMaxLikes);\n        }\n\n        let mut iter = tweet.people_who_liked.iter();\n        if iter.any(|&amp;v| v == user_liking_tweet) {\n            return err!(ErrorCode::UserLikedTweet);\n        }\n\n        tweet.likes += 1;\n        tweet.people_who_liked.push(user_liking_tweet);\n\n        Ok(())\n    }\n}\n\n#&#91;derive(Accounts)]\npub struct TweetPlatform&lt;'info> {\n    #&#91;account(init, payer = user, space = 9000 )]\n    pub tweet: Account&lt;'info, Tweet>,\n    #&#91;account(mut)]\n    pub user: Signer&lt;'info>,\n    pub system_program: Program&lt;'info, System>, \n}\n\n#&#91;derive(Accounts)]\npub struct WriteTweet&lt;'info> {\n    #&#91;account(mut)]\n    pub tweet: Account&lt;'info, Tweet>,\n}\n\n#&#91;derive(Accounts)]\npub struct LikeTweet&lt;'info> {\n    #&#91;account(mut)]\n    pub tweet: Account&lt;'info, Tweet>\n}\n\n#&#91;account] \/\/An attribute for a data structure representing a Solana account.\n#&#91;derive(Default)]\npub struct Tweet {\n    message: String,\n    likes: u8,\n    creator: Pubkey,\n    people_who_liked: Vec&lt;Pubkey>, \/\/ with  #&#91;derive(Default)] we can assign default values\n}\n\n\n#&#91;error_code]\npub enum Errors {\n    #&#91;msg(\"Tweet message cannot be updated\")]\n    CannotUpdateTweet,\n\n    #&#91;msg(\"Message cannot be empty\")]\n    EmtpyMessage,\n\n    #&#91;msg(\"Cannot receive more than 5 likes\")]\n    ReachedMaxLikes,\n\n    #&#91;msg(\"Cannot like a tweet without a valid message\")]\n    NotValidTweet,\n\n    #&#91;msg(\"User has already liked the tweet\")]\n    UserLikedTweet,\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"understanding-the-logic\"><span class=\"ez-toc-section\" id=\"Understanding_the_Logic\"><\/span>Understanding the Logic<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p><strong>Note: <\/strong>By no means I&#8217;m an expert. However, I will do my best to explain my understanding of how Solana and the Anchor framework works.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"what-does-the-program-do\"><span class=\"ez-toc-section\" id=\"What_does_the_program_do\"><\/span>What does the program do?<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>The main purpose of this Solana program is for a user to write a tweet. The requirements for this program are:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Only one person can write a tweet<\/li><li>The tweet&#8217;s message cannot be empty<\/li><li>The tweet can be liked by up to 5 different users<\/li><li>A user cannot like a tweet more than once<\/li><\/ul>\n\n\n\n<p>These requirements are pretty standard.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"defining-the-program-errors\"><span class=\"ez-toc-section\" id=\"Defining_the_program_errors\"><\/span>Defining the program errors<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>Let&#8217;s start with the bottom of the code. It is an enum of <code>Errors<\/code>, and it is used to define each of the errors.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>#&#91;error_code]\npub enum Errors {\n    #&#91;msg(\"Tweet message cannot be updated\")]\n    CannotUpdateTweet,\n\n    #&#91;msg(\"Message cannot be empty\")]\n    EmtpyMessage,\n\n    #&#91;msg(\"Cannot receive more than 5 likes\")]\n    ReachedMaxLikes,\n\n    #&#91;msg(\"Cannot like a tweet without a valid message\")]\n    NotValidTweet,\n\n    #&#91;msg(\"User has already liked the tweet\")]\n    UserLikedTweet,\n}<\/code><\/pre>\n\n\n\n<p>Notice the attribute <code>#[error_code]<\/code> above the enum <code>Errors<\/code>. This attribute is provided by <code>anchor_lang<\/code> library, which is imported at the top of the file.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>#&#91;error_code]\npub enum Errors {\n    #&#91;msg(\"Tweet message cannot be updated\")]\n    CannotUpdateTweet\n}<\/code><\/pre>\n\n\n\n<p>Notice how there is a <code>#[msg()]<\/code> attribute right above each enum error. This allows us to define a user-friendly error message.<\/p>\n\n\n\n<p>In the following snippet of code, we show you how to throw one of the enum <code>Errors<\/code> by using the <code>Err<\/code> which represents a result type containing a value, value we provide using <code>into()<\/code>. For instance, we return the error <code>CannotUpdateTweet<\/code> using the following syntax <code>return err!(ErrorCode::CannotUpdateTweet);<\/code> if the message of the tweet is not empty. <\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>pub fn write_tweet(\n        ctx: Context&lt;WriteTweet>,\n        message: String,\n        user_public_key: Pubkey\n    ) -> ProgramResult {\n        \/\/ some logic\n\n        if !tweet.message.trim().is_empty() {\n            return err!(ErrorCode::CannotUpdateTweet);\n        }\n\n        \/\/ more logic\n    }<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"defining-the-structures\"><span class=\"ez-toc-section\" id=\"Defining_the_Structures\"><\/span>Defining the Structures<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>Let&#8217;s move on to defining the structs, or the structures of data.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>#&#91;derive(Accounts)]\npub struct TweetPlatform&lt;'info&gt; {\n    #&#91;account(init, payer = user, space = 9000 )]\n    pub tweet: Account&lt;'info, Tweet&gt;,\n    #&#91;account(mut)]\n    pub user: Signer&lt;'info&gt;,\n    pub system_program: Program&lt;'info, System&gt;, \n}\n\n#&#91;derive(Accounts)]\npub struct WriteTweet&lt;'info&gt; {\n    #&#91;account(mut)]\n    pub tweet: Account&lt;'info, Tweet&gt;,\n}\n\n#&#91;derive(Accounts)]\npub struct LikeTweet&lt;'info&gt; {\n    #&#91;account(mut)]\n    pub tweet: Account&lt;'info, Tweet&gt;\n}\n\n#&#91;account]\n#&#91;derive(Default)]\npub struct Tweet {\n    message: String,\n    likes: u8,\n    creator: Pubkey,\n    people_who_liked: Vec&lt;Pubkey&gt;\n}<\/code><\/pre>\n\n\n\n<p>Let&#8217;s start with the struct where the main logic of the program is based on, the <code>Tweet<\/code> struct.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>#&#91;account]\n#&#91;derive(Default)]\npub struct Tweet {\n    message: String,\n    likes: u8,\n    creator: Pubkey,\n    people_who_liked: Vec&lt;Pubkey&gt;\n}<\/code><\/pre>\n\n\n\n<p>It is incorrect to call <code>message<\/code>, <code>likes<\/code>, <code>creator<\/code>, and <code>people_who_liked<\/code> &#8220;properties&#8221;. However, you can think of them in that way to relate if you are coming from object-oriented programming. In theory, we are only defining the names and types of the pieces of data.<\/p>\n\n\n\n<p>The <code>String<\/code> type is itself a string, but the other types you might not be familiar with.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><code>u8<\/code> is an unsigned integer type.<\/li><li><code>Pubkey<\/code> is a public key type of a solana account.<\/li><li><code>Vec&lt;&gt;<\/code> is a growable array type. Hence, <code>Vec&lt;Pubkey&gt;<\/code> is a growable array type of public key types.<\/li><\/ul>\n\n\n\n<p>There is the <code>#[account]<\/code> attribute and it defines the data structure of a Solana account. One of the main characteristics of this attribute is to generate implementations to serialize and deserialize an account. <a href=\"https:\/\/docs.rs\/anchor-lang\/latest\/anchor_lang\/attr.account.html\" target=\"_blank\" rel=\"noreferrer noopener\">According to the docs<\/a>, when implementing account serialization traits the first 8 bytes are reserved for a unique account discriminator, self-described by the first 8 bytes of the SHA256 of the account\u2019s Rust ident.AccountSerialize.<\/p>\n\n\n\n<p>Finally, there is <code>#[derive(Default)]<\/code>, and it allows defining default values for the pieces of data whenever the struc is generated. Currently, we are not setting default data. <\/p>\n\n\n\n<p>Let&#8217;s move on to the <code>TweetPlatform<\/code> structure, which contains the <code>tweet<\/code>, <code>user<\/code> and <code>system_program<\/code> pieces of data.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>#&#91;derive(Accounts)]\npub struct TweetPlatform&lt;'info&gt; {\n    #&#91;account(init, payer = user, space = 9000 )]\n    pub tweet: Account&lt;'info, Tweet&gt;,\n    #&#91;account(mut)]\n    pub user: Signer&lt;'info&gt;,\n    pub system_program: Program&lt;'info, System&gt;, \n}<\/code><\/pre>\n\n\n\n<p>Pay attention to the use of the derive attribute <code>#[derive(Accounts)]<\/code>. This allows deserializing the Solana accounts so they can be validated and prevent account substitution attacks. A derive attribute allows new items to be automatically generated for data structures.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>   #&#91;account(init, payer = user, space = 9000 )]\n    pub tweet: Account&lt;'info, Tweet&gt;<\/code><\/pre>\n\n\n\n<p>Notice the use of <code>init<\/code> attribute for the <code>tweet<\/code> field. In other words, this will create a new account owned by the current program. Using <code>init<\/code> requires someone to pay for creating the account.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>   #&#91;account(init, payer = user, space = 9000 )]\n    pub tweet: Account&lt;'info, Tweet&gt;,\n    #&#91;account(mut)]\n    pub user: Signer&lt;'info&gt;,<\/code><\/pre>\n\n\n\n<p>In this case, the <code>user<\/code> field is defined as the account that will provide the funds to create the <code>tweet<\/code> account. Finally, there is the <code>space<\/code> attribute. This defines how large the <code>tweet<\/code> account should be. For the purposes of this tutorial, we assigned 9000, but this should be calculated beforehand to know how much space it will occupy the program.<\/p>\n\n\n\n<p>When using the <code>init<\/code> attribute, we must provide the <code>system_program<\/code> . This is required by the runtime to create the account.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>pub system_program: Program&lt;'info, System&gt;,<\/code><\/pre>\n\n\n\n<p>Finally, we have the <code>WriteTweet<\/code> and <code>LikeTweet<\/code> structs.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>#&#91;derive(Accounts)]\npub struct WriteTweet&lt;'info&gt; {\n    #&#91;account(mut)]\n    pub tweet: Account&lt;'info, Tweet&gt;,\n}\n\n#&#91;derive(Accounts)]\npub struct LikeTweet&lt;'info&gt; {\n    #&#91;account(mut)]\n    pub tweet: Account&lt;'info, Tweet&gt;\n}<\/code><\/pre>\n\n\n\n<p>These structs have the <code>tweet<\/code> account defined with the attribute <code>#[account(mut)]<\/code>. The <code>mut<\/code> flag allows keeping changes made to the account even after exiting the program.<\/p>\n\n\n\n<p>Hence, there are two flags you must take into consideration. The <code>init<\/code> and the <code>mut<\/code> flags. The first is used when the account (<code>tweet<\/code>) is used for the first time and the <code>mut<\/code> is used to persist any changes, for instance, writing a value to <code>message<\/code> or updating the <code>likes<\/code> field.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"defining-instructions-in-the-module\"><span class=\"ez-toc-section\" id=\"Defining_instructions_in_the_module\"><\/span>Defining instructions in the module<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>It&#8217;s time to talk about the methods defined in the module. These are called instructions. <a href=\"https:\/\/docs.solana.com\/developing\/programming-model\/transactions#:~:text=an%20ed25519%20keypair.-,Instructions,accounts%20specified%20by%20the%20instructions.\" target=\"_blank\" rel=\"noreferrer noopener\">Based on Solana documentation<\/a>, an instruction specifies a single program, a subset of the transaction&#8217;s accounts that should be passed to the program, and a data byte array that is passed to the program. The program interprets the data array and operates on the accounts specified by the instructions.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>#&#91;program]\npub mod my_solana_program {\n    use super::*;\n    pub fn setup_platform(ctx: Context&lt;TweetPlatform>) -> Result&lt;()> {\n        let tweet = &amp;mut ctx.accounts.tweet;\n        tweet.likes = 0;\n        tweet.message = (\"\").to_string();\n        Ok(())\n    }\n\n    pub fn write_tweet(\n        ctx: Context&lt;WriteTweet>,\n        message: String,\n        user_public_key: Pubkey\n    ) ->Result&lt;()> {\n        let tweet = &amp;mut ctx.accounts.tweet;\n\n        if !tweet.message.trim().is_empty() {\n            return err!(ErrorCode::CannotUpdateTweet);\n        }\n\n        if message.trim().is_empty() {\n            return err!(ErrorCode::EmtpyMessage);\n        }\n\n        tweet.message = message;\n        tweet.likes = 0;\n        tweet.creator = user_public_key;\n\n        Ok(())\n    }\n\n    pub fn like_tweet(ctx: Context&lt;LikeTweet>, user_liking_tweet: Pubkey) -> Result&lt;()> {\n        let tweet = &amp;mut ctx.accounts.tweet;\n\n        if tweet.message.trim().is_empty() {\n            return err!(ErrorCode::NotValidTweet);\n        }\n\n        if tweet.likes == 5 {\n            return err!(ErrorCode::ReachedMaxLikes);\n        }\n\n        let mut iter = tweet.people_who_liked.iter();\n        if iter.any(|&amp;v| v == user_liking_tweet) {\n            return err!(ErrorCode::UserLikedTweet);\n        }\n\n        tweet.likes += 1;\n        tweet.people_who_liked.push(user_liking_tweet);\n\n        Ok(())\n    }\n}<\/code><\/pre>\n\n\n\n<p>Let&#8217;s start with the <code>setup_platform<\/code> method.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>pub fn setup_platform(ctx: Context&lt;TweetPlatform>) -> Result&lt;()> {\n        let tweet = &amp;mut ctx.accounts.tweet;\n        tweet.likes = 0;\n        tweet.message = (\"\").to_string();\n        Ok(())\n    }<\/code><\/pre>\n\n\n\n<p>The first thing to notice is the usage of a ctx parameter via Context&lt;&gt;. The Context&lt;&gt; deserializes the accounts found in the struct type passed, in this case, the <code>TweetPlatform<\/code>. That&#8217;s why you can access the field <code>tweet<\/code> when using <code>ctx.accounts<\/code>.<\/p>\n\n\n\n<p>There are other data fields you can access via <code>ctx<\/code> parameter<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><code>program_id<\/code>: The current executing program id.<\/li><li><code>remaining_accounts<\/code>: Other accounts given but not deserialized or validated.<\/li><\/ul>\n\n\n\n<p>Which we are not using, but it is important to know about in case we need access to other data fields of a struct.<\/p>\n\n\n\n<p>Also, we use the keyword <code>&amp;mut<\/code> to get the mutable reference of the <code>tweet<\/code> data field. Remember, <strong>Solana programs are considered stateless contracts<\/strong>. This means there are no variables and data must be passed from the outside if we want to modify it.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>let tweet = &amp;mut ctx.accounts.tweet;<\/code><\/pre>\n\n\n\n<p>While the <code>setup_platform<\/code> instruction doesn&#8217;t seem to do much besides setting the <code>likes<\/code> data to 0 and the <code>message<\/code> to an empty string, it is important to remember this process must happen as the <code>TweetPlatform<\/code> struc uses the <code>init<\/code> attribute to create <code>tweet<\/code> account.<\/p>\n\n\n\n<p>Now, let&#8217;s look a the <code>write_tweet<\/code> instruction.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>pub fn write_tweet(\n        ctx: Context&lt;WriteTweet>,\n        message: String,\n        user_public_key: Pubkey\n    ) -> Result&lt;()> {\n        let tweet = &amp;mut ctx.accounts.tweet;\n\n        if !tweet.message.trim().is_empty() {\n            return err!(ErrorCode::CannotUpdateTweet);\n        }\n\n        if message.trim().is_empty() {\n            return err!(ErrorCode::EmtpyMessage);\n        }\n\n        tweet.message = message;\n        tweet.likes = 0;\n        tweet.creator = user_public_key;\n\n        Ok(())\n    }<\/code><\/pre>\n\n\n\n<p>There are two new things happening in this instruction.<\/p>\n\n\n\n<p>One of them is for the Solana program to accept incoming data used to modify an account (<code>tweet<\/code>). Besides accepting the context <code>ctx: Context&lt;WriteTweet&gt;<\/code>, which we used to deserialize and access <code>tweet<\/code> account, <\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>A user can pass a <code>message<\/code>.<\/li><li>A user can pass their <code>user_public_key<\/code> to &#8220;write&#8221; a new tweet and identify the creator or owner of the tweet.<\/li><\/ul>\n\n\n\n<p>The second new part is to apply restrictions to the <code>tweet<\/code> account.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Cannot overwrite a <code>tweet.message<\/code> if the <code>tweet.message<\/code> has already data.<\/li><li>Cannot write an empty <code>tweet.message<\/code> if the <code>message<\/code> provided by the external user is empty.<\/li><\/ul>\n\n\n\n<p>This allows us to use our custom program errors in case any of these fails.<\/p>\n\n\n\n<p>If you paid close attention, we used the <code>WriteTweet<\/code> struct which uses the <code>mut<\/code> attribute on the <code>tweet<\/code> account. Remember, this attribute marks the account as mutable and persists changes. That&#8217;s why, if we access the <code>tweet<\/code> account in a different instruction such as <code>like_tweet<\/code>, we can add additional check to verify the <code>tweet.message<\/code> is not empty, which infers the <code>tweet.message<\/code> should have been previously updated in the <code>write_tweet<\/code> instruction.<\/p>\n\n\n\n<p>Finally, we have the <code>like_tweet<\/code> instruction.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>pub fn like_tweet(ctx: Context&lt;LikeTweet>, user_liking_tweet: Pubkey) -> Result&lt;()> {\n        let tweet = &amp;mut ctx.accounts.tweet;\n\n        if tweet.message.trim().is_empty() {\n             return err!(ErrorCode::NotValidTweet);\n        }\n\n        if tweet.likes == 5 {\n            return err!(ErrorCode::ReachedMaxLikes);\n        }\n\n        let mut iter = tweet.people_who_liked.iter();\n        if iter.any(|&amp;v| v == user_liking_tweet) {\n            return err!(ErrorCode::UserLikedTweet);\n        }\n\n        tweet.likes += 1;\n        tweet.people_who_liked.push(user_liking_tweet);\n\n        Ok(())\n    }<\/code><\/pre>\n\n\n\n<p>Hopefully, this won&#8217;t require much explanation as most of the concepts were explained when we covered the other two instructions, <code>setup_platform<\/code> and <code>write_tweet<\/code>. Probably, the only part it might be new for those without much Rust experience is the way we are checking if a new user has liked a tweet before or not.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>        let mut iter = tweet.people_who_liked.iter();\n        if iter.any(|&amp;v| v == user_liking_tweet) {\n            return Err(Errors::UserLikedTweet.into());\n        }\n\n\n        tweet.people_who_liked.push(user_liking_tweet);<\/code><\/pre>\n\n\n\n<p>In short, we need to iterate through all of the values from the <code>people_who_liked<\/code> data field to verify if the user liking the tweet (<code>user_liking_tweet<\/code>) has liked it before. Otherwise, add the <code>user_liking_tweet<\/code> to the array.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"build-the-program\"><span class=\"ez-toc-section\" id=\"Build_the_program\"><\/span>Build the program<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>After you added all the program logic in the <em>lib.rs<\/em> file, go ahead and build the program using the following command.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>anchor build<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"testing-the-program\"><span class=\"ez-toc-section\" id=\"Testing_the_program\"><\/span>Testing the program<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>If you haven&#8217;t written many programmatic tests in the past, you will find writing tests more often than what you have ever done in your career when working in web3.<\/p>\n\n\n\n<p>When we created this project using the Anchor framework, it generated a <em>tests\/mySolanaProgram.ts<\/em> file.<\/p>\n\n\n\n<p>Update the <em>mySolanaProgram.ts<\/em> file with the following tests.<\/p>\n\n\n\n<pre class=\"wp-block-code language-typescript\"><code>import * as anchor from '@project-serum\/anchor';\nimport { Program } from '@project-serum\/anchor';\nimport { MySolanaProgram } from '..\/target\/types\/my_solana_program';\nimport { expect, assert } from 'chai';\n\ndescribe('mySolanaProgram', () => {\n\n  \/\/ Configure the client to use the local cluster.\n  anchor.setProvider(anchor.AnchorProvider.local());\n\n  const program = anchor.workspace.MySolanaProgram as Program&lt;MySolanaProgram>;\n  it('setup tweet platform!', async () => {\n    const tweetKeypair = anchor.web3.Keypair.generate();\n    const user = program.provider.wallet;\n    await program.rpc.setupPlatform({\n      accounts: {\n        tweet: tweetKeypair.publicKey,\n        user: user.publicKey,\n        systemProgram: anchor.web3.SystemProgram.programId\n      },\n      signers: &#91;tweetKeypair]\n    });\n\n    let tweet = await program.account.tweet.fetch(tweetKeypair.publicKey);\n    expect(tweet.likes).to.equal(0);\n    expect(tweet.message).to.equal('');\n  });\n\n  it('Write a tweet', async () => {\n    const tweetKeypair = anchor.web3.Keypair.generate();\n    const user = program.provider.wallet;\n    await program.rpc.setupPlatform({\n      accounts: {\n        tweet: tweetKeypair.publicKey,\n        user: user.publicKey,\n        systemProgram: anchor.web3.SystemProgram.programId\n      },\n      signers: &#91;tweetKeypair]\n    });\n\n    let tweet = await program.account.tweet.fetch(tweetKeypair.publicKey);\n    expect(tweet.likes).to.equal(0);\n    expect(tweet.message).to.equal('');\n\n    await program.rpc.writeTweet('Hello World!', user.publicKey, {\n      accounts: {\n        tweet: tweetKeypair.publicKey,\n      },\n      signers: &#91;]\n    });\n\n    tweet = await program.account.tweet.fetch(tweetKeypair.publicKey);\n\n    expect(tweet.likes).to.equal(0);\n    expect(tweet.message).to.equal('Hello World!');\n    expect(tweet.creator.toString()).to.equal(user.publicKey.toString());\n  });\n\n  it('should like tweet up no more than 5 times', async () => {\n    const tweetKeypair = anchor.web3.Keypair.generate();\n    const user = program.provider.wallet;\n    await program.rpc.setupPlatform({\n      accounts: {\n        tweet: tweetKeypair.publicKey,\n        user: user.publicKey,\n        systemProgram: anchor.web3.SystemProgram.programId\n      },\n      signers: &#91;tweetKeypair]\n    });\n\n    let tweet = await program.account.tweet.fetch(tweetKeypair.publicKey);\n    expect(tweet.likes).to.equal(0);\n    expect(tweet.message).to.equal('');\n\n    await program.rpc.writeTweet('Hello World!', user.publicKey, {\n      accounts: {\n        tweet: tweetKeypair.publicKey,\n      },\n      signers: &#91;]\n    });\n\n    tweet = await program.account.tweet.fetch(tweetKeypair.publicKey);\n    expect(tweet.likes).to.equal(0);\n    expect(tweet.message).to.equal('Hello World!');\n    expect(tweet.creator.toString()).to.equal(user.publicKey.toString());\n\n    await program.rpc.likeTweet(user.publicKey, {\n      accounts: {\n        tweet: tweetKeypair.publicKey,\n      },\n      signers: &#91;]\n    });\n\n    tweet = await program.account.tweet.fetch(tweetKeypair.publicKey);\n    expect(tweet.likes).to.equal(1);\n    expect(tweet.peopleWhoLiked&#91;0].toString()).to.equal(user.publicKey.toString());\n\n    try {\n      await program.rpc.likeTweet(user.publicKey, {\n        accounts: {\n          tweet: tweetKeypair.publicKey,\n        },\n        signers: &#91;]\n      });\n\n      assert.ok(false);\n    } catch (error) {\n      const expectedError = 'User has already liked the tweet';\n      assert.equal(error.error.errorMessage, expectedError);\n    }\n\n\n    const secondUser = anchor.web3.Keypair.generate();\n    await program.rpc.likeTweet(secondUser.publicKey, {\n      accounts: {\n        tweet: tweetKeypair.publicKey,\n      },\n      signers: &#91;]\n    });\n\n    tweet = await program.account.tweet.fetch(tweetKeypair.publicKey);\n    expect(tweet.likes).to.equal(2);\n    expect(tweet.peopleWhoLiked&#91;1].toString()).to.equal(secondUser.publicKey.toString());\n\n\n\n    const thirdUser = anchor.web3.Keypair.generate();\n    await program.rpc.likeTweet(thirdUser.publicKey, {\n      accounts: {\n        tweet: tweetKeypair.publicKey,\n      },\n      signers: &#91;]\n    });\n\n    tweet = await program.account.tweet.fetch(tweetKeypair.publicKey);\n    expect(tweet.likes).to.equal(3);\n    expect(tweet.peopleWhoLiked&#91;2].toString()).to.equal(thirdUser.publicKey.toString());\n\n\n\n    const fourthUser = anchor.web3.Keypair.generate();\n    await program.rpc.likeTweet(fourthUser.publicKey, {\n      accounts: {\n        tweet: tweetKeypair.publicKey,\n      },\n      signers: &#91;]\n    });\n\n    tweet = await program.account.tweet.fetch(tweetKeypair.publicKey);\n    expect(tweet.likes).to.equal(4);\n    expect(tweet.peopleWhoLiked&#91;3].toString()).to.equal(fourthUser.publicKey.toString());\n\n\n\n    const fifthUser = anchor.web3.Keypair.generate();\n    await program.rpc.likeTweet(fifthUser.publicKey, {\n      accounts: {\n        tweet: tweetKeypair.publicKey,\n      },\n      signers: &#91;]\n    });\n\n    tweet = await program.account.tweet.fetch(tweetKeypair.publicKey);\n    expect(tweet.likes).to.equal(5);\n    expect(tweet.peopleWhoLiked&#91;4].toString()).to.equal(fifthUser.publicKey.toString());\n\n\n    const sixthUser = anchor.web3.Keypair.generate();\n    try {\n\n\n      await program.rpc.likeTweet(sixthUser.publicKey, {\n        accounts: {\n          tweet: tweetKeypair.publicKey,\n        },\n        signers: &#91;]\n      });\n\n      assert.ok(false);\n    } catch (error) {\n      assert.equal(error.error.errorMessage, 'Cannot receive more than 5 likes');\n    }\n  });\n\n  it('should not allow writting an empty message', async () => {\n    const tweetKeypair = anchor.web3.Keypair.generate();\n    const user = program.provider.wallet;\n    await program.rpc.setupPlatform({\n      accounts: {\n        tweet: tweetKeypair.publicKey,\n        user: user.publicKey,\n        systemProgram: anchor.web3.SystemProgram.programId\n      },\n      signers: &#91;tweetKeypair]\n    });\n\n    let tweet = await program.account.tweet.fetch(tweetKeypair.publicKey);\n    expect(tweet.likes).to.equal(0);\n    expect(tweet.message).to.equal('');\n\n\n    try {\n      await program.rpc.writeTweet('', user.publicKey, {\n        accounts: {\n          tweet: tweetKeypair.publicKey,\n        },\n        signers: &#91;]\n      });\n      assert.ok(false);\n    } catch (error) {\n      assert.equal(error.error.errorMessage, 'Message cannot be empty');\n    }\n  });\n});<\/code><\/pre>\n\n\n\n<p>What you will find interesting is how programmatic tests are written in a different programming language (Typescript, but you could configure it also to use JavaScript), and the Solana program uses Rust.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>The Anchor workflow recommends to test your program using integration tests in a language other than Rust to make sure that bugs related to syntax misunderstandings are coverable with tests and not just replicated in tests.<\/p><cite><a href=\"https:\/\/project-serum.github.io\/anchor\/cli\/commands.html#new\" target=\"_blank\" rel=\"noopener\">Anchor documentation<\/a><\/cite><\/blockquote>\n\n\n\n<p>When you built the Solana program in the previous step, it generates an IDL located in the <em>target\/idl<\/em> folder. The IDL is an interface definition language that lets a program written in one language communicate with another program written in an unknown language.<\/p>\n\n\n\n<p>Hence, we can access the instructions we defined in <code>my_solana_program<\/code> in TypeScript so we can validate they are properly working.<\/p>\n\n\n\n<p>By default, anchor added <code>mocha<\/code> and <code>chai<\/code>, JavaScript testing libraries which you can find in the <code>devDependencies<\/code> of the <em>package.json<\/em>.<\/p>\n\n\n\n<p>We won&#8217;t go into details explaining how these libraries work. However, there are a few things to take into account which we will explain below.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"configuring-to-use-a-specific-cluster\"><span class=\"ez-toc-section\" id=\"Configuring_to_use_a_specific_cluster\"><\/span>Configuring to use a specific cluster<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Solana programs are run in clusters. As previously mentioned, the clusters available are devnet, testnet, mainnet, and localnet which is the local cluster. The following line of code is Anchor helping us configure the client to use a specific cluster.<\/p>\n\n\n\n<pre class=\"wp-block-code language-typescript\"><code>\/\/ Configure the client to use the local cluster.\n  anchor.setProvider(anchor.AnchorProvider.local());<\/code><\/pre>\n\n\n\n<p>Currently, the comments said that <code>\/\/ Configure the client to use the local cluster.<\/code> What is truly getting the local cluster is this line of code.<\/p>\n\n\n\n<pre class=\"wp-block-code language-typescript\"><code>anchor.AnchorProvider.local()<\/code><\/pre>\n\n\n\n<p>In other words, that checks the <em>Anchor.toml<\/em> file and checks the cluster set up in <code>[provider]<\/code> section. By default, it should have been set to &#8220;localnet&#8221;. Hence, if you decide to update it to another cluster, it will configure that cluster at the moment of executing the tests.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"accessing-the-solana-program-and-executing-instructions\"><span class=\"ez-toc-section\" id=\"Accessing_the_Solana_program_and_executing_instructions\"><\/span>Accessing the Solana program and executing instructions<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Anchor does a lot of the heavy lifting for us to access the Solana program by using the <code>program<\/code> variable.<\/p>\n\n\n\n<pre class=\"wp-block-code language-typescript\"><code>const program = anchor.workspace.MySolanaProgram as Program&lt;MySolanaProgram&gt;;<\/code><\/pre>\n\n\n\n<p>Anchor provides  <code>workspace<\/code> as a way to access all Solana programs in the local project.<\/p>\n\n\n\n<p>Anchor also has a helper function to generate key pairs to execute the tests. Remember, these key pairs represent a wallet which are accounts we validate in the Solana program.<\/p>\n\n\n\n<pre class=\"wp-block-code language-typescript\"><code>const tweetKeypair = anchor.web3.Keypair.generate();<\/code><\/pre>\n\n\n\n<p>Finally, notice how we are triggering the instructions or methods of the Solana program via the <code>rpc<\/code> property <\/p>\n\n\n\n<pre class=\"wp-block-code language-typescript\"><code>await program.rpc.setupPlatform({\n      accounts: {\n        tweet: tweetKeypair.publicKey,\n        user: user.publicKey,\n        systemProgram: anchor.web3.SystemProgram.programId\n      },\n      signers: &#91;tweetKeypair]\n    });<\/code><\/pre>\n\n\n\n<p>Notice how Anchor updated the naming convention of the methods from one programming language to another. In Rust, it is called <code>setup_platform<\/code> and in JavaScript it is called <code>setupPlatform<\/code>.<\/p>\n\n\n\n<p>Finally, notice how we access the data from the program via <code>program.account<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-typescript\"><code>await program.account.tweet.fetch(tweetKeypair.publicKey);<\/code><\/pre>\n\n\n\n<p>In this case, we access the <code>tweet<\/code> account, and trigger the <code>fetch<\/code> method using the public key for the <code>tweet<\/code> account to access deserialized data, which we use to run tests validations.<\/p>\n\n\n\n<pre class=\"wp-block-code language-typescript\"><code>let tweet = await program.account.tweet.fetch(tweetKeypair.publicKey);\nexpect(tweet.likes).to.equal(0);\nexpect(tweet.message).to.equal('');<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"running-the-tests\"><span class=\"ez-toc-section\" id=\"Running_the_tests\"><\/span>Running the tests<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>To run the tests, execute the following command.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>anchor test<\/code><\/pre>\n\n\n\n<p>This will build, deploy, and test programs against a specific cluster.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"deploying-the-program\"><span class=\"ez-toc-section\" id=\"Deploying_the_program\"><\/span>Deploying the program<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>For this tutorial, we will deploy the Solana program to devnet. To do so, we must do the following.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"configure-devnet-cluster\"><span class=\"ez-toc-section\" id=\"Configure_devnet_cluster\"><\/span>Configure devnet cluster<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>solana config set --url devnet<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"make-sure-you-are-on-the-devnet-cluster\"><span class=\"ez-toc-section\" id=\"Make_sure_you_are_on_the_devnet_cluster\"><\/span>Make sure you are on the devnet cluster<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>solana config get<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"build-the-program-2\"><span class=\"ez-toc-section\" id=\"Build_the_program-2\"><\/span>Build the program<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>anchor build<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"generate-a-new-program-id\"><span class=\"ez-toc-section\" id=\"Generate_a_new_program_id\"><\/span>Generate a new program id<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>By default, Anchor generated a program id for local development. We need to generate a program id before we deploy to devnet.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>solana address -k target\/deploy\/my_solana_program-keypair.json<\/code><\/pre>\n\n\n\n<p>Copy the program id and save it. We will use it in the next step.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"update-program-id-in-anchor-toml-and-lib-rs\"><span class=\"ez-toc-section\" id=\"Update_program_id_in_Anchortoml_and_librs\"><\/span>Update program id in Anchor.toml and lib.rs<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Now that you have the program id, open the <em>Anchor.toml<\/em> file and do the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Update <code>[programs.localnet]<\/code> to <code>[programs.devnet]<\/code>.<\/li><li>Update the program id set in <code>my_solana_program<\/code> with the new program id.<\/li><li>Update the cluster to <code>cluster = \"devnet\"<\/code>.<\/li><\/ul>\n\n\n\n<p>Open the <em>lib.rs<\/em> file and update the program id used in the <code>declar_id!<\/code> function.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>declare_id!(&lt;MY_NEW_PROGRAM_ID&gt;);<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"build-the-program-one-more-time\"><span class=\"ez-toc-section\" id=\"Build_the_program_one_more_time\"><\/span>Build the program one more time<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>anchor build<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"deploy-to-devnet\"><span class=\"ez-toc-section\" id=\"Deploy_to_devnet\"><\/span>Deploy to devnet<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Finally, we are ready to deploy.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>anchor deploy<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"verify-solana-explorer\"><span class=\"ez-toc-section\" id=\"Verify_Solana_Explorer\"><\/span>Verify Solana Explorer<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Open <a href=\"https:\/\/explorer.solana.com\/?cluster=devnet\" target=\"_blank\" rel=\"noreferrer noopener\">Solana Explorer<\/a> devnet and verify it was successfully deployed by providing the program id.<\/p>\n\n\n\n<p><strong>NOTE<\/strong>: Make sure to select &#8220;devnet&#8221; in the top right corner once you are in the Solana Explorer,<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"887\" src=\"https:\/\/www.becomebetterprogrammer.com\/wp-content\/uploads\/2022\/02\/Verify-deployed-Solana-program-in-Solana-Explorer-1024x887.png\" alt=\"\" class=\"wp-image-2116\" srcset=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/02\/Verify-deployed-Solana-program-in-Solana-Explorer-1024x887.png 1024w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/02\/Verify-deployed-Solana-program-in-Solana-Explorer-300x260.png 300w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/02\/Verify-deployed-Solana-program-in-Solana-Explorer-768x665.png 768w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/02\/Verify-deployed-Solana-program-in-Solana-Explorer.png 1317w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Check out the transaction history section. You should only have one transaction. This should tell you when it was deployed.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"conclusion\"><span class=\"ez-toc-section\" id=\"Conclusion\"><\/span>Conclusion<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>This was an extensive tutorial and I hope you were able to create your Solana program using the Anchor framework. We covered several topics and even learned a new programming language like Rust, for those without previous experience in Rust. We learned how to use Anchor CLI to build, deploy and execute tests, and wrote tests cases to make sure our Solana program worked as expected.<\/p>\n\n\n\n<p>I encourage you to make changes to the project and further develop this Solana program if you wish to. By no means do I consider myself an expert. However, I did my best effort to explain the concepts after a lot of research to break them into more digestible content.<\/p>\n\n\n\n<p><strong>Was this tutorial helpful?<\/strong><\/p>\n\n\n\n<p>Hopefully, <strong>it was not only informative to build the Solana smart contract, but also helpful as I understand how complex and confusing this can turn with too many new concepts going on<\/strong>.<\/p>\n\n\n\n<p><strong>If it was, share it with your friends and colleagues interested in the world of Web3 development.<\/strong><\/p>\n\n\n\n<p>I recommend you to check out <a href=\"https:\/\/www.becomebetterprogrammer.com\/web3-react-connect-to-phantom\/\">How to Connect a Web3 React App to Phantom using TypeScript<\/a> if you are interested in learning how to connect to a Phantom wallet using React, which could give you the option to connect to any Solana program, even the Solana program we deployed in devnet in this tutorial.<\/p>\n\n\n\n<p>Share your thoughts by replying on <a href=\"https:\/\/twitter.com\/bbprogrammer\" target=\"_blank\" rel=\"noreferrer noopener\">Twitter of Become A Better Programmer<\/a> or to <a href=\"https:\/\/twitter.com\/arealesramirez\" target=\"_blank\" rel=\"noreferrer noopener\">my personal Twitter account<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-embed aligncenter is-type-rich is-provider-twitter wp-block-embed-twitter\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"twitter-tweet\" data-width=\"550\" data-dnt=\"true\"><p lang=\"en\" dir=\"ltr\">We got a new tutorial I&#39;m sure many of you are interested in getting your hands &quot;wet&quot; in <a href=\"https:\/\/twitter.com\/hashtag\/web3?src=hash&amp;ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"noopener\">#web3<\/a> and would want to check out!<br><br>Learn how to create a Solana program (or smart contract) in <a href=\"https:\/\/twitter.com\/hashtag\/Rust?src=hash&amp;ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"noopener\">#Rust<\/a> and <a href=\"https:\/\/twitter.com\/hashtag\/TypeScript?src=hash&amp;ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"noopener\">#TypeScript<\/a> using the Anchor framework!<a href=\"https:\/\/t.co\/airHECcSwz\">https:\/\/t.co\/airHECcSwz<\/a><\/p>&mdash; Become A Better Programmer (@bbprogrammer) <a href=\"https:\/\/twitter.com\/bbprogrammer\/status\/1488893305391919105?ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"noopener\">February 2, 2022<\/a><\/blockquote><script async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script>\n<\/div><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>Learn how to create a Solana program, or smart contract using the Anchor framework, Rust, and TypeScript in this detailed tutorial.<\/p>\n","protected":false},"author":1,"featured_media":2118,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"nf_dc_page":"","_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[29],"tags":[],"class_list":["post-1962","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-web3","generate-columns","tablet-grid-50","mobile-grid-100","grid-parent","grid-50"],"_links":{"self":[{"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/posts\/1962","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/comments?post=1962"}],"version-history":[{"count":5,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/posts\/1962\/revisions"}],"predecessor-version":[{"id":2804,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/posts\/1962\/revisions\/2804"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/media\/2118"}],"wp:attachment":[{"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/media?parent=1962"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/categories?post=1962"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/tags?post=1962"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}