Solana DokumentationProgramme entwickeln

Entwicklung von Programmen in Rust

Solana-Programme werden hauptsächlich mit der Programmiersprache Rust entwickelt. Diese Seite konzentriert sich auf das Schreiben von Solana-Programmen in Rust ohne Verwendung des Anchor Frameworks, ein Ansatz, der oft als Schreiben von "nativem Rust"-Programmen bezeichnet wird.

Die native Rust-Entwicklung bietet Entwicklern direkte Kontrolle über ihre Solana-Programme. Dieser Ansatz erfordert jedoch mehr manuelle Einrichtung und Boilerplate-Code im Vergleich zur Verwendung des Anchor-Frameworks. Diese Methode wird für Entwickler empfohlen, die:

  • Detaillierte Kontrolle über Programmlogik und Optimierungen suchen
  • Die zugrundeliegenden Konzepte verstehen möchten, bevor sie zu höheren Frameworks übergehen

Für Anfänger empfehlen wir, mit dem Anchor-Framework zu beginnen. Weitere Informationen finden Sie im Anchor-Abschnitt.

Voraussetzungen

Detaillierte Installationsanweisungen finden Sie auf der Installationsseite.

Bevor Sie beginnen, stellen Sie sicher, dass Sie Folgendes installiert haben:

  • Rust: Die Programmiersprache zum Erstellen von Solana-Programmen.
  • Solana CLI: Kommandozeilen-Tool für die Solana-Entwicklung.

Erste Schritte

Das folgende Beispiel behandelt die grundlegenden Schritte zur Erstellung Ihres ersten Solana-Programms in Rust. Wir erstellen ein minimales Programm, das "Hello, world!" in das Programmprotokoll schreibt.

Erstellen eines neuen Programms

Erstellen Sie zunächst ein neues Rust-Projekt mit dem Standard cargo initBefehl und der --libFlag.

Terminal
cargo init hello_world --lib

Navigieren Sie zum Projektverzeichnis. Sie sollten die Standard src/lib.rs und Cargo.tomlDateien sehen

Terminal
cd hello_world

Fügen Sie als Nächstes die solana-programAbhängigkeit hinzu. Dies ist die minimale Abhängigkeit, die zum Erstellen eines Solana-Programms erforderlich ist.

Terminal
cargo add solana-program@1.18.26

Füge als Nächstes den folgenden Codeausschnitt zu Cargo.toml hinzu. Wenn du diese Konfiguration nicht einfügst, wird das Verzeichnis target/deploy beim Erstellen des Programms nicht generiert.

Cargo.toml
[lib]
crate-type = ["cdylib", "lib"]

Deine Datei Cargo.toml sollte wie folgt aussehen:

Cargo.toml
[package]
name = "hello_world"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib", "lib"]
[dependencies]
solana-program = "1.18.26"

Ersetze als Nächstes den Inhalt von src/lib.rs mit dem folgenden Code. Dies ist ein minimales Solana-Programm, das "Hello, world!" in das Programmprotokoll schreibt, wenn das Programm aufgerufen wird.

Das Makro msg! wird in Solana-Programmen verwendet, um eine Nachricht in das Programmprotokoll zu schreiben.

lib.rs
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(())
}

Programm erstellen

Erstelle als Nächstes das Programm mit dem Befehl cargo build-sbf.

Terminal
cargo build-sbf

Dieser Befehl generiert ein Verzeichnis target/deploy mit zwei wichtigen Dateien:

  1. Eine .soDatei (z.B. hello_world.so): Dies ist das kompilierte Solana-Programm, das als "Smart Contract" im Netzwerk bereitgestellt wird.
  2. Eine keypair-Datei (z.B. hello_world-keypair.json): Der öffentliche Schlüssel dieses keypairs wird als Programm-ID bei der Bereitstellung des Programms verwendet.

Um die Programm-ID anzuzeigen, führe den folgenden Befehl in deinem Terminal aus. Dieser Befehl gibt den öffentlichen Schlüssel des keypairs am angegebenen Dateipfad aus:

Terminal
solana address -k ./target/deploy/hello_world-keypair.json

Beispielausgabe:

4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz

Programm testen

Teste als Nächstes das Programm mit der Crate solana-program-test. Füge die folgenden Abhängigkeiten zu Cargo.toml hinzu.

Terminal
cargo add solana-program-test@1.18.26 --dev
cargo add solana-sdk@1.18.26 --dev
cargo add tokio --dev

Füge den folgenden Test zu src/lib.rs unterhalb des Programmcodes hinzu. Dies ist ein Test- Modul, das das Hello-World-Programm aufruft.

