Cross Program Invocation

В этом разделе программа CRUD из предыдущего раздела о PDA обновляется путем добавления Cross Program Invocations (CPIs) — функции, которая позволяет программам Solana вызывать друг друга.

В этом руководстве также показано, как программы могут "подписывать" Program Derived Addresses (PDAs) при выполнении Cross Program Invocations.

Инструкции update и delete требуют изменений для обработки переводов SOL между аккаунтами с помощью вызова System Program.

Цель этого раздела — пошагово рассмотреть процесс реализации CPIs в программе Solana с использованием фреймворка Anchor, основываясь на концепциях PDA, изученных в предыдущем разделе. Для получения дополнительной информации обратитесь к странице Cross Program Invocation.

Для справки, эта ссылка содержит финальный код после завершения разделов PDA и CPI.

Начальный код для этого раздела включает только завершенный раздел PDA.

Обновление инструкции Update

Сначала программе нужен простой механизм "pay-to-update" — для этого измените структуру Update и функцию update.

Начните с обновления файла lib.rs, чтобы подключить элементы из модуля system_program.

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

Далее обновите структуру Update, чтобы добавить новый аккаунт с именем vault_account. Этот аккаунт, управляемый программой, получает SOL от пользователя при обновлении его аккаунта сообщения.

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

Далее добавьте логику CPI в инструкцию update для перевода 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

Обновите инструкцию удаления

Теперь добавьте механизм "возврата при удалении", изменив структуру Delete и функцию delete.

Сначала обновите структуру Delete и добавьте vault_account. Это позволит переводить все SOL из хранилища обратно пользователю при закрытии его аккаунта сообщений.

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

Также добавьте system_program, так как для CPI-перевода требуется вызов System Program.

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

Далее добавьте логику CPI в инструкцию delete для перевода 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())?;

Обратите внимание, что _ctx: Context<Delete> меняется на ctx: Context<Delete> для использования контекста в теле функции.

Перестройте программу.

Terminal
$
build

Повторное развертывание программы

После внесения этих изменений повторно разверните обновленную программу. Это гарантирует, что модифицированная программа станет доступной для тестирования. В Solana обновление программы требует просто развертывания программы с тем же идентификатором программы.

Убедитесь, что в вашем кошельке Playground есть devnet SOL. Получите devnet SOL из Solana Faucet.

Terminal
$
deploy

Обновление тестового файла

Далее обновите файл anchor.test.ts, чтобы добавить новый аккаунт хранилища в инструкции. Для этого нужно получить vault PDA и включить его в вызовы инструкций update и delete.

Получение PDA хранилища

Сначала добавьте получение PDA хранилища:

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

Изменение теста обновления

Затем обновите инструкцию update, чтобы включить vaultAccount

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

Изменение теста удаления

Затем обновите инструкцию delete, чтобы включить vaultAccount

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

Повторный запуск теста

После внесения этих изменений запустите тесты, чтобы убедиться, что всё работает как ожидается:

Terminal
$
test

Затем вы можете проверить ссылки SolanaFM, чтобы просмотреть детали транзакции, где вы найдете CPI для инструкций передачи в рамках инструкций обновления и удаления.

Обновление CPIОбновление CPI

Удаление CPIУдаление CPI

Если вы столкнетесь с какими-либо ошибками, вы можете обратиться к финальному коду.

Следующие шаги

Поздравляем с завершением руководства по быстрому старту Solana. Вы получили практический опыт работы с ключевыми концепциями Solana, включая:

  • Получение и чтение данных из аккаунтов
  • Создание и отправка транзакций
  • Развертывание и обновление программ Solana
  • Работа с адресами, производными от программ (PDAs)
  • Выполнение межпрограммных вызовов (CPIs)

Чтобы углубить понимание этих концепций, ознакомьтесь с документацией Основные концепции, которая предоставляет подробные объяснения тем, рассмотренных в этом руководстве.

Изучите больше примеров

Если вы предпочитаете учиться на примерах, ознакомьтесь с репозиторием примеров программ, где представлено множество примеров программ.

Solana Playground предлагает удобную функцию, позволяющую импортировать или просматривать проекты, используя их ссылки на GitHub. Например, откройте эту ссылку на Solana Playground, чтобы просмотреть проект Anchor из этого репозитория на GitHub.

Нажмите кнопку Import и введите название проекта, чтобы добавить его в свой список проектов в Solana Playground. После импорта проекта все изменения будут сохраняться и сохраняться автоматически.

Is this page helpful?

Управляется

© 2026 Фонд Solana.
Все права защищены.
Подключиться