Desenvolvendo Programas em Rust
Os programas Solana são desenvolvidos principalmente usando a linguagem de programação Rust. Esta página concentra-se na escrita de programas Solana em Rust sem usar o framework Anchor, uma abordagem frequentemente referida como escrita de programas "Rust nativos".
O desenvolvimento em Rust nativo proporciona aos desenvolvedores controle direto sobre seus programas Solana. No entanto, esta abordagem requer mais configuração manual e código boilerplate em comparação com o uso do framework Anchor. Este método é recomendado para desenvolvedores que:
- Buscam controle granular sobre a lógica e otimizações do programa
- Querem aprender os conceitos subjacentes antes de passar para frameworks de nível superior
Para iniciantes, recomendamos começar com o framework Anchor. Veja a seção Anchor para mais informações.
Pré-requisitos
Para instruções detalhadas de instalação, visite a página de instalação.
Antes de começar, certifique-se de ter o seguinte instalado:
- Rust: A linguagem de programação para construir programas Solana.
- Solana CLI: Ferramenta de linha de comando para desenvolvimento Solana.
Primeiros Passos
O exemplo abaixo cobre os passos básicos para criar seu primeiro programa Solana escrito em Rust. Vamos criar um programa mínimo que imprime "Hello, world!" no log do programa.
Criar um novo programa
Primeiro, crie um novo projeto Rust usando o comando padrão cargo new
com a
flag --lib
.
$cargo new hello_world --lib
Navegue até o diretório do projeto. Você deverá ver os arquivos padrão
src/lib.rs
e Cargo.toml
$cd hello_world
Atualize o campo edition
no Cargo.toml
para 2021
. Caso contrário, você
pode encontrar um erro ao compilar o programa.
Adicione a dependência solana-program
Em seguida, adicione a dependência solana-program
. Esta é a dependência mínima
necessária para construir um programa Solana.
$cargo add solana-program@2.2.0
Adicione o crate-type
Em seguida, adicione o seguinte trecho ao Cargo.toml
.
[lib]crate-type = ["cdylib", "lib"]
Se você não incluir esta configuração, o diretório target/deploy
não será
gerado quando você compilar o programa.
Seu arquivo Cargo.toml
deve parecer com o seguinte:
[package]name = "hello_world"version = "0.1.0"edition = "2021"[lib]crate-type = ["cdylib", "lib"][dependencies]solana-program = "2.2.0"
Adicione o código do programa
Em seguida, substitua o conteúdo de src/lib.rs
pelo seguinte código. Este é um
programa Solana mínimo que imprime "Hello, world!" no log do programa quando o
programa é invocado.
A macro msg!
é usada em programas Solana para imprimir uma mensagem no log do
programa.
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(())}
Compile o programa
Em seguida, compile o programa usando o comando cargo build-sbf
.
$cargo build-sbf
Este comando gera um diretório target/deploy
contendo dois arquivos
importantes:
- Um arquivo
.so
(ex.:hello_world.so
): Este é o programa Solana compilado que será implantado na rede como um "contrato inteligente". - Um arquivo keypair (ex.:
hello_world-keypair.json
): A chave pública deste keypair é usada como o ID do programa ao implantar o programa.
Para visualizar o ID do programa, execute o seguinte comando no seu terminal. Este comando imprime a chave pública do keypair no caminho de arquivo especificado:
$solana address -k ./target/deploy/hello_world-keypair.json
Exemplo de saída:
$ cargo new hello-worldCreated binary (application) `hello-world` package
$ cd hello-world
$ cargo init --libCreated library package
Adicionar dependências de teste
Em seguida, teste o programa usando o crate litesvm
. Adicione as seguintes
dependências ao Cargo.toml
.
[package]name = "hello-world"version = "0.1.0"edition = "2021"[dependencies]solana-program = "1.18.0"[dev-dependencies]solana-program-test = "1.18.0"solana-sdk = "1.18.0"
$ cargo build
Testar o programa
Adicione o seguinte teste ao src/lib.rs
, abaixo do código do programa. Este é
um módulo de teste que invoca o programa 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();}}
Execute o teste usando o comando cargo test
. O log do programa exibirá "Hello,
world!".
$ cargo test
Exemplo de saída:
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!
Implantar o programa
Em seguida, implante o programa. Ao desenvolver localmente, podemos usar o
solana-test-validator
.
Primeiro, configure a CLI da Solana para usar o cluster local da Solana.
$ solana config set --url localhost
Exemplo de saída:
Config File: ~/.config/solana/cli/config.ymlRPC URL: http://localhost:8899WebSocket URL: ws://localhost:8900/ (computed)Keypair Path: ~/.config/solana/id.jsonCommitment: confirmed
Abra um novo terminal e execute o comando solana-test-validators
para iniciar
o validator local.
$ solana-test-validator
Enquanto o validator de teste estiver em execução, execute o comando
solana program deploy
em um terminal separado para implantar o programa no
validator local.
$ cargo build-sbf$ solana program deploy target/deploy/hello_world.so
Exemplo de saída:
Program Id: 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMzSignature:5osMiNMiDZGM7L1e2tPHxU8wdB8gwG8fDnXLg5G7SbhwFz4dHshYgAijk4wSQL5cXiu8z1MMou5kLadAQuHp7ybH
Você pode inspecionar o ID do programa e a assinatura da transação no Solana Explorer.
Observe que o cluster no Solana Explorer também deve ser localhost. A opção
"Custom RPC URL" no Solana Explorer tem como padrão http://localhost:8899
.
Criar cliente de exemplo
A seguir, demonstraremos como invocar o programa usando um cliente Rust.
Primeiro, crie um diretório examples
e um arquivo client.rs
.
$mkdir -p examples && touch examples/client.rs
Adicione o seguinte ao Cargo.toml
.
[[example]]name = "client"path = "examples/client.rs"
Adicione as dependências solana-client
e tokio
.
$cargo add solana-client@2.2.0 --dev$cargo add tokio --dev
Adicionar o cliente
Adicione o seguinte código ao examples/client.rs
. Este é um script cliente em
Rust que financia um novo keypair para pagar as taxas de transação e então
invoca o programa 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),}}
Substituir o ID do programa
Antes de executar o código do cliente, substitua o ID do programa no trecho de código pelo ID do seu programa.
Você pode obter o ID do seu programa executando o seguinte comando.
$solana address -k ./target/deploy/hello_world-keypair.json
Invocar o programa
Execute o script do cliente com o seguinte comando.
$cargo run --example client
Exemplo de saída:
Transaction Signature: 54TWxKi3Jsi3UTeZbhLGUFX6JQH7TspRJjRRFZ8NFnwG5BXM9udxiX77bAACjKAS9fGnVeEazrXL4SfKrW7xZFYV
Você pode inspecionar a assinatura da transação no Solana Explorer (cluster local) para ver "Hello, world!" no log do programa.
Atualizar o programa
Os programas Solana podem ser atualizados reimplantando-os com o mesmo ID de
programa. Atualize o programa em src/lib.rs
para imprimir "Hello, Solana!" em
vez de "Hello, world!".
pub fn process_instruction(_program_id: &Pubkey,_accounts: &[AccountInfo],_instruction_data: &[u8],) -> ProgramResult {-msg!("Hello, world!");+msg!("Hello, Solana!");Ok(())}
Execute o comando cargo build-sbf
para gerar um arquivo .so
atualizado.
$cargo build-sbf
Teste o programa atualizado executando o comando cargo test
.
$cargo test -- --no-capture
Você deverá ver "Hello, Solana!" no log do programa.
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
Reimplantar o programa
Reimplante o programa usando o mesmo comando solana program deploy
.
$solana program deploy ./target/deploy/hello_world.so
Execute o código do cliente novamente e inspecione a assinatura da transação no Solana Explorer para ver "Hello, Solana!" no log do programa.
$cargo run --example client
Fechar o programa
Você pode fechar seu programa Solana para recuperar o SOL alocado na conta. Fechar um programa é irreversível, então deve ser feito com cautela.
Para fechar um programa, use o comando solana program close <PROGRAM_ID>
. Por
exemplo:
$solana program close 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz --bypass-warning
Exemplo de saída:
Closed Program Id 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz, 0.1350588 SOLreclaimed
Observe que uma vez que um programa é fechado, seu ID de programa não pode ser reutilizado. Tentar implantar um programa com um ID de programa previamente fechado resultará em um erro.
Error: Program 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz has been closed, usea new Program Id
Reimplantar um programa fechado
Se você precisar reimplantar um programa com o mesmo código-fonte após fechar um programa, você deve gerar um novo ID de programa. Para gerar um novo keypair para o programa, execute o seguinte comando:
$solana-keygen new -o ./target/deploy/hello_world-keypair.json --force
Alternativamente, você pode excluir o arquivo keypair existente (por exemplo,
./target/deploy/hello_world-keypair.json
) e executar cargo build-sbf
novamente, que irá gerar um novo arquivo keypair.
Is this page helpful?