Développement de programmes en Rust
Les programmes Solana sont principalement développés en utilisant le langage de programmation Rust. Cette page se concentre sur l'écriture de programmes Solana en Rust sans utiliser le framework Anchor, une approche souvent appelée écriture de programmes "Rust natifs".
Le développement en Rust natif offre aux développeurs un contrôle direct sur leurs programmes Solana. Cependant, cette approche nécessite plus de configuration manuelle et de code standard par rapport à l'utilisation du framework Anchor. Cette méthode est recommandée pour les développeurs qui :
- Recherchent un contrôle granulaire sur la logique et les optimisations du programme
- Souhaitent apprendre les concepts sous-jacents avant de passer à des frameworks de plus haut niveau
Pour les débutants, nous recommandons de commencer avec le framework Anchor. Consultez la section Anchor pour plus d'informations.
Prérequis
Pour des instructions d'installation détaillées, visitez la page installation.
Avant de commencer, assurez-vous d'avoir installé les éléments suivants :
- Rust : Le langage de programmation pour construire des programmes Solana.
- Solana CLI : Outil en ligne de commande pour le développement Solana.
Premiers pas
L'exemple ci-dessous couvre les étapes de base pour créer votre premier programme Solana écrit en Rust. Nous allons créer un programme minimal qui affiche "Hello, world !" dans le journal du programme.
Créer un nouveau programme
D'abord, créez un nouveau projet Rust en utilisant la commande standard
cargo new
avec le drapeau --lib
.
$cargo new hello_world --lib
Naviguez vers le répertoire du projet. Vous devriez voir les fichiers par défaut
src/lib.rs
et Cargo.toml
$cd hello_world
Mettez à jour le champ edition
dans Cargo.toml
à 2021
. Sinon, vous
pourriez rencontrer une erreur lors de la compilation du programme.
Ajouter la dépendance solana-program
Ensuite, ajoutez la dépendance solana-program
. C'est la dépendance minimale
requise pour construire un programme Solana.
$cargo add solana-program@2.2.0
Ajouter le crate-type
Ensuite, ajoutez l'extrait suivant à Cargo.toml
.
[lib]crate-type = ["cdylib", "lib"]
Si vous n'incluez pas cette configuration, le répertoire target/deploy
ne
sera pas généré lorsque vous construirez le programme.
Votre fichier Cargo.toml
devrait ressembler à ce qui suit :
[package]name = "hello_world"version = "0.1.0"edition = "2021"[lib]crate-type = ["cdylib", "lib"][dependencies]solana-program = "2.2.0"
Ajouter le code du programme
Ensuite, remplacez le contenu de src/lib.rs
par le code suivant. C'est un
programme Solana minimal qui affiche "Hello, world!" dans le journal du
programme lorsque le programme est invoqué.
La macro msg!
est utilisée dans les programmes Solana pour afficher un message
dans le journal du programme.
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(())}
Compiler le programme
Ensuite, compilez le programme en utilisant la commande cargo build-sbf
.
$cargo build-sbf
Cette commande génère un répertoire target/deploy
contenant deux fichiers
importants :
- Un fichier
.so
(par ex.,hello_world.so
) : C'est le programme Solana compilé qui sera déployé sur le réseau comme un "smart contract". - Un fichier keypair (par ex.,
hello_world-keypair.json
) : La clé publique de ce keypair est utilisée comme ID du programme lors du déploiement du programme.
Pour voir l'ID du programme, exécutez la commande suivante dans votre terminal. Cette commande affiche la clé publique du keypair au chemin de fichier spécifié :
$solana address -k ./target/deploy/hello_world-keypair.json
Exemple de sortie :
4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz
Ajouter les dépendances de test
Ensuite, testez le programme en utilisant le crate litesvm
. Ajoutez les
dépendances suivantes à Cargo.toml
.
$cargo add litesvm --dev$cargo add solana-sdk@2.2.0 --dev
Tester le programme
Ajoutez le test suivant à src/lib.rs
, sous le code du programme. Il s'agit
d'un module de test qui invoque le programme 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:#?}");}}
Exécutez le test en utilisant la commande cargo test
. Le journal du programme
affichera "Hello, world!".
$cargo test -- --no-capture
Exemple de sortie :
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
Déployer le programme
Ensuite, déployez le programme. Lors du développement en local, nous pouvons
utiliser le solana-test-validator
.
D'abord, configurez l'interface en ligne de commande Solana pour utiliser le cluster Solana local.
$solana config set -ul
Exemple de sortie :
Config File: /.config/solana/cli/config.ymlRPC URL: http://localhost:8899WebSocket URL: ws://localhost:8900/ (computed)Keypair Path: /.config/solana/id.jsonCommitment: confirmed
Ouvrez un nouveau terminal et exécutez la commande solana-test-validators
pour
démarrer le validator local.
$solana-test-validator
Pendant que le validator de test est en cours d'exécution, exécutez la commande
solana program deploy
dans un terminal séparé pour déployer le programme sur
le validator local.
$solana program deploy ./target/deploy/hello_world.so
Exemple de sortie :
Program Id: 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMzSignature:5osMiNMiDZGM7L1e2tPHxU8wdB8gwG8fDnXLg5G7SbhwFz4dHshYgAijk4wSQL5cXiu8z1MMou5kLadAQuHp7ybH
Vous pouvez examiner l'ID du programme et la signature de transaction sur Solana Explorer.
Notez que le cluster sur Solana Explorer doit également être localhost.
L'option "URL RPC personnalisée" sur Solana Explorer est par défaut
http://localhost:8899
.
Créer un client d'exemple
Ensuite, nous allons démontrer comment invoquer le programme en utilisant un client Rust.
Créez d'abord un répertoire examples
et un fichier client.rs
.
$mkdir -p examples && touch examples/client.rs
Ajoutez ce qui suit à Cargo.toml
.
[[example]]name = "client"path = "examples/client.rs"
Ajoutez les dépendances solana-client
et tokio
.
$cargo add solana-client@2.2.0 --dev$cargo add tokio --dev
Ajouter le client
Ajoutez le code suivant à examples/client.rs
. Il s'agit d'un script client
Rust qui finance un nouveau keypair pour payer les frais de transaction, puis
invoque le programme 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),}}
Remplacer l'ID du programme
Avant d'exécuter le code client, remplacez l'ID du programme dans l'extrait de code par celui de votre programme.
Vous pouvez obtenir l'ID de votre programme en exécutant la commande suivante.
$solana address -k ./target/deploy/hello_world-keypair.json
Invoquer le programme
Exécutez le script client avec la commande suivante.
$cargo run --example client
Exemple de sortie :
Transaction Signature: 54TWxKi3Jsi3UTeZbhLGUFX6JQH7TspRJjRRFZ8NFnwG5BXM9udxiX77bAACjKAS9fGnVeEazrXL4SfKrW7xZFYV
Vous pouvez examiner la signature de la transaction sur Solana Explorer (cluster local) pour voir "Hello, world!" dans le journal du programme.
Mettre à jour le programme
Les programmes Solana peuvent être mis à jour en redéployant sur le même ID de
programme. Mettez à jour le programme dans src/lib.rs
pour afficher "Hello,
Solana!" au lieu de "Hello, world!".
pub fn process_instruction(_program_id: &Pubkey,_accounts: &[AccountInfo],_instruction_data: &[u8],) -> ProgramResult {-msg!("Hello, world!");+msg!("Hello, Solana!");Ok(())}
Exécutez la commande cargo build-sbf
pour générer un fichier .so
mis à jour.
$cargo build-sbf
Testez le programme mis à jour en exécutant la commande cargo test
.
$cargo test -- --no-capture
Vous devriez voir "Hello, Solana!" dans le journal du programme.
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
Redéployer le programme
Redéployez le programme en utilisant la même commande solana program deploy
.
$solana program deploy ./target/deploy/hello_world.so
Exécutez à nouveau le code client et examinez la signature de la transaction sur Solana Explorer pour voir "Hello, Solana!" dans le journal du programme.
$cargo run --example client
Fermer le programme
Vous pouvez fermer votre programme Solana pour récupérer le SOL alloué au compte. La fermeture d'un programme est irréversible, elle doit donc être effectuée avec prudence.
Pour fermer un programme, utilisez la commande
solana program close <PROGRAM_ID>
. Par exemple :
$solana program close 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz --bypass-warning
Exemple de sortie :
Closed Program Id 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz, 0.1350588 SOLreclaimed
Notez qu'une fois qu'un programme est fermé, son ID de programme ne peut pas être réutilisé. Toute tentative de déployer un programme avec un ID de programme précédemment fermé entraînera une erreur.
Error: Program 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz has been closed, usea new Program Id
Redéployer un programme fermé
Si vous devez redéployer un programme avec le même code source après avoir fermé un programme, vous devez générer un nouvel ID de programme. Pour générer un nouveau keypair pour le programme, exécutez la commande suivante :
$solana-keygen new -o ./target/deploy/hello_world-keypair.json --force
Alternativement, vous pouvez supprimer le fichier keypair existant (par ex.
./target/deploy/hello_world-keypair.json
) et exécuter cargo build-sbf
à
nouveau, ce qui générera un nouveau fichier keypair.
Is this page helpful?