Create a Solana dApp from scratch

Getting started with Solana and Anchor

Episode 2
1 week ago
14 min read

Getting started with Solana can be quite the chore without a guide. In this article, I’ll make sure we have everything ready in our local machine to get started with Solana programs using the Anchor framework.

Since there is quite a lot to go through, I'll make sure to get to the point quickly so you can re-read this article as an actionable checklist in the future. That being said, we will spend a bit of time digging through how Anchor works to better understand the "Build, Deploy, Test" cycle we will use throughout this series.

If you're a Windows user, I'm afraid this guide is more tailored for Linux and Mac users. Fortunately, Buildspace has got a nice guide for installing Solana on a Windows machine so hopefully, you can still follow along after that.

I’d also like to add that the Solana ecosystem moves relatively quickly and, therefore, some of these steps might end up changing or — fingers crossed — being simplified in the future. If that’s the case, please reach out to me and I’ll make sure to update the article accordingly.

Finally, here's a table of content in case you're re-reading this and looking for a particular section.

Install Rust

Why? Rust is the language Solana uses to build programs.

Installing Rust is as simple as running this.

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

When installed, it will add the following PATH — or similar — to your shell configurations which is good to know if you want to move that to your dotfiles or something.

export PATH="$HOME/.cargo/bin:$PATH"

You can check that rust is properly installed by running the following commands.

rustup --version
rustc --version
cargo --version

Install Solana

Similarly, you can install Solana by running the following installer script.

sh -c "$(curl -sSfL https://release.solana.com/v1.8.5/install)"

Note that newer versions have been released since then so feel free to use them but this is the Solana version I used for this tutorial.

Installing Solana will also add a new PATH to your shell configurations. Alternatively, depending on your system, it might ask you to manually update your PATH by providing you with a line to copy/paste.

export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH"

You can check that Solana is properly installed by running the following commands.

# Check the Solana binary is available.
solana --version

# Check you can run a local validator (Run Ctrl+C to exit).
# We’ll see what this does in this article.
# Note this creates a "test-ledger" folder in your current directory.
solana-test-validator

Install Solana on Apple M1

Unfortunately, at the time of writing, the Solana installer script above will not work on Apple M1 computers.

The installation will be successful and you’ll be able to call solana commands but other Solana binaries such as solana-test-validator will throw various errors since it’s expecting dependencies to be located elsewhere. If you’ve already installed it that way, no worries, simply run rm -rf ~/.local/share/solana to uninstall Solana.

I’ll be sure to update this article if/when this will work out-of-the-box for M1 computers.

In the meantime, we’ve got a little workaround to go through. We need to clone the Solana repository and compile the binary from the source code. Don’t worry, the installation process is still super simple, it just takes a bit longer due to the compilation time. Here are the steps.

# Go to your dev folder (for me it’s “~/Code”).
cd ~/Code

# Clone the Solana repository and cd into it.
git clone https://github.com/solana-labs/solana.git
cd solana

# Checkout the latest stable branch.
git checkout v1.8.2

# Run the installation script (it takes a while).
./scripts/cargo-install-all.sh .

At the end of the script, it should provide you with a line to copy/paste in your shell configuration to update your PATH accordingly. Open your ~/.zshrc file — or ~/.bashrc or ~/.profile or whatever file you use — and paste that line in there. In my case that was:

export PATH="$HOME/Code/solana/bin:$PATH"

To check that Solana is properly installed, you may run the following commands.

# Check the solana binary is available.
solana --version

# Check you can run a local validator (Run Ctrl+C to exit).
# Notice the special flag. We’ll explain that in a minute.
# Note this creates a "test-ledger" folder in your current directory.
solana-test-validator --no-bpf-jit

If you're having more troubles along the way, Note that Buildspace also has a detailed guide on how to install Solana for Apple M1 computer that they keep up-to-date.

Use Solana locally

Why? Solana defaults to using the “mainnet” network. For now, we want to develop our programs locally before we deploy them for real.

solana config set --url localhost

After running this, you should see all your configs pointing to localhost URLs which is exactly what we want.

Generate your local key pair

Why? We need a public and private key to identify ourselves when using the Solana binaries locally.

