Cross Program Invocation

Trong phần này, chương trình CRUD từ phần PDA trước đó được cập nhật bằng cách thêm Cross Program Invocations (CPIs), một tính năng cho phép các program Solana có thể gọi lẫn nhau.

Hướng dẫn này cũng chỉ ra cách các program có thể "ký" cho Program Derived Addresses (PDAs) khi thực hiện Cross Program Invocations.

Các lệnh updatedelete cần được sửa đổi để xử lý việc chuyển SOL giữa các tài khoản bằng cách gọi System Program.

Mục đích của phần này bao gồm việc hướng dẫn quy trình triển khai CPIs trong một program Solana sử dụng framework Anchor, xây dựng dựa trên các khái niệm PDA đã khám phá trong phần trước. Để biết thêm chi tiết, hãy tham khảo trang Cross Program Invocation.

Để tham khảo, liên kết này bao gồm mã cuối cùng sau khi hoàn thành cả hai phần PDA và CPI.

Mã khởi đầu cho phần này chỉ bao gồm phần PDA đã hoàn thành.

Cập nhật lệnh Update

Đầu tiên, chương trình cần một cơ chế "trả tiền để cập nhật" đơn giản bằng cách thay đổi cấu trúc Update và hàm update.

Bắt đầu bằng việc cập nhật tệp lib.rs để đưa vào phạm vi các mục từ module system_program.

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

Tiếp theo, cập nhật cấu trúc Update để bao gồm một tài khoản mới gọi là vault_account. Tài khoản này, được kiểm soát bởi program, nhận SOL từ người dùng khi họ cập nhật tài khoản tin nhắn của mình.

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

Tiếp theo, thêm logic CPI trong lệnh update để chuyển 0.001 SOL từ tài khoản của người dùng đến tài khoản kho.

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)?;

Xây dựng lại chương trình.

Terminal
$
build

Cập nhật lệnh xóa

Bây giờ hãy thêm cơ chế "hoàn tiền khi xóa" bằng cách thay đổi cấu trúc Delete và hàm delete.

Đầu tiên, cập nhật cấu trúc Delete để bao gồm vault_account. Điều này cho phép chuyển bất kỳ SOL nào trong vault trở lại cho người dùng khi họ đóng tài khoản tin nhắn của họ.

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

Đồng thời thêm system_program vì CPI cho việc chuyển tiền yêu cầu gọi System Program.

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

Tiếp theo, thêm logic CPI trong lệnh delete để chuyển SOL từ tài khoản vault trở lại tài khoản của người dùng.

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())?;

Lưu ý rằng _ctx: Context<Delete> thay đổi thành ctx: Context<Delete> để sử dụng context trong phần thân của hàm.

Xây dựng lại chương trình.

Terminal
$
build

Triển khai lại chương trình

Sau khi thực hiện những thay đổi này, hãy triển khai lại chương trình đã cập nhật. Điều này đảm bảo chương trình đã sửa đổi sẽ khả dụng để kiểm tra. Trên Solana, việc cập nhật chương trình chỉ đơn giản là triển khai chương trình với cùng một program ID.

Đảm bảo ví Playground của bạn có devnet SOL. Nhận devnet SOL từ Solana Faucet.

Terminal
$
deploy

Cập nhật tệp kiểm tra

Tiếp theo, cập nhật tệp anchor.test.ts để bao gồm tài khoản vault mới trong các lệnh. Điều này yêu cầu phải tạo vault PDA và bao gồm nó trong các lệnh gọi cập nhật và xóa.

Tạo Vault PDA

Đầu tiên, thêm phần tạo vault PDA:

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

Thay đổi Update Test

Sau đó, cập nhật hướng dẫn update để bao gồm vaultAccount

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

Thay đổi Delete Test

Sau đó, cập nhật hướng dẫn delete để bao gồm vaultAccount

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

Chạy lại Test

Sau khi thực hiện những thay đổi này, chạy các bài test để đảm bảo mọi thứ hoạt động như mong đợi:

Terminal
$
test

Sau đó bạn có thể kiểm tra các liên kết SolanaFM để xem chi tiết giao dịch, nơi bạn sẽ tìm thấy các CPI cho các lệnh chuyển tiền trong các lệnh cập nhật và xóa.

CPI Cập nhậtCPI Cập nhật

CPI XóaCPI Xóa

Nếu bạn gặp bất kỳ lỗi nào, bạn có thể tham khảo mã cuối cùng.

Các bước tiếp theo

Chúc mừng bạn đã hoàn thành hướng dẫn Quickstart của Solana. Bạn đã có được kinh nghiệm thực hành với các khái niệm chính của Solana bao gồm:

  • Lấy và đọc dữ liệu từ các tài khoản
  • Xây dựng và gửi các giao dịch
  • Triển khai và cập nhật các chương trình Solana
  • Làm việc với Program Derived Addresses (PDAs)
  • Thực hiện Cross-Program Invocations (CPIs)

Để hiểu sâu hơn về các khái niệm này, hãy xem tài liệu Khái niệm cốt lõi cung cấp các giải thích chi tiết về các chủ đề được đề cập trong hướng dẫn này.

Khám phá thêm các ví dụ

Nếu bạn thích học thông qua ví dụ, hãy xem Kho lưu trữ ví dụ chương trình để tìm hiểu nhiều chương trình mẫu khác nhau.

Solana Playground cung cấp một tính năng tiện lợi cho phép bạn nhập hoặc xem các dự án bằng cách sử dụng liên kết GitHub của họ. Ví dụ, mở liên kết Solana Playground này để xem dự án Anchor từ kho GitHub này.

Nhấp vào nút Import và nhập tên dự án để thêm vào danh sách các dự án của bạn trong Solana Playground. Khi một dự án được nhập, tất cả các thay đổi sẽ được tự động lưu và duy trì.

Is this page helpful?

Mục lục

Chỉnh sửa trang