導入
プログラムが動くようになったら、実際にWebアプリ(dApp)から呼び出してみましょう。第7章で見たIDLが、ここでフル活用されます。
説明
TypeScriptからSolanaプログラムを呼ぶときに使う代表的なライブラリが2つあります。
@solana/web3.js… Solanaネットワークへの接続(Connection)、トランザクションの送信、アドレス(PublicKey)の扱いなど、低レベルの基本機能を提供する。@coral-xyz/anchor… IDLをもとに、あなたのプログラムを型付きのオブジェクトとして扱えるようにする、Anchor専用のクライアントライブラリ。
import * as anchor from "@coral-xyz/anchor";
import { Program } from "@coral-xyz/anchor";
import { GreetingProgram } from "../target/types/greeting_program";
import idl from "../target/idl/greeting_program.json";
// Provider: ネットワーク接続 + ウォレット をまとめたもの
const provider = anchor.AnchorProvider.env();
anchor.setProvider(provider);
// IDLから型付きのProgramオブジェクトを作る
const program = new Program<GreetingProgram>(idl as any, provider);
async function sayHello() {
const greetingAccount = anchor.web3.Keypair.generate();
await program.methods
.initialize("こんにちは、Solana!")
.accounts({
greetingAccount: greetingAccount.publicKey,
user: provider.wallet.publicKey,
systemProgram: anchor.web3.SystemProgram.programId,
})
.signers([greetingAccount])
.rpc();
const account = await program.account.greetingAccount.fetch(greetingAccount.publicKey);
console.log(account.message); // "こんにちは、Solana!"
}
program.methods.initialize(...) の引数の型・.accounts({...}) に必要なキー・返ってくる account の型は、すべてIDLから自動生成されます。Rust側の命令やアカウント構造を変えて anchor build し直せば、TypeScript側の型もそれに追従します(第7章レッスン28の内容がここで実際に使われています)。
graph LR
IDL["target/idl/*.json<br/>+ target/types/*.ts"] --> Program["new Program(idl, provider)"]
Program --> Call["program.methods.命令名(...)<br/>.accounts({...}).rpc()"]
Call --> Chain["ブロックチェーンへ<br/>トランザクション送信"]
ブラウザで動く実際のdApp(Webアプリ)では、provider.wallet の部分に、ユーザーがブラウザ拡張機能などで用意する ウォレット(Phantomなど)を接続します。ユーザーは取引ごとに、そのウォレットで署名の可否を確認・承認します――第6・7章で繰り返し出てきた「署名者チェック」は、まさにこの最後の一手を検証している仕組みです。
演習
program.methods.initialize(...) を呼んだとき、裏側でIDLがどのような役割を果たしているか、レッスン28の内容を振り返りながら自分の言葉でまとめてみましょう。
ヒント1を見る
IDLは「命令の名前・引数の型・必要なアカウントの一覧」を記述したJSONでした。
ヒント2を見る
TypeScript側はそのJSONを読み込むことで、Rustのコードを直接見なくても正しい呼び出し方を型として知ることができます。