First, you might want to check if you've already got a local key pair by running the following command.

solana address

If you get an error, that means you don't have one yet and so let's create a new one.

Simply run the following command and follow the steps. Personally, I don't enter a paraphrase since the generated key pair will only be used locally.

solana-keygen new

At the end of the process, you will be given a long recovery phrase that can be used to recover both your public and private key. Even though it's only used locally, I still store that recovery phrase on my password manager just in case.

Note that you can recover any key pair by running solana-keygen recover and providing the recovery phrase in the process.

Install Anchor

Why? Anchor is a Solana framework that significantly improved the developer experience when creating programs.

You can install Anchor in your local machine by running the following command.

cargo install --git https://github.com/project-serum/anchor anchor-cli --locked

Note that you can also install Anchor using npm globally but since I use multiple versions of npm via nvm I'm not a big fan of npm global dependencies.

You may run the following command to check Anchor CLI is installed properly.

anchor --version

Install yarn

Why? By default, Anchor relies on yarn to manage JavaScript libraries.

If you don't have it installed already, you can do so by running one of the following commands:

# Using npm global dependencies.
npm install -g yarn

# Using homebrew on Mac.
brew install yarn

# Using apt on Linux
apt install yarn

Create a new Anchor project

Now that we have Anchor installed, we can run anchor init to start a new project!

# Go to your dev folder (for me it’s “~/Code”).
cd ~/Code

# Create a new Anchor project.
anchor init solana-twitter

# Cd into the newly created project.
cd solana-twitter

Inside our new project, Anchor prepared a bunch of things for us:

  • A programs folder for all our Solana programs. It already comes with a very simple program we can build upon so we don't have to do all the scaffolding.
  • A tests folder for all our JavaScript tests directly interacting with our programs. Again, it already comes with a test file for our auto-generated program.
  • An Anchor.toml configuration file helping us configure our program ID, Solana clusters, test command, etc.
  • An empty app folder that will, later on, contain our JavaScript client.

Now that we have our project scaffolded, let's see how we can build, deploy and test the default program generated by Anchor. That way, we'll understand more about the development cycle of building a Solana program.

Build and deploy

Anchor has two very useful commands that will delegate to the Rust compiler and Solana CLI tools to build and deploy your programs for you.

# Compiles your program.
anchor build

# Deploys your compiled program.
anchor deploy

Whilst these commands are not necessary to compile and deploy, they certainly make the developer experience a lot more enjoyable by abstracting all of the more complex commands we would otherwise need to run.

That being said, let's have a quick look at what happens when we run these commands.

Anchor build

First, our code is compiled and we will be shown any warnings or errors that occur at compile time. The Rust compiler is pretty powerful so if we did something wrong in our code, it most likely won't let use compile it.

Let's run this command on our brand new project.

anchor build

As you can see our program compiled but you should see the following warning: unused variable: 'ctx'. That's fair because the auto-generated program is so simple that it doesn't actually do anything with that ctx variable and, therefore, the compiler warns us it's not being used. We can safely ignore that warning for now.

Additionally, once our code was compiled, the target folder was updated accordingly. You don't need to fully understand what's happening inside that folder but it basically keeps track of any built releases and deployment of our program. Note that this folder is relative to your local machine and will not be committed to your git repository.

Finally, anchor build also generated an IDL file. IDL stands for "Interface Description Language" and it is quite simply a JSON file that contains all the specifications of our Solana program. It contains information about its instructions, the parameters required by these instructions, the accounts generated by the program, etc.

The purpose of this IDL file is to feed it to our JavaScript client later on so we can interact with our Solana program in a structured manner.

Anchor deploy

Running anchor deploy will take our latest build and deploy it on the cluster.

Note that the first time you build a program, it will also generate a public and private key for it — which will be stored in the target directory. The public key generated will become the unique identifier of your program — a.k.a the program ID.

