Розробка програм на Rust
Програми Solana переважно розробляються за допомогою мови програмування Rust. Ця сторінка зосереджена на написанні програм Solana на Rust без використання фреймворку Anchor, підхід, який часто називають написанням програм на "нативному Rust".
Розробка на нативному Rust надає розробникам прямий контроль над їхніми програмами Solana. Однак цей підхід вимагає більше ручного налаштування та шаблонного коду порівняно з використанням фреймворку Anchor. Цей метод рекомендується для розробників, які:
- Прагнуть детального контролю над логікою програми та оптимізаціями
- Хочуть вивчити основні концепції перед переходом до фреймворків вищого рівня
Для початківців ми рекомендуємо почати з фреймворку Anchor. Дивіться розділ Anchor для отримання додаткової інформації.
Передумови
Для детальних інструкцій з встановлення відвідайте сторінку встановлення.
Перш ніж почати, переконайтеся, що у вас встановлено наступне:
- Rust: Мова програмування для створення програм Solana.
- Solana CLI: Інструмент командного рядка для розробки на Solana.
Початок роботи
Приклад нижче охоплює основні кроки для створення вашої першої програми Solana, написаної на Rust. Ми створимо мінімальну програму, яка виводить "Hello, world!" у журнал програми.
Створення нової програми
Спочатку створіть новий проект Rust, використовуючи стандартну команду
cargo new
з прапорцем --lib
.
$cargo new hello_world --lib
Перейдіть до каталогу проекту. Ви повинні побачити стандартні файли src/lib.rs
та Cargo.toml
$cd hello_world
Оновіть поле edition
у файлі Cargo.toml
на 2021
. Інакше ви можете
зіткнутися з помилкою під час збірки програми.
Додайте залежність solana-program
Далі додайте залежність solana-program
. Це мінімальна залежність, необхідна
для створення програми Solana.
$cargo add solana-program@2.2.0
Додайте crate-type
Далі додайте наступний фрагмент до Cargo.toml
.
[lib]crate-type = ["cdylib", "lib"]
Якщо ви не включите цю конфігурацію, каталог target/deploy
не буде створено
під час збірки програми.
Ваш файл Cargo.toml
повинен виглядати так:
[package]name = "hello_world"version = "0.1.0"edition = "2021"[lib]crate-type = ["cdylib", "lib"][dependencies]solana-program = "2.2.0"
Додайте код програми
Далі замініть вміст src/lib.rs
наступним кодом. Це мінімальна програма Solana,
яка виводить "Hello, world!" у журнал програми, коли програма викликається.
Макрос msg!
використовується в програмах Solana для виведення повідомлення в
журнал програми.
use solana_program::{account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, msg, pubkey::Pubkey,};entrypoint!(process_instruction);pub fn process_instruction(_program_id: &Pubkey,_accounts: &[AccountInfo],_instruction_data: &[u8],) -> ProgramResult {msg!("Hello, world!");Ok(())}
Зберіть програму
Далі зберіть програму за допомогою команди cargo build-sbf
.
$cargo build-sbf
Ця команда створює каталог target/deploy
, що містить два важливі файли:
- Файл
.so
(наприклад,hello_world.so
): Це скомпільована програма Solana, яка буде розгорнута в мережі як "смарт-контракт". - Файл keypair (наприклад,
hello_world-keypair.json
): Публічний ключ цього keypair використовується як ідентифікатор програми при розгортанні програми.
Щоб переглянути ідентифікатор програми, виконайте наступну команду в терміналі. Ця команда виводить публічний ключ keypair за вказаним шляхом до файлу:
$solana address -k ./target/deploy/hello_world-keypair.json
Приклад виводу:
$ cargo new hello-world
$ cd hello-world
$ cargo add solana-program
Додайте тестові залежності
Далі, протестуйте програму за допомогою крейту litesvm
. Додайте наступні
залежності до Cargo.toml
.
[dev-dependencies]solana-program-test = "1.16.0"solana-sdk = "1.16.0"
$ cargo add solana-program-test solana-sdk --dev
Протестуйте програму
Додайте наступний тест до src/lib.rs
, під кодом програми. Це тестовий модуль,
який викликає програму hello world.
#[cfg(test)]mod test {use super::*;use solana_program::instruction::{AccountMeta, Instruction};use solana_program_test::*;use solana_sdk::{signature::Signer, transaction::Transaction};#[tokio::test]async fn test_transaction() {let program_id = Pubkey::new_unique();let (mut banks_client, payer, recent_blockhash) = ProgramTest::new("hello_world",program_id,processor!(process_instruction),).start().await;let instruction = Instruction::new_with_bincode(program_id,&[0],vec![],);let mut transaction = Transaction::new_with_payer(&[instruction],Some(&payer.pubkey()),);transaction.sign(&[&payer], recent_blockhash);banks_client.process_transaction(transaction).await.unwrap();}}
Запустіть тест за допомогою команди cargo test
. У журналі програми
відобразиться "Hello, world!".
$cargo test -- --no-capture
Приклад виводу:
running 1 testtest test::test_transaction ... oktest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00sProgram log: Hello, world!
Розгорніть програму
Далі, розгорніть програму. Під час локальної розробки ми можемо використовувати
solana-test-validator
.
Спочатку налаштуйте Solana CLI для використання локального кластера Solana.
$ solana config set --url localhost
Приклад виводу:
Config File: ~/.config/solana/cli/config.ymlRPC URL: http://localhost:8899WebSocket URL: ws://localhost:8900/ (computed)Keypair Path: ~/.config/solana/id.jsonCommitment: confirmed
Відкрийте новий термінал і запустіть команду solana-test-validators
для
запуску локального validator.
$ solana-test-validator
Поки тестовий validator працює, запустіть команду solana program deploy
в
окремому терміналі, щоб розгорнути програму на локальному validator.
$solana program deploy ./target/deploy/hello_world.so
Приклад виводу:
Program Id: 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMzSignature:5osMiNMiDZGM7L1e2tPHxU8wdB8gwG8fDnXLg5G7SbhwFz4dHshYgAijk4wSQL5cXiu8z1MMou5kLadAQuHp7ybH
Ви можете переглянути ідентифікатор програми та підпис транзакції в Solana Explorer.
Зверніть увагу, що кластер у Solana Explorer також має бути localhost. Опція
"Custom RPC URL" у Solana Explorer за замовчуванням встановлена на
http://localhost:8899
.
Створення прикладу клієнта
Далі ми продемонструємо, як викликати програму за допомогою клієнта на Rust.
Спочатку створіть директорію examples
та файл client.rs
.
$mkdir -p examples && touch examples/client.rs
Додайте наступне до Cargo.toml
.
[[example]]name = "client"path = "examples/client.rs"
Додайте залежності solana-client
та tokio
.
$cargo add solana-client@2.2.0 --dev$cargo add tokio --dev
Додавання клієнта
Додайте наступний код до examples/client.rs
. Це скрипт клієнта на Rust, який
фінансує новий keypair для оплати комісій за транзакції, а потім викликає
програму hello world.
use solana_client::rpc_client::RpcClient;use solana_sdk::{commitment_config::CommitmentConfig,instruction::Instruction,pubkey::Pubkey,signature::{Keypair, Signer},transaction::Transaction,};use std::str::FromStr;#[tokio::main]async fn main() {// Program ID (replace with your actual program ID)let program_id = Pubkey::from_str("4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz").unwrap();// Connect to the Solana devnetlet rpc_url = String::from("http://localhost:8899");let client = RpcClient::new_with_commitment(rpc_url, CommitmentConfig::confirmed());// Generate a new keypair for the payerlet payer = Keypair::new();// Request airdroplet airdrop_amount = 1_000_000_000; // 1 SOLlet signature = client.request_airdrop(&payer.pubkey(), airdrop_amount).expect("Failed to request airdrop");// Wait for airdrop confirmationloop {let confirmed = client.confirm_transaction(&signature).unwrap();if confirmed {break;}}// Create the instructionlet instruction = Instruction::new_with_borsh(program_id,&(), // Empty instruction datavec![], // No accounts needed);// Add the instruction to new transactionlet mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));transaction.sign(&[&payer], client.get_latest_blockhash().unwrap());// Send and confirm the transactionmatch client.send_and_confirm_transaction(&transaction) {Ok(signature) => println!("Transaction Signature: {}", signature),Err(err) => eprintln!("Error sending transaction: {}", err),}}
Заміна ідентифікатора програми
Перед запуском клієнтського коду замініть ідентифікатор програми у фрагменті коду на той, що відповідає вашій програмі.
Ви можете отримати ідентифікатор вашої програми, виконавши наступну команду.
$solana address -k ./target/deploy/hello_world-keypair.json
Виклик програми
Запустіть клієнтський скрипт за допомогою наступної команди.
$cargo run --example client
Приклад виводу:
Transaction Signature: 54TWxKi3Jsi3UTeZbhLGUFX6JQH7TspRJjRRFZ8NFnwG5BXM9udxiX77bAACjKAS9fGnVeEazrXL4SfKrW7xZFYV
Ви можете перевірити підпис транзакції в Solana Explorer (локальний кластер), щоб побачити "Hello, world!" у журналі програми.
Оновлення програми
Програми Solana можна оновлювати, повторно розгортаючи їх з тим самим
ідентифікатором програми. Оновіть програму в src/lib.rs
, щоб вона виводила
"Hello, Solana!" замість "Hello, world!".
pub fn process_instruction(_program_id: &Pubkey,_accounts: &[AccountInfo],_instruction_data: &[u8],) -> ProgramResult {-msg!("Hello, world!");+msg!("Hello, Solana!");Ok(())}
Виконайте команду cargo build-sbf
, щоб згенерувати оновлений файл .so
.
$cargo build-sbf
Протестуйте оновлену програму, виконавши команду cargo test
.
$cargo test -- --no-capture
Ви повинні побачити "Hello, Solana!" у журналі програми.
running 1 testLogs: ["Program 5y8bHrnwfq2dLDgLn3WoTHb9dDuyorj9gyapW6aeyrpV invoke [1]","Program log: Hello, Solana!","Program 5y8bHrnwfq2dLDgLn3WoTHb9dDuyorj9gyapW6aeyrpV consumed 211 of 200000 compute units","Program 5y8bHrnwfq2dLDgLn3WoTHb9dDuyorj9gyapW6aeyrpV success",]test test::test_hello_world ... oktest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.08s
Повторне розгортання програми
Повторно розгорніть програму, використовуючи ту саму команду
solana program deploy
.
$solana program deploy ./target/deploy/hello_world.so
Запустіть клієнтський код знову та перевірте підпис транзакції в Solana Explorer, щоб побачити "Hello, Solana!" у журналі програми.
$cargo run --example client
Закриття програми
Ви можете закрити свою програму Solana, щоб повернути SOL, виділений для облікового запису. Закриття програми є незворотним, тому це слід робити з обережністю.
Щоб закрити програму, використовуйте команду
solana program close <PROGRAM_ID>
. Наприклад:
$solana program close 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz --bypass-warning
Приклад виводу:
Closed Program Id 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz, 0.1350588 SOLreclaimed
Зверніть увагу, що після закриття програми її ідентифікатор програми не може бути використаний повторно. Спроба розгорнути програму з раніше закритим ідентифікатором програми призведе до помилки.
Error: Program 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz has been closed, usea new Program Id
Повторне розгортання закритої програми
Якщо вам потрібно повторно розгорнути програму з тим самим вихідним кодом після закриття програми, ви повинні згенерувати новий ідентифікатор програми. Щоб згенерувати нову keypair для програми, виконайте таку команду:
$solana-keygen new -o ./target/deploy/hello_world-keypair.json --force
Альтернативно, ви можете видалити існуючий файл keypair (наприклад,
./target/deploy/hello_world-keypair.json
) і знову виконати cargo build-sbf
, що згенерує новий файл keypair.
Is this page helpful?