Cross Program Invocation
У цьому розділі програма CRUD з попереднього розділу про PDA оновлюється шляхом додавання міжпрограмних викликів (Cross Program Invocations, CPIs) — функції, яка дозволяє програмам Solana викликати одна одну.
Цей посібник також показує, як програми можуть "підписуватися" за адреси, похідні від програми (Program Derived Addresses, PDAs) під час здійснення міжпрограмних викликів.
Інструкції update
та delete
потребують модифікації для обробки переказів SOL
між рахунками шляхом виклику System Program.
Мета цього розділу включає покроковий процес реалізації CPIs у програмі Solana за допомогою фреймворку Anchor, спираючись на концепції PDA, розглянуті в попередньому розділі. Для отримання додаткової інформації зверніться до сторінки Cross Program Invocation.
Для довідки, це посилання містить фінальний код після завершення обох розділів PDA та CPI.
Початковий код для цього розділу включає лише завершений розділ PDA.
Оновлення інструкції Update
Спочатку програмі потрібен простий механізм "плати за оновлення" шляхом зміни
структури Update
та функції update
.
Почніть з оновлення файлу lib.rs
, щоб включити в область видимості елементи з
модуля system_program
.
use anchor_lang::system_program::{transfer, Transfer};
Далі оновіть структуру Update
, щоб включити новий рахунок під назвою
vault_account
. Цей рахунок, контрольований програмою, отримує SOL від
користувача, коли він оновлює свій рахунок повідомлення.
#[account(mut,seeds = [b"vault", user.key().as_ref()],bump,)]pub vault_account: SystemAccount<'info>,
Далі додайте логіку CPI в інструкцію update
для переказу 0.001 SOL з
облікового запису користувача на обліковий запис сховища.
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)?;
Перебудуйте програму.
$build
Оновлення інструкції видалення
Тепер додайте механізм "повернення коштів при видаленні", змінивши структуру
Delete
та функцію delete
.
Спочатку оновіть структуру Delete
, щоб включити vault_account
. Це
дозволяє переказувати будь-який SOL зі сховища назад користувачу, коли вони
закривають свій акаунт повідомлення.
#[account(mut,seeds = [b"vault", user.key().as_ref()],bump,)]pub vault_account: SystemAccount<'info>,
Також додайте system_program
, оскільки CPI для переказу вимагає виклику System
Program.
pub system_program: Program<'info, System>,
Далі додайте логіку CPI в інструкцію delete
для переказу SOL з облікового
запису сховища назад на обліковий запис користувача.
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>
для використання контексту в тілі функції.
Перебудуйте програму.
$build
Повторне розгортання програми
Після внесення цих змін повторно розгорніть оновлену програму. Це забезпечить доступність модифікованої програми для тестування. У Solana оновлення програми просто вимагає розгортання програми з тим самим ідентифікатором програми.
Переконайтеся, що ваш гаманець Playground має devnet SOL. Отримайте devnet SOL з Solana Faucet.
$deploy
Оновлення тестового файлу
Далі оновіть файл anchor.test.ts
, щоб включити новий акаунт сховища в
інструкції. Це вимагає отримання PDA сховища та включення його в виклики
інструкцій оновлення та видалення.
Отримання PDA сховища
Спочатку додайте отримання PDA сховища:
const [vaultPda, vaultBump] = PublicKey.findProgramAddressSync([Buffer.from("vault"), wallet.publicKey.toBuffer()],program.programId);
Зміна тесту оновлення
Потім оновіть інструкцію оновлення, щоб включити vaultAccount
const transactionSignature = await program.methods.update(message).accounts({messageAccount: messagePda,vaultAccount: vaultPda}).rpc({ commitment: "confirmed" });
Зміна тесту видалення
Потім оновіть інструкцію видалення, щоб включити vaultAccount
const transactionSignature = await program.methods.delete().accounts({messageAccount: messagePda,vaultAccount: vaultPda}).rpc({ commitment: "confirmed" });
Повторний запуск тесту
Після внесення цих змін запустіть тести, щоб переконатися, що все працює як очікувалося:
$test
Потім ви можете переглянути посилання SolanaFM для перегляду деталей транзакції, де ви знайдете CPIs для інструкцій переказу в межах інструкцій оновлення та видалення.
CPI оновлення
CPI видалення
Якщо ви зіткнулися з помилками, ви можете звернутися до фінального коду.
Наступні кроки
Вітаємо із завершенням посібника Solana Quickstart. Ви отримали практичний досвід роботи з ключовими концепціями Solana, включаючи:
- Отримання та читання даних з акаунтів
- Створення та надсилання транзакцій
- Розгортання та оновлення програм Solana
- Робота з Program Derived Addresses (PDAs)
- Виконання Cross-Program Invocation (CPIs)
Щоб поглибити розуміння цих концепцій, перегляньте документацію Основні концепції, яка надає детальні пояснення тем, висвітлених у цьому посібнику.
Дослідіть більше прикладів
Якщо ви віддаєте перевагу навчанню на прикладах, перегляньте Репозиторій прикладів програм для різноманітних прикладів програм.
Solana Playground пропонує зручну функцію, яка дозволяє імпортувати або переглядати проєкти за допомогою їхніх посилань на GitHub. Наприклад, відкрийте це посилання Solana Playground, щоб переглянути проєкт Anchor з цього репозиторію Github.
Натисніть кнопку Import
та введіть назву проєкту, щоб додати його до свого
списку проєктів у Solana Playground. Після імпорту проєкту всі зміни автоматично
зберігаються.
Is this page helpful?