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 init
avec l'option --lib
.
cargo init 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
Ensuite, ajoutez la dépendance solana-program
. C'est la dépendance minimale
requise pour construire un programme Solana.
cargo add solana-program@1.18.26
Ensuite, ajoutez l'extrait suivant à Cargo.toml
. Si vous n'incluez pas cette
configuration, le répertoire target/deploy
ne sera pas généré lors de la
compilation du programme.
[lib]crate-type = ["cdylib", "lib"]
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 = "1.18.26"
Ensuite, remplacez le contenu de src/lib.rs
par le code suivant. Il s'agit
d'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 imprimer 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 exemple,hello_world.so
) : c'est le programme Solana compilé qui sera déployé sur le réseau en tant que "smart contract". - Un fichier de paire de clés (par exemple,
hello_world-keypair.json
) : la clé publique de cette paire de clés est utilisée comme ID de programme lors du déploiement du programme.
Pour afficher l'ID du programme, exécutez la commande suivante dans votre terminal. Cette commande affiche la clé publique de la paire de clés au chemin de fichier spécifié :
solana address -k ./target/deploy/hello_world-keypair.json
Exemple de sortie :
4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz
Tester le programme
Ensuite, testez le programme en utilisant la crate solana-program-test
.
Ajoutez les dépendances suivantes à Cargo.toml
.
cargo add solana-program-test@1.18.26 --devcargo add solana-sdk@1.18.26 --devcargo add tokio --dev
Ajoutez le test suivant à src/lib.rs
, en dessous du code du programme. Il
s'agit d'un module de test qui invoque le programme hello world.
#[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 instructionlet instruction = Instruction {program_id,accounts: vec![],data: vec![],};// Create transaction with instructionlet mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));// Sign transactiontransaction.sign(&[&payer], recent_blockhash);let transaction_result = banks_client.process_transaction(transaction).await;assert!(transaction_result.is_ok());}}
Exécutez le test en utilisant la commande cargo test-sbf
. Le journal du
programme affichera "Hello, world!".
cargo test-sbf
Exemple de sortie :
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 successtest test::test_hello_world ... oktest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.13s
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 le CLI 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 validateur local.
solana-test-validator
Pendant que le validateur de test est en cours d'exécution, lancez la commande
solana program deploy
dans un terminal séparé pour déployer le programme sur
le validateur local.
solana program deploy ./target/deploy/hello_world.so
Exemple de sortie :
Program Id: 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMzSignature:5osMiNMiDZGM7L1e2tPHxU8wdB8gwG8fDnXLg5G7SbhwFz4dHshYgAijk4wSQL5cXiu8z1MMou5kLadAQuHp7ybH
Vous pouvez inspecter 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
"Custom RPC URL" sur Solana Explorer est par défaut http://localhost:8899
.
Invoquer le programme
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 examplestouch examples/client.rs
Ajoutez ce qui suit à Cargo.toml
.
[[example]]name = "client"path = "examples/client.rs"
Ajoutez la dépendance solana-client
.
cargo add solana-client@1.18.26 --dev
Ajoutez le code suivant à examples/client.rs
. Il s'agit d'un script client
Rust qui finance une nouvelle paire de clés 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://127.0.0.1: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),}}
Avant d'exécuter le script, remplacez l'ID du programme dans l'extrait de code ci-dessus 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
#[tokio::main]async fn main() {- let program_id = Pubkey::from_str("4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz").unwrap();+ let program_id = Pubkey::from_str("YOUR_PROGRAM_ID).unwrap();}}
Exécutez le script client avec la commande suivante.
cargo run --example client
Exemple de sortie :
Transaction Signature: 54TWxKi3Jsi3UTeZbhLGUFX6JQH7TspRJjRRFZ8NFnwG5BXM9udxiX77bAACjKAS9fGnVeEazrXL4SfKrW7xZFYV
Vous pouvez inspecter la signature de 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(())}
Testez le programme mis à jour en exécutant la commande cargo test-sbf
.
cargo test-sbf
Vous devriez voir "Hello, Solana!" dans le journal du programme.
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 successtest test::test_hello_world ... oktest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.14s
Exécutez la commande cargo build-sbf
pour générer un fichier .so
mis à jour.
cargo build-sbf
Redéployez le programme en utilisant la commande solana program deploy
.
solana program deploy ./target/deploy/hello_world.so
Exécutez à nouveau le code client et inspectez la signature de 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 plus être réutilisé. Tenter 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
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 une nouvelle paire de clés 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 de paire de clés existant (par
exemple ./target/deploy/hello_world-keypair.json
) et exécuter
cargo build-sbf
à nouveau, ce qui générera un nouveau fichier de paire de
clés.
Is this page helpful?