Tworzenie programów w Rust
Programy Solana są głównie tworzone w języku programowania Rust. Ta strona koncentruje się na pisaniu programów Solana w Rust bez użycia frameworka Anchor, co często nazywane jest pisaniem programów w "czystym Rust".
Tworzenie w czystym Rust daje programistom bezpośrednią kontrolę nad ich programami Solana. Jednak podejście to wymaga więcej ręcznej konfiguracji i szablonowego kodu w porównaniu do użycia frameworka Anchor. Metoda ta jest zalecana dla programistów, którzy:
- Chcą mieć szczegółową kontrolę nad logiką programu i optymalizacjami
- Chcą poznać podstawowe koncepcje przed przejściem do frameworków wyższego poziomu
Dla początkujących zalecamy rozpoczęcie od frameworka Anchor. Zobacz sekcję Anchor po więcej informacji.
Wymagania wstępne
Szczegółowe instrukcje instalacji znajdziesz na stronie instalacja.
Przed rozpoczęciem upewnij się, że masz zainstalowane następujące elementy:
- Rust: Język programowania do tworzenia programów Solana.
- Solana CLI: Narzędzie wiersza poleceń do rozwoju Solana.
Pierwsze kroki
Poniższy przykład obejmuje podstawowe kroki tworzenia pierwszego programu Solana napisanego w Rust. Stworzymy minimalny program, który wypisuje "Hello, world!" do logu programu.
Utwórz nowy program
Najpierw utwórz nowy projekt w Rust, używając standardowego polecenia
cargo new
z flagą --lib
.
$cargo new hello_world --lib
Przejdź do katalogu projektu. Powinieneś zobaczyć domyślne pliki src/lib.rs
i
Cargo.toml
.
$cd hello_world
Zaktualizuj pole edition
w pliku Cargo.toml
na 2021
. W przeciwnym razie
możesz napotkać błąd podczas budowania programu.
Dodaj zależność solana-program
Następnie dodaj zależność solana-program
. Jest to minimalna zależność wymagana
do zbudowania programu Solana.
$cargo add solana-program@2.2.0
Dodaj typ crate
Następnie dodaj poniższy fragment do Cargo.toml
.
[lib]crate-type = ["cdylib", "lib"]
Jeśli nie uwzględnisz tej konfiguracji, katalog target/deploy
nie zostanie
wygenerowany podczas budowania programu.
Twój plik Cargo.toml
powinien wyglądać następująco:
[package]name = "hello_world"version = "0.1.0"edition = "2021"[lib]crate-type = ["cdylib", "lib"][dependencies]solana-program = "2.2.0"
Dodaj kod programu
Następnie zastąp zawartość src/lib.rs
poniższym kodem. Jest to minimalny
program Solana, który wypisuje "Hello, world!" do dziennika programu, gdy
program zostanie wywołany.
Makro msg!
jest używane w programach Solana do wypisywania wiadomości do
dziennika programu.
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(())}
Zbuduj program
Następnie zbuduj program za pomocą polecenia cargo build-sbf
.
$cargo build-sbf
To polecenie generuje katalog target/deploy
zawierający dwa ważne pliki:
- Plik
.so
(np.hello_world.so
): Jest to skompilowany program Solana, który zostanie wdrożony w sieci jako "smart contract". - Plik keypair (np.
hello_world-keypair.json
): Klucz publiczny tego keypair jest używany jako identyfikator programu podczas wdrażania programu.
Aby wyświetlić identyfikator programu, uruchom następujące polecenie w terminalu. To polecenie wypisuje klucz publiczny keypair znajdującego się w określonej ścieżce pliku:
$solana address -k ./target/deploy/hello_world-keypair.json
Przykładowy wynik:
4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz
Dodaj zależności testowe
Następnie przetestuj program, używając biblioteki litesvm
. Dodaj następujące
zależności do pliku Cargo.toml
.
$cargo add litesvm --dev$cargo add solana-sdk@2.2.0 --dev
Przetestuj program
Dodaj następujący test do pliku src/lib.rs
, poniżej kodu programu. Jest to
moduł testowy, który wywołuje program hello world.
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(())}#[cfg(test)]mod test {use litesvm::LiteSVM;use solana_sdk::{instruction::Instruction,message::Message,signature::{Keypair, Signer},transaction::Transaction,};#[test]fn test_hello_world() {// Create a new LiteSVM instancelet mut svm = LiteSVM::new();// Create a keypair for the transaction payerlet payer = Keypair::new();// Airdrop some lamports to the payersvm.airdrop(&payer.pubkey(), 1_000_000_000).unwrap();// Load our programlet program_keypair = Keypair::new();let program_id = program_keypair.pubkey();svm.add_program_from_file(program_id, "target/deploy/hello_world.so").unwrap();// Create instruction with no accounts and no datalet instruction = Instruction {program_id,accounts: vec![],data: vec![],};// Create transactionlet message = Message::new(&[instruction], Some(&payer.pubkey()));let transaction = Transaction::new(&[&payer], message, svm.latest_blockhash());// Send transaction and verify it succeedslet result = svm.send_transaction(transaction);assert!(result.is_ok(), "Transaction should succeed");let logs = result.unwrap().logs;println!("Logs: {logs:#?}");}}
Uruchom test za pomocą polecenia cargo test
. W dzienniku programu pojawi się
"Hello, world!".
$cargo test -- --no-capture
Przykładowy wynik:
running 1 testLogs: ["Program 9528phXNvdWp5kkR4rgpoeZvR8ZWT5THVywK95YRprkk invoke [1]","Program log: Hello, world!","Program 9528phXNvdWp5kkR4rgpoeZvR8ZWT5THVywK95YRprkk consumed 211 of 200000 compute units","Program 9528phXNvdWp5kkR4rgpoeZvR8ZWT5THVywK95YRprkk success",]test test::test_hello_world ... oktest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.05s
Wdróż program
Następnie wdroż program. Podczas pracy lokalnej możemy użyć
solana-test-validator
.
Najpierw skonfiguruj Solana CLI, aby używać lokalnego klastra Solana.
$solana config set -ul
Przykładowy wynik:
Config File: /.config/solana/cli/config.ymlRPC URL: http://localhost:8899WebSocket URL: ws://localhost:8900/ (computed)Keypair Path: /.config/solana/id.jsonCommitment: confirmed
Otwórz nowe okno terminala i uruchom polecenie solana-test-validators
, aby
uruchomić lokalny validator.
$solana-test-validator
Podczas gdy testowy validator działa, uruchom polecenie solana program deploy
w osobnym terminalu, aby wdrożyć program na lokalnym validatorze.
$solana program deploy ./target/deploy/hello_world.so
Przykładowy wynik:
Program Id: 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMzSignature:5osMiNMiDZGM7L1e2tPHxU8wdB8gwG8fDnXLg5G7SbhwFz4dHshYgAijk4wSQL5cXiu8z1MMou5kLadAQuHp7ybH
Możesz sprawdzić identyfikator programu i podpis transakcji na Solana Explorer.
Pamiętaj, że klaster na Solana Explorer musi również być localhost. Opcja
"Custom RPC URL" na Solana Explorer domyślnie wskazuje na
http://localhost:8899
.
Utwórz przykładowego klienta
Następnie pokażemy, jak wywołać program za pomocą klienta w języku Rust.
Najpierw utwórz katalog examples
i plik client.rs
.
$mkdir -p examples && touch examples/client.rs
Dodaj następujące elementy do Cargo.toml
.
[[example]]name = "client"path = "examples/client.rs"
Dodaj zależności solana-client
i tokio
.
$cargo add solana-client@2.2.0 --dev$cargo add tokio --dev
Dodaj klienta
Dodaj następujący kod do examples/client.rs
. Jest to skrypt klienta w języku
Rust, który finansuje nowy keypair, aby opłacić opłaty transakcyjne, a następnie
wywołuje program 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),}}
Zamień identyfikator programu
Przed uruchomieniem kodu klienta zamień identyfikator programu w fragmencie kodu na ten, który odpowiada Twojemu programowi.
Możesz uzyskać identyfikator swojego programu, uruchamiając następujące polecenie.
$solana address -k ./target/deploy/hello_world-keypair.json
Wywołaj program
Uruchom skrypt klienta za pomocą następującego polecenia.
$cargo run --example client
Przykładowy wynik:
Transaction Signature: 54TWxKi3Jsi3UTeZbhLGUFX6JQH7TspRJjRRFZ8NFnwG5BXM9udxiX77bAACjKAS9fGnVeEazrXL4SfKrW7xZFYV
Możesz sprawdzić podpis transakcji w Solana Explorer (lokalny klaster), aby zobaczyć "Hello, world!" w logu programu.
Zaktualizuj program
Programy Solana można aktualizować, ponownie wdrażając je pod tym samym ID
programu. Zaktualizuj program w src/lib.rs
, aby wyświetlał "Hello, Solana!"
zamiast "Hello, world!".
pub fn process_instruction(_program_id: &Pubkey,_accounts: &[AccountInfo],_instruction_data: &[u8],) -> ProgramResult {-msg!("Hello, world!");+msg!("Hello, Solana!");Ok(())}
Uruchom polecenie cargo build-sbf
, aby wygenerować zaktualizowany plik .so
.
$cargo build-sbf
Przetestuj zaktualizowany program, uruchamiając polecenie cargo test
.
$cargo test -- --no-capture
Powinieneś zobaczyć "Hello, Solana!" w logu programu.
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
Ponownie wdroż program
Ponownie wdroż program, używając tego samego polecenia solana program deploy
.
$solana program deploy ./target/deploy/hello_world.so
Uruchom ponownie kod klienta i sprawdź podpis transakcji w Solana Explorer, aby zobaczyć "Hello, Solana!" w logu programu.
$cargo run --example client
Zamknij program
Możesz zamknąć swój program Solana, aby odzyskać SOL przypisane do konta. Zamknięcie programu jest nieodwracalne, więc należy to zrobić ostrożnie.
Aby zamknąć program, użyj polecenia solana program close <PROGRAM_ID>
. Na
przykład:
$solana program close 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz --bypass-warning
Przykładowy wynik:
Closed Program Id 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz, 0.1350588 SOLreclaimed
Zwróć uwagę, że po zamknięciu programu jego identyfikator programu (program ID) nie może być ponownie użyty. Próba wdrożenia programu z wcześniej zamkniętym identyfikatorem programu zakończy się błędem.
Error: Program 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz has been closed, usea new Program Id
Ponowne wdrożenie zamkniętego programu
Jeśli musisz ponownie wdrożyć program z tym samym kodem źródłowym po jego zamknięciu, musisz wygenerować nowy identyfikator programu (program ID). Aby wygenerować nową parę kluczy dla programu, uruchom następujące polecenie:
$solana-keygen new -o ./target/deploy/hello_world-keypair.json --force
Alternatywnie możesz usunąć istniejący plik pary kluczy (np.
./target/deploy/hello_world-keypair.json
) i ponownie uruchomić cargo build-sbf
, co spowoduje wygenerowanie nowego pliku pary kluczy.
Is this page helpful?