Documentação SolanaDesenvolvendo programas

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 do programa e otimizações
  • 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 init com a flag --lib.

Terminal
cargo init hello_world --lib

Navegue até o diretório do projeto. Você deve ver os arquivos padrão src/lib.rs e Cargo.toml

Terminal
cd hello_world

Em seguida, adicione a dependência solana-program. Esta é a dependência mínima necessária para construir um programa Solana.

Terminal
cargo add solana-program@1.18.26

Em seguida, adicione o seguinte trecho ao Cargo.toml. Se você não incluir esta configuração, o diretório target/deploy não será gerado quando você compilar o programa.

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

Seu arquivo Cargo.toml deve se parecer com o seguinte:

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

Em seguida, substitua o conteúdo de src/lib.rs com o código a seguir. 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.

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(())
}

Compilar o programa

Em seguida, compile o programa usando o comando cargo build-sbf.

Terminal
cargo build-sbf

Este comando gera um diretório target/deploy contendo dois arquivos importantes:

  1. Um arquivo .so (ex.: hello_world.so): Este é o programa Solana compilado que será implantado na rede como um "smart contract".
  2. Um arquivo keypair (ex.: hello_world-keypair.json): A chave pública deste keypair é usada como 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:

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

Exemplo de saída:

4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz

Testar o programa

Em seguida, teste o programa usando o crate solana-program-test. Adicione as seguintes dependências ao Cargo.toml.

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

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.

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());
}
}

Execute o teste usando o comando cargo test-sbf. O log do programa exibirá "Hello, world!".

Terminal
cargo test-sbf

Exemplo de saída:

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

Implantar o programa

Em seguida, implante o programa. Durante o desenvolvimento local, podemos usar o solana-test-validator.

Primeiro, configure a CLI da Solana para usar o cluster local da Solana.

Terminal
solana config set -ul

Exemplo de saída:

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

Abra um novo terminal e execute o comando solana-test-validators para iniciar o validator local.

Terminal
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.

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

Exemplo de saída:

Program Id: 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz
Signature:
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.

Invocar o programa

Em seguida, demonstraremos como invocar o programa usando um cliente Rust.

Primeiro crie um diretório examples e um arquivo client.rs.

Terminal
mkdir -p examples
touch examples/client.rs

Adicione o seguinte ao Cargo.toml.

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

Adicione a dependência solana-client.

Terminal
cargo add solana-client@1.18.26 --dev

Adicione o seguinte código ao examples/client.rs. Este é um script cliente em Rust que financia um novo keypair para pagar taxas de transação e depois invoca o programa hello world.

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),
}
}

Antes de executar o script, substitua o ID do programa no trecho de código acima pelo ID do seu programa.

Você pode obter o ID do seu programa executando o seguinte comando.

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();
}
}

Execute o script cliente com o seguinte comando.

Terminal
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 no mesmo ID de programa. Atualize o programa em src/lib.rs para imprimir "Hello, Solana!" em vez de "Hello, world!".

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

Teste o programa atualizado executando o comando cargo test-sbf.

Terminal
cargo test-sbf

Você deverá ver "Hello, Solana!" no log do programa.

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

Execute o comando cargo build-sbf para gerar um arquivo .so atualizado.

Terminal
cargo build-sbf

Reimplante o programa usando o comando solana program deploy.

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

Execute o código cliente novamente e inspecione a assinatura da transação no Solana Explorer para ver "Hello, Solana!" no log do programa.

Terminal
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, portanto, deve ser feito com cautela.

Para fechar um programa, use o comando solana program close <PROGRAM_ID>. Por exemplo:

Terminal
solana program close 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz
--bypass-warning

Exemplo de saída:

Closed Program Id 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz, 0.1350588 SOL
reclaimed

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, use
a new Program Id

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:

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

Alternativamente, você pode excluir o arquivo de keypair existente (por exemplo, ./target/deploy/hello_world-keypair.json) e executar cargo build-sbf novamente, que gerará um novo arquivo de keypair.

Is this page helpful?

Índice

Editar Página