lib.rs
#[cfg(test)]
mod test {
use solana_program_test::*;
use solana_sdk::{
instruction::Instruction, pubkey::Pubkey, signature::Signer, transaction::Transaction,
};
#[tokio::test]
async fn test_hello_world() {
let program_id = Pubkey::new_unique();
let mut program_test = ProgramTest::default();
program_test.add_program("hello_world", program_id, None);
let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
// Create instruction
let instruction = Instruction {
program_id,
accounts: vec![],
data: vec![],
};
// Create transaction with instruction
let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
// Sign transaction
transaction.sign(&[&payer], recent_blockhash);
let transaction_result = banks_client.process_transaction(transaction).await;
assert!(transaction_result.is_ok());
}
}

Führe den Test mit dem Befehl cargo test-sbf aus. Das Programmprotokoll wird "Hello, world!" anzeigen.

Terminal
cargo test-sbf

Beispielausgabe:

Terminal
running 1 test
[2024-10-18T21:24:54.889570000Z INFO solana_program_test] "hello_world" SBF program from /hello_world/target/deploy/hello_world.so, modified 35 seconds, 828 ms, 268 µs and 398 ns ago
[2024-10-18T21:24:54.974294000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM invoke [1]
[2024-10-18T21:24:54.974814000Z DEBUG solana_runtime::message_processor::stable_log] Program log: Hello, world!
[2024-10-18T21:24:54.976848000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM consumed 140 of 200000 compute units
[2024-10-18T21:24:54.976868000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM success
test test::test_hello_world ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.13s

Programm bereitstellen

Als Nächstes stellen Sie das Programm bereit. Bei der lokalen Entwicklung können wir den solana-test-validator verwenden.

Konfigurieren Sie zunächst die Solana CLI für die Verwendung des lokalen Solana-Clusters.

Terminal
solana config set -ul

Beispielausgabe:

Config File: /.config/solana/cli/config.yml
RPC URL: http://localhost:8899
WebSocket URL: ws://localhost:8900/ (computed)
Keypair Path: /.config/solana/id.json
Commitment: confirmed

Öffnen Sie ein neues Terminal und führen Sie den Befehl solana-test-validators aus, um den lokalen Validator zu starten.

Terminal
solana-test-validator

Während der Test-Validator läuft, führen Sie den Befehl solana program deploy in einem separaten Terminal aus, um das Programm auf dem lokalen Validator bereitzustellen.

Terminal
solana program deploy ./target/deploy/hello_world.so

Beispielausgabe:

Program Id: 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz
Signature:
5osMiNMiDZGM7L1e2tPHxU8wdB8gwG8fDnXLg5G7SbhwFz4dHshYgAijk4wSQL5cXiu8z1MMou5kLadAQuHp7ybH

Sie können die Programm-ID und die Transaktionssignatur auf Solana Explorer überprüfen. Beachten Sie, dass der Cluster im Solana Explorer ebenfalls localhost sein muss. Die Option "Custom RPC URL" im Solana Explorer ist standardmäßig auf http://localhost:8899 eingestellt.

Programm aufrufen

Als Nächstes zeigen wir, wie man das Programm mit einem Rust-Client aufruft.

Erstellen Sie zunächst ein Verzeichnis examples und eine Datei client.rs.

Terminal
mkdir -p examples
touch examples/client.rs

Fügen Sie Folgendes zu Cargo.toml hinzu.

Cargo.toml
[[example]]
name = "client"
path = "examples/client.rs"

Fügen Sie die Abhängigkeit solana-client hinzu.

Terminal
cargo add solana-client@1.18.26 --dev

Fügen Sie den folgenden Code zu examples/client.rs hinzu. Dies ist ein Rust-Client-Skript, das ein neues Keypair finanziert, um Transaktionsgebühren zu bezahlen, und dann das Hello-World-Programm aufruft.

example/client.rs
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 devnet
let rpc_url = String::from("http://127.0.0.1:8899");
let client = RpcClient::new_with_commitment(rpc_url, CommitmentConfig::confirmed());
// Generate a new keypair for the payer
let payer = Keypair::new();
// Request airdrop
let airdrop_amount = 1_000_000_000; // 1 SOL
let signature = client
.request_airdrop(&payer.pubkey(), airdrop_amount)
.expect("Failed to request airdrop");
// Wait for airdrop confirmation
loop {
let confirmed = client.confirm_transaction(&signature).unwrap();
if confirmed {
break;
}
}
// Create the instruction
let instruction = Instruction::new_with_borsh(
program_id,
&(), // Empty instruction data
vec![], // No accounts needed
);
// Add the instruction to new transaction
let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
transaction.sign(&[&payer], client.get_latest_blockhash().unwrap());
// Send and confirm the transaction
match client.send_and_confirm_transaction(&transaction) {
Ok(signature) => println!("Transaction Signature: {}", signature),
Err(err) => eprintln!("Error sending transaction: {}", err),
}
}

Bevor Sie das Skript ausführen, ersetzen Sie die Programm-ID im obigen Codeausschnitt durch die ID Ihres Programms.

Sie können Ihre Programm-ID mit dem folgenden Befehl abrufen.

Terminal
solana address -k ./target/deploy/hello_world-keypair.json
#[tokio::main]
async fn main() {
- let program_id = Pubkey::from_str("4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz").unwrap();
+ let program_id = Pubkey::from_str("YOUR_PROGRAM_ID).unwrap();
}
}

Führen Sie das Client-Skript mit dem folgenden Befehl aus.

Terminal
cargo run --example client

Beispielausgabe:

Transaction Signature: 54TWxKi3Jsi3UTeZbhLGUFX6JQH7TspRJjRRFZ8NFnwG5BXM9udxiX77bAACjKAS9fGnVeEazrXL4SfKrW7xZFYV

Sie können die Transaktionssignatur im Solana Explorer (lokaler Cluster) überprüfen, um "Hello, world!" im Programmlog zu sehen.

Programm aktualisieren

Solana-Programme können durch erneutes Bereitstellen unter derselben Programm-ID aktualisiert werden. Aktualisieren Sie das Programm in src/lib.rs, um "Hello, Solana!" anstelle von "Hello, world!" auszugeben.

lib.rs
pub fn process_instruction(
_program_id: &Pubkey,
_accounts: &[AccountInfo],
_instruction_data: &[u8],
) -> ProgramResult {
- msg!("Hello, world!");
+ msg!("Hello, Solana!");
Ok(())
}

Testen Sie das aktualisierte Programm, indem Sie den Befehl cargo test-sbf ausführen.

Terminal
cargo test-sbf

Sie sollten "Hello, Solana!" im Programmlog sehen.

Terminal
running 1 test
[2024-10-23T19:28:28.842639000Z INFO solana_program_test] "hello_world" SBF program from /code/misc/delete/hello_world/target/deploy/hello_world.so, modified 4 minutes, 31 seconds, 435 ms, 566 µs and 766 ns ago
[2024-10-23T19:28:28.934854000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM invoke [1]
[2024-10-23T19:28:28.936735000Z DEBUG solana_runtime::message_processor::stable_log] Program log: Hello, Solana!
[2024-10-23T19:28:28.938774000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM consumed 140 of 200000 compute units
[2024-10-23T19:28:28.938793000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM success
test test::test_hello_world ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.14s

Führen Sie den Befehl cargo build-sbf aus, um eine aktualisierte .so-Datei zu generieren.

Terminal
cargo build-sbf

Stellen Sie das Programm erneut bereit, indem Sie den Befehl solana program deploy verwenden.

Terminal
solana program deploy ./target/deploy/hello_world.so

Führen Sie den Client-Code erneut aus und überprüfen Sie die Transaktionssignatur im Solana Explorer, um "Hello, Solana!" im Programmlog zu sehen.

Terminal
cargo run --example client

Programm schließen

Sie können Ihr Solana-Programm schließen, um das dem Konto zugewiesene SOL zurückzufordern. Das Schließen eines Programms ist irreversibel und sollte daher mit Vorsicht durchgeführt werden.

Um ein Programm zu schließen, verwenden Sie den Befehl solana program close <PROGRAM_ID>. Zum Beispiel:

Terminal
solana program close 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz
--bypass-warning

Beispielausgabe:

Closed Program Id 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz, 0.1350588 SOL
reclaimed

Beachten Sie, dass sobald ein Programm geschlossen ist, seine Programm-ID nicht wiederverwendet werden kann. Der Versuch, ein Programm mit einer zuvor geschlossenen Programm-ID zu deployen, führt zu einem Fehler.

Error: Program 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz has been closed, use
a new Program Id

Wenn Sie ein Programm mit demselben Quellcode nach dem Schließen erneut deployen müssen, müssen Sie eine neue Programm-ID generieren. Um ein neues keypair für das Programm zu generieren, führen Sie den folgenden Befehl aus:

Terminal
solana-keygen new -o ./target/deploy/hello_world-keypair.json --force

Alternativ können Sie die vorhandene keypair-Datei (z.B. ./target/deploy/hello_world-keypair.json) löschen und cargo build-sbf erneut ausführen, was eine neue keypair-Datei generieren wird.

Is this page helpful?

Inhaltsverzeichnis

Seite bearbeiten