Solana の開発環境の紹介
こんにちは、ソフトゲートと申します。
しばらくお休みしておりましたが、最近 Solana での開発に復帰しました。
ご縁があり、Radar ハッカソンの Gaming Track で 3 位を受賞した Windfall で主にコントラクト開発を担当しております。
さて、今回は「Solana の開発環境の紹介」というテーマで、
- Solana CLI および Anchor のインストール手順の説明
- 最近 Solana で使われている(今後使われそうな)開発ツールの紹介
をお届けしたいと思います。
Solana の近況
現在は Solana 自体や TypeScript ライブラリがバージョン 1 から 2 に切り替わりつつある過渡期であるため、古い情報をそのまま鵜呑みにすると、コマンドの実行でエラーが起きたりするケースが散見されます。
バリデータや CLI の基本的な使い方に違いはありませんが、いくつかのオプションや RPC エンドポイントが廃止されており、特に TypeScript で書かれた過去のコード例を参考にする場合に注意が必要です。
TypeScript ライブラリ @solana/web3.js
については後述するとして、バリデータのオプションや RPC エンドポイントの変更点については、以下の資料をご覧ください。最後の QuickNode の記事には、廃止された confirmTransaction
相当の関数を新しい API で実装する例が紹介されています。
それでは、Solana CLI および Anchor のインストール手順を詳しく説明していきます。
Solana CLI
なにはともあれ Solana での開発をする際に必要となってくるのが Solana CLI です。
基本的には以下のページに沿って進めていけば大丈夫...のはずなのですが、いくつか躓きポイントがありますので、随時補足しながら、順番に見ていきましょう。
利用環境
まず、環境ですが、とにかくトラブルを避けてすんなりインストールするなら、クラウドの Ubuntu LTS (バージョンは 22 でも 24 でも構いませんが Intel/AMD x64 ベースのもの) が無難です。
ご自分の PC にインストールする場合は、個人的なお勧めは
- Intel/AMD 系 CPU を搭載した Windows なら
docker
や Ubuntu VM 上にインストール - Apple Silicon 搭載 Mac なら、そのままインストール
Windows なら WSL という選択肢もありますが、WSL から Windows 側のファイルシステムにアクセスするとエラーが起きるなど、うっかりミスの箇所が増えるので、自力で解決する自信がない人は素直に docker
あるいは何らかの仮想マシン Ubuntu を用意してしまう方が楽かもしれません。
また、Apple Silicon (M1-M4) を搭載した Mac の場合は、docker
を使うと、
- アーキテクチャを指定しないとインストール時に適切なパッケージが見つからない
- x64 を指定するとバリデータ起動時に AVX 命令が見つからずにエラー
など、ところどころでハマるので、私は直で Mac にインストールしました。
Rust と Solana CLI のインストール
それでは、インストールに取り掛かりましょう。Ubuntu (Windows の VM や WSL 含む) の場合は、前提条件のインストールからです。これらは Anchor をインストールする際に必要となります。フレッシュインストールの Ubuntu であれば、apt
でパッケージの更新もしておくとよいでしょう。Mac の人はスキップしてください。
> sudo apt update && sudo apt upgrade -y
> sudo apt-get install -y \
build-essential \
pkg-config \
libudev-dev llvm libclang-dev \
protobuf-compiler libssl-dev
次に Rust をインストールします。Mac の人はここから合流です。
> curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
上記のコマンドを実行してインストールが完了したら、いったん再ログインするなどしてシェルを再起動するか、. "$HOME/.cargo/env"
を実行して Rust のツールにパスを通します。この時点で rustc
がインストールされているはずですので、バージョンを確認しておきます。
> rustc --version
rustc 1.83.0 (90b35a623 2024-11-26)
そして、Anza がリリースしている Solana CLI の最新安定版を入れましょう。
2024 年 12 月 3 日現在は 2.0.17 がインストールされます。
> sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)"
インストールには少々時間がかかりますが、最後に次のようなメッセージが表示されると思います。
Close and reopen your terminal to apply the PATH changes or run the following in your existing shell:
export PATH="/Users/test/.local/share/solana/install/active_release/bin:$PATH"
これが表示されたら、再ログインしてシェルを再起動するか、ここに記載されたコマンドをシェルで実行してパスを通しましょう。
> export PATH="/Users/your_name/.local/share/solana/install/active_release/bin:$PATH"
Mac の場合は、~/.zprofile
の末尾に設定が追加されています(もしかしたら自分で追加したのかも?すいません、覚えていません)。
よくわからない方は、いったんログアウトして入り直せば、パスが通った状態になっていると思います。バージョンを確認してみましょう。
> solana --version
solana-cli 2.0.17 (src:7104d713; feat:607245837, client:Agave)
ここまではすんなりインストールできると思います。できましたよね?
Anchor
次に、Solana プログラムのデファクトスタンダードな開発フレームワークである Anchor をインストールしていきます。
...が、その前に、各種開発ツールのランタイムのバージョンを管理するツールを入れておくのがお勧めです。Node.js とか Python のバージョンをディレクトリごとに簡単に切り替えるようなアレです。
オープンソースで提供されている Solana の他のプロジェクトをビルドしてみようと思った時に、前提条件となるツールのバージョンを合わせないと、バージョンの不整合でビルドが失敗することが少なくありません。Solana も Anchor も Rust もそれぞれ開発が進んでいるので、バージョンの違いで起きる問題って、案外多いんですよね。
開発者の方であれば、すでに馴染みのランタイム管理ツールがあるかもしれませんので、お好きなものを使ってください。ここでは私が利用している mise
を紹介しておきます。
mise インストール
ランタイム管理ツール asdf との互換性を保ちつつ(つまり asdf プラグイン資源がそのまま使える)、Rust で実装して高速化や利便性の向上を図ったものが mise です(発音は meez だそうです)。以前は rtx と呼ばれていました。
ランタイム管理以外に、direnv
のような環境変数管理機能と、ビルドやテストなどのタスク実行機能も備えています。
Ubuntu でも Mac でも、以下のコマンドでインストール可能です:
> curl https://mise.run | sh
Ubuntu でインストールした時は、このような実行結果になりました:
> curl https://mise.run | sh
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 6333 100 6333 0 0 61517 0 --:--:-- --:--:-- --:--:-- 61485
mise: installing mise...
######################################################################## 100.0%
mise: installed successfully to /home/ubuntu/.local/bin/mise
mise: run the following to activate mise in your shell:
echo "eval \"\$(/home/ubuntu/.local/bin/mise activate bash)\"" >> ~/.bashrc
mise: this must be run in order to use mise in the terminal
mise: run `mise doctor` to verify this is setup correctly
指示に従って、コマンドを実行し、~/.bashrc
に一行追加しておきます(Mac の場合はどうだったのか失念しました、すいません!):
> echo "eval \"\$(/home/ubuntu/.local/bin/mise activate bash)\"" >> ~/.bashrc
シェルを再起動またはログインし直してから、mise doctor
というコマンドを実行してみてください。
いろいろな情報が表示された後に、No problems found
というメッセージが出力されればインストールは成功しています。
では、早速、Anchor でプロジェクトを作成する時に必要になるので、yarn
と Node.js をインストールしておきましょう。
> mise install node@lts yarn@4
> mise global node@lts yarn@4
上記のコマンドで、Node.js の LTS(現在は 22)の最新バージョンと yarn
4.x の最新バージョンがインストールされ、これらのツールがグローバルで有効になります。mise
ではこのように曖昧にバージョンを指定しても、適切なマイナーバージョンを自動的に選択してくれたり、インストールするツールバージョンを複数指定できるなど、asdf
よりも使い勝手が良くなっています。
> yarn --version
4.5.3
> node --version
v22.11.0
ところで、「こんなツールを入れるのだったら、Rust より先にインストールして、Rust のバージョンも管理すればよかったのに...」と思われるかもしれません。実際 mise
にも Rust プラグインは用意されていますが、mise
の作者は、特別な理由がない限り、Rust に関しては mise
ではなく rustup
の標準機能でバージョンを管理すればいいというスタンスのようです。
たとえば、「このディレクトリでは Rust の 1.79.0 を使いたい」というようなケースであれば、
> rustup override set 1.79.0
というコマンドを実行することで、ローカルの Rust バージョンを固定できます。
Anchor インストール
お待たせしました、ようやく Anchor のインストールです。avm
という Anchor のバージョン管理ツールからインストールしましょう。
> cargo install --git https://github.com/coral-xyz/anchor avm --force
ビルドにはまあまあ時間がかかりますが、このコマンドは問題なく実行されるかと思います。
avm
がインストールされたので、Anchor 本体の各バージョンをインストールします。現時点での最新版は 0.30.1 です。とりあえず最新版だけインストールするのであれば、avm use latest
を実行すると、「最新版をインストールするかい?」と聞かれるので Y と答えましょう。
> avm use latest
Version 0.30.1 is not installed. Would you like to install? [y/n]
このコマンドが正常終了すれば、Anchor 0.30.1 のインストールおよびバージョン選択は完了です。
これ以降、Anchor の異なるバージョンを使いたい時には、avm
で随時切り替えることができます。
- バージョン一覧確認 -
avm list
- 特定バージョンインストール -
avm install 0.29.0
,avm install latest
など - 特定バージョンアンインストール -
avm uninstall 0.29.0
など - バージョン切り替え -
avm use 0.29.0
,avm use latest
など -
avm
自体の更新 -avm update
...でも、まだ終わりじゃありません。ビルドとテストの実行を確認します。
ビルドの確認
Anchor でプロジェクトを新規作成し、そのプロジェクトのビルドと TypeScript テストが問題なく実行できることを確認しておきましょう。
プロジェクトの新規作成は anchor init プロジェクト名
です。
> anchor init hoge
プロジェクトの作成は問題ないかと思いますので、続けて、これをビルドしてみます。
> cd hoge
> anchor build
error: failed to parse lock file at: /home/ubuntu/hoge/Cargo.lock
Caused by:
lock file version 4 requires `-Znext-lockfile-bump`
はい、でました、よくわからないハマりポイントその1。
結論から言うと、Cargo.lock
の version = 4
という行を version = 3
に書き換えれば対処可能です。この問題は近々リリースされる予定の Anchor 0.31 では直っているはずです。
ということで、vi
でも nano
でも何でもいいので、適当なテキストエディタで Cargo.lock
を編集して、3行目を version = 3
に直してください。
では、再度ビルドを試みてみます。
> anchor build
しばらく順調にビルドが進みますが、最後の最後で警告が大量に表示されるかもしれません。
warning: unexpected `cfg` condition value: `custom-heap`
--> programs/hoge/src/lib.rs:5:1
|
5 | #[program]
| ^^^^^^^^^^
|
= note: expected values for `feature` are: `cpi`, `default`, `idl-build`, `no-entrypoint`, `no-idl`, and `no-log-ix-name`
= help: consider adding `custom-heap` as a feature in `Cargo.toml`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
= note: `#[warn(unexpected_cfgs)]` on by default
= note: this warning originates in the macro `$crate::custom_heap_default` which comes from the expansion of the attribute macro `program` (in Nightly builds, run with -Z macro-backtrace for more info)
これは Rust nightly のバージョンによって起きる問題とのことで、nightly のバージョンを現時点では 11 月 29 日のものにすれば表示されなくなります。
具体的にはビルドする際に
> RUSTUP_TOOLCHAIN="nightly-2024-11-19" anchor build
のように環境変数を指定するか、さきほど mise
をインストールした方はその機能を活用して、hoge
ディレクトリで次のコマンドを実行して環境変数をオーバーライドすることもできます:
> mise set RUSTUP_TOOLCHAIN=nightly-2024-11-19
この状態で anchor build
を実行すれば、ビルドは正常終了するはずです。
テストの確認
ビルドが完了したら、そのままデフォルトの TypeScript テストも実行しましょう。
> anchor test
Finished release [optimized] target(s) in 0.22s
Finished `test` profile [unoptimized + debuginfo] target(s) in 0.24s
Running unittests src/lib.rs (/home/ubuntu/hoge/target/debug/deps/hoge-1828cdac5c6a3c3f)
Found a 'test' script in the Anchor.toml. Running it as a test suite!
Running test suite: "/home/ubuntu/hoge/Anchor.toml"
(node:26841) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
hoge
Your transaction signature 2GHniV3J6zUXZsptf4VU4Qer7YK1HYmrFaAWF1Vx3EHJNxpECbdsbbp6WVLs37wa2FGsNQBLPArFfbA3huVYtK5w
✔ Is initialized! (481ms)
1 passing (485ms)
一応実行はできているようですが、途中に警告が表示されているのが気に入らない人もいるかもしれません。これは Node.js のバージョンが 22.x の場合に表示されるものなので、このディレクトリでは Node.js 20.x を利用するようにすれば警告を消すことができます。
再び mise
を使って、このディレクトリでは Node.js 20.x を使うようにローカル指定しましょう。
> mise install node@20
> mise local node@20
これで警告は消えるはずですから、確認してみます。
> anchor test
Finished release [optimized] target(s) in 0.20s
Finished `test` profile [unoptimized + debuginfo] target(s) in 0.17s
Running unittests src/lib.rs (/home/ubuntu/hoge/target/debug/deps/hoge-1828cdac5c6a3c3f)
Found a 'test' script in the Anchor.toml. Running it as a test suite!
Running test suite: "/home/ubuntu/hoge/Anchor.toml"
hoge
Your transaction signature yFqAEEBe4dfTWb3UQ3bMNt2veSjt24fEfEq2jRESNMAvmREQtqKaJtCYqgPnnshHgFhM3zN26SXgFPri4EGtiTW
✔ Is initialized! (195ms)
1 passing (200ms)
問題ないようですね。
以上が Solana CLI と Anchor のインストール手順となります! お疲れ様でした!
ツール紹介
これ以降は、おまけ的に、現在 Solana 開発で使われているライブラリとツール類についてまとめたものになります。
時間の経過とともに状況は変化していきますが、2024 年 12 月現在で一般的に使われているものを取り上げるようにしました。
開発言語
基本的に、現在の Solana 界隈では
- Solana プログラム開発は Rust (多くは Anchor 利用)
- フロントエンドや BOT またはテストなどコントラクトを呼び出す側は TypeScript
というチョイスが一般的です。
一部、高速化や時間送りをしたいがために Rust でテストを記述したり、CLI のようなツールを Rust で書くことはありますが、それ以外の選択肢に至ってはぶっちゃけ茨の道なので自己責任で頑張ってください。
TypeScript ライブラリ
@solana/web3.js
フロントエンドや BOT の開発で広く使われている Solana の TypeScript ライブラリです。
最近、npm
でバージョン 2.x がインストールされるようになったので、バージョン 1.x を使いたい場合には npm i @solana/web3.js@1
のようにして、バージョン 1.x を明示的に指定します。
2.x のメリットや使い方については、こちらを参照してください:
見ていただくとわかりますが、2.x は 1.x とは全然別物です。
いまネットで見かけるサンプルはほとんどがバージョン 1.x のものですし、多くのプロジェクトが 1.x に依存しているので、現時点では特別な理由がない限りは 1.x を使うことになるでしょう。
もちろん、他プロジェクトへの依存がほぼない新規プロジェクトでは、2.x の採用を一考する価値はあると思います。
Umi
Umi は、Solana プログラムの JavaScript クライアントを扱うための Metaplex Foundation が提供する TypeScript / JavaScript ライブラリです。
他のパッケージへの依存性を極力排除して、これ単体で使えるように作られています。
フロントエンドを開発していると、Solana 関連のパッケージがやたらと増えてきて、そいつらのバージョンの衝突が起きるなど、頭痛の種になりがちです。
この問題への対策の一環として、Umi やさきほどの @solana/web3.js
2.x への移行を少しずつ進めていけると望ましいと思います。
ただし、実際に Solana プログラムとやりとり(インストラクションの呼び出しやアカウントのデシリアライズ)をするには、Umi 向けの JavaScript クライアントが別途必要になるので、後ほど紹介する Codama を使ってクライアントを生成してください。
開発フレームワーク
Anchor
言わずと知れた Rust での Solana 開発の標準的なフレームワークです。
最近でこそ情報が多くなり、開発がしやすくなってきましたが、膨大な Rust マクロの後ろに実装が隠蔽されていて、ちょっと変わったことをやろうとするとハマる可能性もあります。
慣れてきたら Anchor マクロの意味をちゃんと理解して、背後でどんなコードが生成されているかを知っておくとよいでしょう。
日本語ではユウキさんの以下の記事が参考になります:
Anchor のマクロ処理後の生成コードを確認したい方は、anchor expand
を使ってください。
まずは一度 cargo-expand
をインストールします。
> cargo install cargo-expand
その後、Anchor のプロジェクトディレクトリで anchor expand
を実行します。
> anchor expand
すると、.anchor/expanded-macros/プロジェクト名
というディレクトリの下に、マクロ展開後の生成コードが出力されているはずです。
Poseidon
Turbin3 の人たちが開発しているトランスパイラーで、TypeScript コードから Rust (Anchor) コードを生成します。
まだ実際のプロジェクトでの採用実績はないと思いますが、技術的に大変興味をそそられるツールです。
Steel
Ore の開発に伴って作られたフレームワークで、10 月 24 日にバージョン 2 が公開されました。
私は全然詳しくないのですが、すごく雑に言うと、Anchor みたいなものです(多分)。興味はあるものの、まだ深掘りはしておりません。
クライアント生成
Anchor では、プロジェクトをビルドすると idl/プロジェクト名.json
という名前の JSON ファイルを生成してくれますが、これは IDL と呼ばれるデータで、Solana プログラムのインストラクションやデータの型定義が含まれています。
このように、IDL を生成する機能が Anchor には備わっているわけですが、他にも shank というツールがあり、あえて shank で IDL を生成しているプロジェクトもあります (Jito など)。
また、この IDL の情報をもとにして、各種言語から利用しやすいクライアントライブラリを生成するツールがあります。
その一例が Anchor 本体と同じバージョン番号で更新されている @coral-xyz/anchor
という TypeScript ライブラリです。 @coral-xyz/anchor
は IDL ファイルおよび型定義ファイルから @solana/web3.js
1.x 系で使いやすいクライアントを動的に生成してくれます。
他にも、歴史的には、IDL から TypeScript クライアントを生成する Solita や、Rust クライアントを生成する Solores, anchor-gen、あるいは Python クライアントを生成する client-gen のような仕組みが存在します。
正直なところ、これらはほとんど過去の遺物となっており、現在も利用されているのは Anchor 以外には、IDL 生成目的で shank がたまに使われている程度かと思います。
Codama
これら廃れつつあるクライアント生成ツールに取って代わって、現時点では Codama が最有力候補になりつつあるようです。これは Metaplex Foundation が開発したもので、以前は Kinobi という名前でした。
Codama は Anchor または shank の IDL ファイルを入力として受け取り、現時点では以下のようなクライアントを生成することができます:
-
@solana/web3.js
2.x - Umi
- Rust
これらに、Anchor がデフォルトで対応している @solana/web3.js
1.x を加えれば、現在広く要求される種類のクライアント生成は概ね網羅されることになります。
テスト
Solana Bankrun
Anchor プログラムのテストは、多くの場合 TypeScript で記述すると思いますが、このテスト手法の限界の一つが、バリデータの時間を進めることができない点にあります。
たとえば、NFT の販売期間を設定しておいて、その期間外ならミントが失敗するようなプログラムを作った場合、自動テスト時には販売期間のパラメータを長くてもせいぜい数十秒とかに設定して、テストコードに適宜ウエイトを入れて時間を調整しながら、期間外と期間内の動作確認をするわけですね。
これに対して、solana-program-test を使った Rust テストであれば、バリデータ(正確に言うとフルのバリデータが動いているわけではありません)の時刻を自由に変更できます。
同様のことを TypeScript で可能にしてくれるのが Solana Bankrun です。
Bankrun は solana-program-test と同じ仕組みでテストを実行するので、テストバリデータは起動しません。
したがって、原則として RPC サーバへの問い合わせはできないのですが、Anchor との連携機能によって、アカウント情報など一部の情報は通常の Anchor TypeScript テストと同様の方法で取得できるようになっています。
また、テストバリデータを利用したテストに比べると、とても高速に実行されます。
Trident
Solana のテストを Rust で書ける方には、Solana プログラムの Fuzz テストを(ある程度まで)自動生成できる Trident も紹介しておきます。
なお、Trident を開発している Ackee Blockchain Security は、School of Solana や Solana Auditors Bootcamp といった教育プログラムを無料で提供しています。内容は英語になりますが、動画を見ながら自分のペースで学習を進めることができます。ただし、Github で課題が出されるので、期間内に課題をクリアしないと卒業はできません。一定の基準を満たして卒業すると認定 NFT がもらえるようです。
教育プログラム
Turbin3
教育プログラムの話が出たので、Turbin3 も紹介しておきます。
一般的な Solana 開発者向けのプログラムから、さらに上級向けのコースまで用意されています。
私は参加したことがありませんが、おそらくオンラインミーティング形式で進んでいくと思うので、(タイムゾーンの違いもあるし)そこそこ気合を入れて時間を確保する必要がありそうです。
前述の Poseidon をはじめ、意欲的なプロジェクトがここから派生したり、あるいはここの卒業生がハッカソン参加プロジェクトの開発を担当したりしています。
Discussion