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

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

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

updatedeleteのinstructionsは、System Programを呼び出してアカウント間のSOL転送を処理するように修正する必要があります。

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

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

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

Update instructionの更新

まず、プログラムには*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

削除instructionの更新

次に、*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ファイルを更新して、instructionsに新しいボールトアカウントを含めます。これには、ボールトPDAを導出し、更新および削除instructionsの呼び出しに含める必要があります。

ボールトPDAの導出

まず、ボールトPDAの導出を追加します:

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

更新テストの変更

次に、vaultAccountを含めるように更新instructionsを更新します

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

削除テストの変更

次に、vaultAccountを含めるように削除instructionsを更新します

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

テストの再実行

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

Terminal
$
test

その後、SolanaFMのリンクを調べてトランザクションの詳細を確認できます。そこでは、更新と削除のinstructions内の送金instructionsに対するCPIを見つけることができます。

更新CPI更新CPI

削除CPI削除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?

目次

ページを編集