Since we've set up our cluster to be localhost earlier, we currently have no network to deploy to. That means, if you try to run anchor deploy right now, you'll get an error saying error sending request for url (http://localhost:8899/).

To fix that, we need to run a local ledger.

Run a local ledger

A local ledger is basically a simulation of a Solana cluster inside your local machine. When building locally, we don't actually want to send anything to the Solana blockchain so this is exactly what we want.

Fortunately for us, running a local ledger is as simple as running the following command.

solana-test-validator

This command will keep a session open in your terminal until you exit it by running Ctrl+C. Whilst the session is open, you now have a local ledger to deploy to! 🎉

That means you can now run anchor deploy and it successfully deploy to your local ledger.

anchor deploy

Note that all the data sent to your local ledger is stored in a test-ledger folder created in the current directory.

So let's make sure we don't commit that entire folder to our git repository by updating our .gitignore file like so.

  .anchor
  .DS_Store
  target
  **/*.rs.bk
  node_modules
+ test-ledger

Also note that exiting your local ledger (by running Ctrl+C) will not destroy any data you've sent to the cluster. However, removing that test-ledger folder will. You can achieve the same result by adding the --reset flag.

# Runs a new empty local ledger.
solana-test-validator --reset

Run a local ledger on Apple M1

There's one little quirk here for Apple M1 users. By default, the local ledger uses something called "BPF just-in-time" which is not compatible with Apple M1 computers. Therefore, we need to add the --no-bpf-jit flag to make it work.

solana-test-validator --no-bpf-jit

Note that this issue should be resolved soon as Solana has already worked on a fix that will automatically detect if a machine supports BPF just-in-time.

Update your program ID

Now that we've run anchor build and anchor deploy for the first time, we need to update our program ID.

As we've mentioned above, a new key pair for our program is generated on the very first deployment. Before that, we simply don't know what the public address of our program will be.

Your program ID should be displayed when running anchor deploy but you may also access it by using the following Solana command.

solana address -k target/deploy/solana_twitter-keypair.json
# Outputs something like: 2EKFZUwMrNdo8YLRHn3CyZa98zp6WH7Zpg16qYGU7htD

Depending on how you named your anchor project, this file might be called something else so you may have to look at the target/deploy folder to find the right file.

Okay now that we know our program ID, let's update it.

When we created our new project using anchor init, Anchor used a random placeholder in two places as our program ID that we can now replace.

First, in our Anchor.toml configuration file.

[programs.localnet]
solana_twitter = "2EKFZUwMrNdo8YLRHn3CyZa98zp6WH7Zpg16qYGU7htD"

Then, in the lib.rs file of our Solana program. In my case, that's programs/solana-twitter/src/lib.rs.

use anchor_lang::prelude::*;
use anchor_lang::solana_program::system_program;

declare_id!("2EKFZUwMrNdo8YLRHn3CyZa98zp6WH7Zpg16qYGU7htD");

Finally, we need to build and deploy one more time to make sure our program is compiled with the right identifier.

anchor build
anchor deploy

Anchor scripts

Before we wrap up this article, I’d like to make sure we can run the generated tests on our program.

If you look inside your Anchor.toml file, you'll notice a scripts section containing a test script.

[scripts]
test = "yarn ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"

This is already configured for us so that it'll run all the tests inside our tests folder using Mocha.

To run that script, run the following command.

anchor run test

If you have a local ledger running — via solana-test-validator — and you've built and deployed your project properly — via anchor build and anchor deploy — then you should see the test passing!

Note that you can add any custom script to your Anchor.toml configuration file and use anchor run to execute it. Here's a quick example.

[scripts]
test = "..."
my-custom-script = "echo 'Hello world!'"
anchor run my-custom-script
# Outputs: Hello world!

Anchor test

Alright, we now know the full development cycle. First, you need a local ledger, then you can build, deploy and test. Here's a quick recap:

# Start the local ledger.
solana-test-validator

# Then, on a separate terminal session.
anchor build
anchor deploy
anchor run test

Well, it turns out anchor has a special command that takes care of that full cycle for us. It's called:

anchor test

⛔️ Not to confuse with anchor run test that only runs the test script inside your Anchor.toml file.

So what does anchor test actually do?

  • First, it starts a local ledger that will be automatically terminated at the end of the command. That means you cannot run anchor test if you already have a local ledger running. Make sure to terminate any local ledger before running anchor test, this is a common gotcha. Also, note that it uses the --reset flag to make sure our tests always start with the same empty data.
    solana-test-validator --reset
    
  • Now, Anchor is ready to build, deploy and run the tests.
    anchor build
    anchor deploy
    anchor run test
    

The anchor test command is really powerful when developing your Solana programs locally. It abstracts away all the faff and lets you focus on your program.

Remember though that running anchor test immediately after generating a new project — via anchor init — will not work because you'll first need to update your program ID after the first deployment.

Therefore I suggest, you build and deploy manually the very first time and once you've updated your program ID, you can start using anchor test.

Anchor localnet

If you end up working on other Anchor projects, you might come across the anchor localnet command. This command is very similar to anchor test except that it does not run any test and does not terminate the local ledger at the end.

Thus, it is basically the equivalent to:

solana-test-validator --reset
anchor build
anchor deploy

# The local ledger will stay active after deployment.

This command is typically used to quickly spin up your program when working on your frontend client.

Anchor test and localnet on Apple M1

If you're an M1 user, then I'm afraid the anchor test and anchor localnet commands will not work for you just yet.

This is because both of them are calling solana-test-validator without the --no-bpf-jit flag which is necessary for a local ledger to work on an M1 computer. That being said, when this --no-bpf-jit flag issue will be fixed, M1 users should be able to fully enjoy these two anchor commands.

In the meantime, instead of anchor test, you'll need to run:

# Start and reset your local ledger.
solana-test-validator --reset --no-bpf-jit

# Then, on a different terminal session
# Run anchor test without the local ledger.
anchor test --skip-local-validator

And instead of anchor localnet, you'll need to run:

# Start and reset your local ledger.
solana-test-validator --reset --no-bpf-jit

# Then, on a different terminal session
# Build and deploy your program.
anchor build
anchor deploy

Conclusion

Phew, we got there in the end! Congratulations on setting up your local machine with Solana and Anchor. On top of that, we now have a fully scaffolded project we can use to build our Twitter in Solana project.

I do hope you didn't encounter too many issues along the way. I know setting up things on your machine can be a real nightmare especially when the technology is moving quickly. If you have any issues feel free to add a comment to this article or better yet, create an issue on the GitHub repository below so anyone can jump in and help you across all episodes.

If you want to see the code we generated during this episode, here's a link to the episode-2 branch of this series' repository.

View Episode 2 on GitHub

Now that, we're all set up and we understand our development cycle, let's start building things! 🔥

← Previous episode
What are we building?

Discussions

Author avatar
Đorđe Zeljić
1 week ago

First of all, great post(s)!

If you have trouble running anchor deploy and getting --program-id error, there is opened issue on GH: https://github.com/project-serum/anchor/issues/1000

💖 1

Discussion

Getting started with Solana and Anchor
Author avatar
Đorđe Zeljić
1 week ago

First of all, great post(s)!

If you have trouble running anchor deploy and getting --program-id error, there is opened issue on GH: https://github.com/project-serum/anchor/issues/1000

💖 1
Author avatar
Loris Leiva
1 week ago

Thanks for sharing! 🍺

💖 0

Would you like to chime in?

You must be a member to add a reply to a discussion.

Fortunately, it only takes two click to become one. See you on the other side! 🌸

Become a Member
Author avatar
Ahmed Ali
6 days ago

About time someone starts such great content! Thank you for the amazing series! can't stress how useful it is. Even after reading and fiddling around Solana and Anchor documentation, I am still finding this series helpful and putting things together quite nicely!

💖 0

Discussion

Getting started with Solana and Anchor
Author avatar
Ahmed Ali
6 days ago

About time someone starts such great content! Thank you for the amazing series! can't stress how useful it is. Even after reading and fiddling around Solana and Anchor documentation, I am still finding this series helpful and putting things together quite nicely!

💖 0

Would you like to chime in?

You must be a member to add a reply to a discussion.

Fortunately, it only takes two click to become one. See you on the other side! 🌸

Become a Member

Would you like to chime in?

You must be a member to start a new discussion.

Fortunately, it only takes two click to become one. See you on the other side! 🌸

Become a Member