クロスプログラム呼び出し

このセクションでは、前のPDAセクションのCRUDプログラムが、Solanaプログラムが互いに呼び出すことを可能にする機能であるクロスプログラム呼び出し(CPI)を追加することで更新されます。

このチュートリアルでは、プログラムがクロスプログラム呼び出しを行う際にプログラム派生アドレス(PDA)に対して「署名」する方法も示しています。

updatedelete命令は、System Programを呼び出すことによってアカウント間のSOL転送を処理するために修正が必要です。

このセクションの目的には、Anchorフレームワークを使用してSolanaプログラムでCPIを実装するプロセスを説明し、前のセクションで探求したPDAの概念を基に構築することが含まれます。詳細については、クロスプログラム呼び出しページを参照してください。

参考として、このリンクにはPDAとCPIの両方のセクションを完了した後の最終コードが含まれています。

このセクションのスターターコードには、PDAセクションのみが完了しています。

更新命令の更新

まず、プログラムは*rsUpdate*構造体とupdate関数を変更することで、シンプルな「更新のための支払い」メカニズムを必要とします。

system_programモジュールからアイテムをスコープに取り込むために、lib.rsファイルの更新から始めます。

lib.rs
use anchor_lang::system_program::{transfer, Transfer};

次に、*rsUpdate*構造体を更新して、vault_accountという新しいアカウントを含めます。このアカウントはプログラムによって制御され、ユーザーがメッセージアカウントを更新する際にユーザーからSOLを受け取ります。

lib.rs
#[account(
mut,
seeds = [b"vault", user.key().as_ref()],
bump,
)]
pub vault_account: SystemAccount<'info>,

次に、update命令にCPIロジックを追加して、ユーザーのアカウントからボールトアカウントに0.001 SOLを転送します。

lib.rs
let transfer_accounts = Transfer {
from: ctx.accounts.user.to_account_info(),
to: ctx.accounts.vault_account.to_account_info(),
};
let cpi_context = CpiContext::new(
ctx.accounts.system_program.to_account_info(),
transfer_accounts,
);
transfer(cpi_context, 1_000_000)?;

プログラムを再ビルドします。

Terminal
$
build

削除命令の更新

*rsDelete*構造体とdelete関数を変更して、「削除時の返金」メカニズムを追加します。

まず、*rsDelete*構造体を更新してvault_accountを含めます。これにより、ユーザーがメッセージアカウントを閉じるときにボールト内のSOLをユーザーに返金することができます。

lib.rs
#[account(
mut,
seeds = [b"vault", user.key().as_ref()],
bump,
)]
pub vault_account: SystemAccount<'info>,

また、転送のCPIにはSystem Programの呼び出しが必要なため、system_programも追加します。

lib.rs
pub system_program: Program<'info, System>,

次に、delete命令にCPIロジックを追加して、ボールトアカウントからユーザーのアカウントにSOLを転送します。

lib.rs
let user_key = ctx.accounts.user.key();
let signer_seeds: &[&[&[u8]]] =
&[&[b"vault", user_key.as_ref(), &[ctx.bumps.vault_account]]];
let transfer_accounts = Transfer {
from: ctx.accounts.vault_account.to_account_info(),
to: ctx.accounts.user.to_account_info(),
};
let cpi_context = CpiContext::new(
ctx.accounts.system_program.to_account_info(),
transfer_accounts,
).with_signer(signer_seeds);
transfer(cpi_context, ctx.accounts.vault_account.lamports())?;

*rs_ctx: Context<Delete>rsctx: Context<Delete>*に変更され、関数本体でコンテキストを使用することに注意してください。

プログラムを再ビルドします。

Terminal
$
build

プログラムの再デプロイ

これらの変更を行った後、更新されたプログラムを再デプロイします。これにより、変更されたプログラムがテスト可能になります。Solanaでは、プログラムの更新は単に同じプログラムIDでプログラムをデプロイするだけです。

PlaygroundウォレットにdevnetのSOLがあることを確認してください。Solana Faucetからdevnet SOLを取得できます。

Terminal
$
deploy

テストファイルの更新

次に、anchor.test.ts ファイルを更新して、命令に新しいボールトアカウントを含めます。これには、ボールトPDAを導出し、更新および削除命令の呼び出しに含める必要があります。

Vault PDAの導出

まず、vault PDAの導出を追加します:

anchor.test.ts
const [vaultPda, vaultBump] = PublicKey.findProgramAddressSync(
[Buffer.from("vault"), wallet.publicKey.toBuffer()],
program.programId
);

Updateテストの変更

次に、vaultAccountを含めるようにupdate命令を更新します

anchor.test.ts
const transactionSignature = await program.methods
.update(message)
.accounts({
messageAccount: messagePda,
vaultAccount: vaultPda
})
.rpc({ commitment: "confirmed" });

Deleteテストの変更

次に、vaultAccountを含めるようにdelete命令を更新します

anchor.test.ts
const transactionSignature = await program.methods
.delete()
.accounts({
messageAccount: messagePda,
vaultAccount: vaultPda
})
.rpc({ commitment: "confirmed" });

テストの再実行

これらの変更を行った後、テストを実行して、すべてが期待通りに動作することを確認します:

Terminal
$
test

その後、SolanaFMのリンクを調べてトランザクションの詳細を確認できます。そこでは、update命令とdelete命令内のtransfer命令に対するCPIを見つけることができます。

Update CPIUpdate CPI

Delete CPIDelete CPI

エラーが発生した場合は、最終コードを参照してください。

次のステップ

Solanaクイックスタートガイドを完了おめでとうございます。以下のSolanaの重要な概念について実践的な経験を得ることができました:

  • アカウントからのデータの取得と読み取り
  • トランザクションの構築と送信
  • Solanaプログラムのデプロイと更新
  • Program Derived Addresses (PDAs)の操作
  • Cross-Program Invocations (CPIs)の実行

これらの概念についての理解を深めるには、コア概念のドキュメントをチェックしてください。このガイドで取り上げたトピックについて詳細な説明が提供されています。

さらなる例を探索する

例から学ぶことを好む場合は、プログラム例リポジトリをチェックして、様々なサンプルプログラムを確認してください。

Solana Playgroundには、GitHubリンクを使用してプロジェクトをインポートまたは表示できる便利な機能があります。例えば、このSolana Playgroundリンクを開くと、このGithubリポジトリからAnchorプロジェクトを表示できます。

Importボタンをクリックし、プロジェクト名を入力して、Solana Playgroundのプロジェクトリストに追加します。プロジェクトがインポートされると、すべての変更は自動的に保存され、永続化されます。

Is this page helpful?

目次

ページを編集