A testing framework for Solana programs
anchor localnet
is equivalent to:
anchor build
solana-test-validator --reset
# The local ledger will stay active after deployment.
- Init a project:
$ anchor init <project-name>
(by default Typescript)Anchor used a random placeholder in two places as our program ID that we can now replace. The first is in the
./programs/<project-name>/src/lib.rs
file, and the second is in the./Anchor.toml
file. - Init a project using JS:
$ anchor init <project-name> --javascript
- Init a project with no git:
$ anchor init <project-name> --no-git
- Project directory:
app - Where our frontend code will go
programs - This is where the Rust code lives for the Solana program
test - Where the JavaScript tests for the program live
migrations - A basic deploy script
- Example:
❯ anchor build
BPF SDK: /Users/abhi3700/.local/share/solana/install/releases/1.8.5/solana-release/bin/sdk/bpf
cargo-build-bpf child: rustup toolchain list -v
cargo-build-bpf child: cargo +bpf build --target bpfel-unknown-unknown --release
Finished release [optimized] target(s) in 0.33s
cargo-build-bpf child: /Users/abhi3700/.local/share/solana/install/releases/1.8.5/solana-release/bin/sdk/bpf/dependencies/bpf-tools/llvm/bin/llvm-readelf --dyn-symbols /Users/abhi3700/F/coding/github_repos/crunchy-vs-smooth/target/deploy/crunchy_vs_smooth.so
To deploy this program:
$ solana program deploy /Users/abhi3700/F/coding/github_repos/crunchy-vs-smooth/target/deploy/crunchy_vs_smooth.so
The program address will default to this keypair (override with --program-id):
/Users/abhi3700/F/coding/github_repos/crunchy-vs-smooth/target/deploy/crunchy_vs_smooth-keypair.json
anchor build
is combination of:
$ cargo build-bpf
$ anchor idl parse -f program/src/lib.rs -o target/idl/basic_0.json
- After this,
target/
folder gets generated.- IDL is found at
target/idl/<project-name>.json
, which is similar to ABI in solidity and will be using them in a similar way in our JavaScript tests and frontends to communicate with our Solana program via RPC. program-id
also gets generated. View via- M-1 Using (solana-cli):
$ solana address -k target/deploy/crunchy_vs_smooth-keypair.json
- M-2 Using (solana-keygen):
$ solana-keygen pubkey target/deploy/crunchy_vs_smooth-keypair.json
- M-3 Using (anchor-cli):
anchor keys list
- M-1 Using (solana-cli):
- Replace the
program-id
in 2 places:
declare_id!("EGzbH5pZmHhm26PBtEYA57WsLUkGA2vqn8vhsREenfNS");
[programs.localnet]
crunchy_vs_smooth = "EGzbH5pZmHhm26PBtEYA57WsLUkGA2vqn8vhsREenfNS"
[programs.devnet]
crunchy_vs_smooth = "EGzbH5pZmHhm26PBtEYA57WsLUkGA2vqn8vhsREenfNS"
-
2 ways to add details of network, deployer's wallet during deployment:
cluster
param's value in theAnchor.toml
file of the repo.- M-1:
$ anchor deploy
as CLI command. The provider's info inAnchor.toml
file:
[provider] cluster = "devnet" wallet = "~/.config/solana/id.json"
- M-2:
$ anchor deploy --provider.cluster devnet --provider.wallet ~/.config/solana/id.json
- M-1:
// it's redundant to use the above provider info in `Anchor.toml` file
If the wallet address' directory is in different place that the default, then parse that which contains faucet.
Before deployment, make sure that the new program ID generated during
build
is added in theAnchor.toml
&lib.rs
files like this:
Anchor.toml
[programs.localnet]
solana_twitter = "Gy1q1wi3V1Xiji2PgoYSEcu4pcqjy7D8vr9HJhfAQpnt"
lib.rs
declare_id!("Gy1q1wi3V1Xiji2PgoYSEcu4pcqjy7D8vr9HJhfAQpnt");
- To devnet: Get the output file location from
$ anchor build
# M-1.1: using solana
# This works, if in `~/.config/solana/cli/config.yml` directory, it is connected to the same network as we want to deploy on. Otherwise, use M-1.2
❯ solana program deploy target/deploy/crunchy_vs_smooth.so
OR
# M-1.2: using solana with customization
# This is used when deploying with a specific address (having some SOL already).
# Then, need to provide the file directory containing private key.
# Very useful when deploying on mainnet using an account which already owns valuable SOL tokens (for transaction fees).
❯ solana program -k <~/solanawallet.json> deploy target/deploy/crunchy_vs_smooth.so -u https://api.devnet.solana.com
# Output
Program Id: G36EspggVjxkDEKfHGXjsrHjt2sLPJa2hhomSNijzuTx
# M-2: using anchor
❯ anchor deploy --provider.cluster devnet ⏎
Deploying workspace: https://api.devnet.solana.com
Upgrade authority: /Users/abhi3700/.config/solana/id.json
Deploying program "crunchy-vs-smooth"...
Program path: /Users/abhi3700/F/coding/github_repos/sol_contracts_crunchyvssmooth/target/deploy/crunchy_vs_smooth.so...
Program Id: G36EspggVjxkDEKfHGXjsrHjt2sLPJa2hhomSNijzuTx
Deploy success
NOTE:
$ anchor deploy
is for localnet. Here, in another terminal tab, start the node viasolana-test-validator
NOTE: the wallet account must have token balance for deployment. If not created
# M-1: using solana
❯ solana program deploy target/deploy/crunchy_vs_smooth.so --program-id G36EspggVjxkDEKfHGXjsrHjt2sLPJa2hhomSNijzuTx
Program Id: G36EspggVjxkDEKfHGXjsrHjt2sLPJa2hhomSNijzuTx
# M-2: using anchor
❯ anchor upgrade target/deploy/counter.so --provider.cluster devnet --program-id G36EspggVjxkDEKfHGXjsrHjt2sLPJa2hhomSNijzuTx ⏎
Program Id: G36EspggVjxkDEKfHGXjsrHjt2sLPJa2hhomSNijzuTx
- Solana program architecture uses
Entrypoint
,State
,Processor
,Instruction
,Lib
andError
files. So, these are taken care ofAnchor
. - Anchor has modules, modules are basically a way of grouping structs, functions, methods etc in a large program to make it more easier to export and reuse.
serialization
&deserialization
: translate data structure or objects into a format(bytes) that can be stored or transmitted. In other words, serialize/deserialize is to pack/unpack data. E.g. In a Redis DB, in order to store an image, it is encoded & in order to retrieve the image, it is decoded.
Here, in Solana programs, mostly
accounts
,structs
are serialized or deserialized.
// extract stored data from an account
let mut data = account.try_borrow_mut_data();
// unpack the data
let mut unpacked = Message::unpack(&data).expect("Failed to read data");
// modify a param `txt` of unpacked data to `txtFinal` of str type.
unpacked.txt = txtFinal
// Then, pack the data
unpacked.pack(&mut data);
The entire snippet can be seen here.
- 2 imports to start with:
prelude
,state
. - In anchor, there are no separate files for programs
entrypoint
,state
,processor
,instructions
etc. - the
#[program]
attribute initialises the instructions to be passed and should be enclosed in a module (mod{}
).
#[program]
pub mod hello {
}
Amount of space allocated to each type of struct defined in an account.