
Como começar a desenvolver com o SDK Solana Web3.js 2.0
Antes de começarmos, queremos agradecer a Evan e Nick pela revisão deste artigo. Agradecemos muito pelo feedback valioso e pelas observações.
Introdução
O SDK Solana Web3.js é uma biblioteca avançada de TypeScript e JavaScript para desenvolver aplicações Solana nas plataformas Node.js, web e React Native. Em 7 de novembro de 2024, a Anza apresentou a aguardada atualização 2.0 do SDK, com diversos recursos e melhorias modernas de JavaScript. Entre os principais destaques estão os tipos JS padrão para bigints e criptografia, além da redução no tamanho dos bundles, tornando essa uma atualização significativa para desenvolvedores.
Se você usa @solana/web3.js, precisará migrar seu software para o novo pacote v2.0 ou especificar explicitamente a versão para mantê-lo na v1.x.
Neste artigo, exploraremos as atualizações mais recentes do SDK Web3.js 2.0, orientaremos você no processo de migração e apresentaremos um exemplo para ajudar você a começar.
Este artigo pressupõe um conhecimento sólido dos conceitos fundamentais da Solana, como o envio de transações, o modelo de contas da Solana, blockhashes e taxas de prioridade, além de experiência com TypeScript ou JavaScript. Embora seja recomendável conhecer a versão anterior do SDK Web3.js, isso não é obrigatório. Vamos começar!
O que há de novo no Web3.js 2.0?
Vamos conferir rapidamente o que o novo SDK Web3.js 2.0 oferece:
1. Melhorias de desempenho
Operações criptográficas mais rápidas: a geração de pares de chaves, a assinatura de transações e a verificação de mensagens são até 10 vezes mais rápidas graças ao uso de APIs de criptografia nativas em ambientes JavaScript modernos, como Node.js e navegadores atuais.
2. Aplicações menores e eficientes
O Web3.js 2.0 é totalmente compatível com tree shaking, permitindo incluir apenas as partes da biblioteca que você usa e minimizar o tamanho do bundle. Além disso, o novo SDK não possui dependências externas, garantindo um build leve e seguro.
3. Mais flexibilidade
Agora, os desenvolvedores podem criar soluções personalizadas ao:
- Definir instâncias de RPC com métodos personalizados
- Usar transportes de rede ou signatários de transações especializados
- Combinar primitivas personalizadas para rede, confirmações de transações e codecs
Os novos clientes TypeScript para programas on-chain agora estão hospedados na organização @solana-program no GitHub. Esses clientes são gerados automaticamente com o Codama, permitindo que os desenvolvedores gerem rapidamente clientes para programas personalizados.
Você já deve migrar para o Web3.js v2?
Em fevereiro de 2025:
- Se você estiver criando uma nova aplicação Solana em JS/TS e usando programas existentes, como o programa do sistema, o programa de tokens, o programa de tokens associados e outros programas comuns, já poderá usar o web3.js v2.
- Se você estiver criando aplicações on-chain personalizadas com Anchor, talvez seja melhor esperar — o Anchor ainda não oferece suporte nativo ao web3.js v2. Você pode aguardar uma atualização futura do Anchor. Como alternativa, use o Codama para criar um cliente TypeScript para suas aplicações on-chain, embora isso exija um pouco mais de trabalho.
Migração do web3.js versão 1
Se você já usou o web3.js v1, confira um breve resumo das principais diferenças:
Pares de chaves
Em todos os lugares em que você usaria Keypair, agora deve usar um KeyPairSigner. Keypair.generate() agora é generateKeyPairSigner(). Além disso, keypair agora é escrito como keyPair em todos os lugares, seguindo o camelCase comum de JS/TS.
As chaves secretas agora são chamadas de privateKey e podem ser acessadas em keyPairSigner.privateKey. Em geral, você usa KeyPairSigner no web3.js v2 sempre que uma secretKey era usada no web3.js v1.
Endereços/chaves públicas
Os locais que usavam uma PublicKey no web3.js v1 usam apenas um endereço no web3.js v2. Por exemplo, os KeyPairSigner têm uma propriedade keypairSigner.address, que é sua chave pública. Você pode transformar uma chave pública em formato de string em um endereço usando a função address.
Valores em SOL e tokens
Os valores usam o tipo BigInt nativo do JS. Portanto, você adicionaria n ao final dos números, escrevendo um 1n em vez de 1.
Fábricas
Muitos recursos são configuráveis. Portanto, em vez de ter uma implementação predefinida (por exemplo, doThing()), há uma fábrica (chamada doThingFactory()) que você pode usar para criar sua própria função doThing(). Por exemplo:
- Para enviar e confirmar transações, você executa
sendAndConfirmTransactionFactory()uma vez com suas opções preferidas e recebe uma funçãosendAndConfirmTransaction()personalizada. Depois, você pode usar suasendAndConfirmTransaction()sempre que precisar enviar e confirmar uma transação. - Para receber um airdrop na devnet ou localnet, você executa
airdropFactory()uma vez e recebe uma funçãoairdrop()personalizada, que pode usar sempre que quiser um airdrop.
Como enviar transações com o Web3.js 2.0
A Helius publicou recentemente o Kite, um framework TypeScript para web3.js v2, que inclui funções de chamada única para as tarefas mais comuns da Solana.
Criaremos um programa client-side usando o Web3.js 2.0 para transferir lamports para outra carteira. Esse programa demonstrará técnicas para aumentar as taxas de sucesso das transações e reduzir os tempos de confirmação.
Seguiremos estas práticas recomendadas para enviar transações:
- Buscar o blockhash mais recente com o nível de compromisso confirmed
- Definir as taxas de prioridade conforme recomendado pela Priority Fee API da Helius
- Otimizar as unidades de computação
- Enviar a transação com maxRetries definido como 0 e skipPreflight definido como true
Essa abordagem garante desempenho e confiabilidade ideais, mesmo durante um congestionamento da rede.
Pré-requisitos
- Instale o Node.js
- Uma IDE compatível (por exemplo, VS Code ou Cursor)
Instalação
Comece criando um projeto básico em Node.js para estruturar sua aplicação.
Execute o comando a seguir para criar um arquivo package.json que gerencie as dependências e os metadados do seu projeto:
npm init -yCrie um diretório src e, dentro dele, adicione um arquivo index.ts, onde ficará o código principal:
mkdir src
touch src/index.tsEm seguida, use npm para instalar as dependências necessárias para trabalhar com o SDK Web3.js 2.0 da Solana:
npm install @solana/web3.js@2 @solana-program/system @solana-program/compute-budget esrunConfira uma descrição de cada pacote:
@solana/web3.js: o SDK Solana Web3.js 2.0 é essencial para criar e gerenciar transações da Solana@solana-program/system: fornece acesso ao Programa do Sistema da Solana, permitindo operações como transferências de lamports@solana-program/compute-budget: usado para definir taxas de prioridade e otimizar unidades de computação para transaçõesesruné uma maneira simples de executar aplicações TypeScript pela linha de comando sem precisar de configurações ou funções wrapper.
Defina os endereços da transferência
Em index.ts, vamos definir os endereços de origem e destino para transferir lamports. Usaremos a função address() para gerar a chave pública de destino a partir da string fornecida.
Para a origem, derivaremos o KeyPair usando seu secretKey.
import { address, createKeyPairSignerFromBytes, getBase58Encoder } from "@solana/web3.js";
const destinationAddress = address("public-key-to-send-lamports-to");
const secretKey = "add-your-private-key";
const sourceKeypair = await createKeyPairSignerFromBytes(getBase58Encoder().encode(secretKey));
Configure as conexões RPC
Em seguida, podemos configurar as conexões RPC relevantes. A função createSolanaRpc estabelece a comunicação com o servidor RPC usando um transporte HTTP padrão, suficiente para a maioria dos casos de uso.
Da mesma forma, usamos createSolanaRpcSubscriptions para estabelecer uma conexão WebSocket. O rpc_url e o wss_url estão no painel da Helius — basta criar uma conta ou fazer login e acessar a seção “Endpoints”.
A função sendAndConfirmTransactionFactory cria um remetente de transações reutilizável. Esse remetente exige uma conexão RPC para enviar transações e uma assinatura RPC para monitorar o status delas.
import {
// ...
createSolanaRpcSubscriptions,
createSolanaRpc,
sendAndConfirmTransactionFactory,
} from "@solana/web3.js";
const rpc_url = "https://mainnet.helius-rpc.com/?api-key=<your-key>";
const wss_url = "wss://mainnet.helius-rpc.com/?api-key=<your-key>";
const rpc = createSolanaRpc(rpc_url);
const rpcSubscriptions = createSolanaRpcSubscriptions(wss_url);
const sendAndConfirmTransaction = sendAndConfirmTransactionFactory({
rpc,
rpcSubscriptions,
});Crie uma instrução de transferência
Incluir um blockhash recente evita duplicações e define a validade das transações — toda transação precisa incluir um blockhash válido para ser aceita para execução. Para esta transação, buscaremos o blockhash mais recente usando o nível de compromisso confirmed.
Em seguida, usaremos getTransferSolInstruction() para criar uma instrução de transferência predefinida fornecida pelo Programa do Sistema. Isso exige especificar o valor, a origem
, e o destino. A origem deve ser sempre um Signer, enquanto o destino deve ser um endereço público.
import {
// ...
lamports,
} from "@solana/web3.js";
import { getTransferSolInstruction } from "@solana-program/system";
/**
* STEP 1: CREATE THE TRANSFER TRANSACTION
*/
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
const instruction = getTransferSolInstruction({
amount: lamports(1n),
destination: destinationAddress,
source: sourceKeypair,
});
Crie a mensagem da transação
Em seguida, criaremos a mensagem da transação. Todas as mensagens de transação agora reconhecem a versão, eliminando a necessidade de lidar com tipos diferentes (por exemplo, Transaction em comparação com VersionedTransaction).
Definiremos a origem como pagadora da taxa, incluiremos o blockhash e adicionaremos a instrução para transferir lamports.
import {
// ...
pipe,
createTransactionMessage,
setTransactionMessageFeePayer,
setTransactionMessageLifetimeUsingBlockhash,
appendTransactionMessageInstruction,
} from "@solana/web3.js";
// ...
const transactionMessage = pipe(
createTransactionMessage({ version: 0 }),
(message) => setTransactionMessageFeePayer(sourceKeypair.address, message),
(message) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, message),
(message) => appendTransactionMessageInstruction(instruction, message),
);
console.log("Transaction message created");
A função pipe, muito usada em programação funcional, cria uma sequência de funções em que a saída de uma se torna a entrada da próxima. Aqui, ela cria uma mensagem de transação passo a passo, aplicando transformações como definir o pagador da taxa e a validade, além de adicionar instruções.
Inicialize a mensagem da transação:
createTransactionMessage({ version: 0 }) começa com uma mensagem de transação básica.
Defina o pagador da taxa:
message => setTransactionMessageFeePayer(fromKeypair.address, message) adiciona o endereço do pagador da taxa.
Defina a validade usando o blockhash
message => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, message) usa o blockhash mais recente para garantir que a transação seja válida dentro de um período.
Adicione a instrução de transferência
message => appendTransactionMessageInstruction(instruction, message) acrescenta a ação (por exemplo, transferir lamports) à mensagem.
Cada função de seta message => (...) modifica a mensagem e passa a versão atualizada para a próxima etapa, produzindo uma mensagem de transação nova e totalmente construída.
Assine a transação
Assinaremos a transação usando o signatário especificado, o Keypair de origem.
import {
// ...
signTransactionMessageWithSigners,
} from "@solana/web3.js";
// ...
/**
* STEP 2: SIGN THE TRANSACTION
*/
const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);
console.log("Transaction signed");
Estime as taxas de prioridade
Nesta etapa, podemos prosseguir com o envio e a confirmação da transação. No entanto, devemos otimizar a transação definindo taxas de prioridade e ajustando as unidades de computação. Essas otimizações ajudam a aumentar as taxas de sucesso das transações e reduzir os tempos de confirmação, especialmente durante congestionamentos da rede.
Para definir as taxas de prioridade, usaremos a Priority Fee API da Helius. Isso exige a transação serializada no formato Base64. Embora a API também ofereça suporte à codificação Base58, o SDK atual fornece a transação diretamente no formato Base64, simplificando o processo.
import {
// ...
getBase64EncodedWireTransaction,
} from "@solana/web3.js";
/**
* STEP 3: GET PRIORITY FEE FROM SIGNED TRANSACTION
*/
const base64EncodedWireTransaction = getBase64EncodedWireTransaction(signedTransaction);
const response = await fetch(rpc_url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0",
id: "helius-example",
method: "getPriorityFeeEstimate",
params: [
{
transaction: base64EncodedWireTransaction,
options: {
transactionEncoding: "base64",
priorityLevel: "High",
},
},
],
}),
});
const { result } = await response.json();
const priorityFee = result.priorityFeeEstimate;
console.log("Setting priority fee to ", priorityFee);
Definir priorityLevel como High geralmente é suficiente. No entanto, implementar estratégias avançadas de taxas de prioridade, como o uso de transações serializadas e chaves de contas, pode aumentar significativamente as taxas de sucesso das transações durante congestionamentos da rede.
Otimize as unidades de computação
Em seguida, estimaremos as unidades de computação que a mensagem da transação realmente consome.
Depois, adicionamos uma margem de 10% multiplicando esse valor por 1,1. Essa margem considera as unidades de computação usadas pelas taxas de prioridade e pelas instruções adicionais de unidades de computação, que incorporaremos posteriormente.
Algumas instruções, como a transferência de lamports, podem ter uma estimativa menor de unidades de computação. Para garantir recursos suficientes, adicionamos uma proteção que define um mínimo de 1.000 unidades de computação caso a estimativa fique abaixo desse limite.
import {
// ...
getComputeUnitEstimateForTransactionMessageFactory,
} from "@solana/web3.js";
/**
* STEP 4: OPTIMIZE COMPUTE UNITS
*/
const getComputeUnitEstimateForTransactionMessage = getComputeUnitEstimateForTransactionMessageFactory({
rpc,
});
// Request an estimate of the actual compute units this message will consume.
let computeUnitsEstimate = await getComputeUnitEstimateForTransactionMessage(transactionMessage);
computeUnitsEstimate = computeUnitsEstimate < 1000 ? 1000 : Math.ceil(computeUnitsEstimate * 1.1);
console.log("Setting compute units to ", computeUnitsEstimate);
Reconstrua e assine a transação
Agora temos as taxas de prioridade e as unidades de computação necessárias para esta transação. Como a transação já foi assinada, não podemos adicionar novas instruções diretamente. Em vez disso, reconstruiremos toda a mensagem da transação com um novo blockhash.
Os blockhashes só são válidos por cerca de 1 a 2 minutos, e a obtenção das taxas de prioridade e unidades de computação leva algum tempo. Para evitar o risco de o blockhash expirar durante o envio da transação, é mais seguro obter um novo ao reconstruí-la.
Nesta transação reconstruída, incluiremos duas instruções adicionais:
- Uma instrução para definir as taxas de prioridade; e
- Outra instrução para definir as unidades de computação
Por fim, assinaremos essa transação atualizada para prepará-la para o envio:
import {
// ...
appendTransactionMessageInstructions,
} from "@solana/web3.js";
import { getSetComputeUnitLimitInstruction, getSetComputeUnitPriceInstruction } from "@solana-program/compute-budget";
/**
* STEP 5: REBUILD AND SIGN FINAL TRANSACTION
*/
const { value: finalLatestBlockhash } = await rpc.getLatestBlockhash().send();
const finalTransactionMessage = appendTransactionMessageInstructions(
[
getSetComputeUnitPriceInstruction({ microLamports: priorityFee }),
getSetComputeUnitLimitInstruction({ units: computeUnitsEstimate }),
],
transactionMessage,
);
setTransactionMessageLifetimeUsingBlockhash(finalLatestBlockhash, finalTransactionMessage);
const finalSignedTransaction = await signTransactionMessageWithSigners(finalTransactionMessage);
console.log("Rebuilt the transaction and signed it");
Envie e confirme a transação
Em seguida, a transação assinada é enviada e confirmada usando a função sendAndConfirmTransaction.
O nível de compromisso é definido como confirmed, de modo consistente com o blockhash obtido anteriormente, enquanto maxRetries é definido como 0. A opção skipPreflight é definida como true, ignorando as verificações de preflight para acelerar a execução. No entanto, isso só deve ser usado quando você tiver certeza de que a assinatura da transação foi verificada e não há outros erros.
A sendAndConfirmTransaction foi criada anteriormente com as URLs de RPC e de assinatura RPC. O uso da URL de assinatura RPC verifica o status da transação, eliminando a necessidade de polling manual.
Na seção de tratamento de erros, o código verifica os erros ocorridos durante as verificações de preflight. Como definimos skipPreflight como true, essa verificação é redundante. No entanto, ela será útil se você não definir essa opção como true.
import {
getSignatureFromTransaction,
isSolanaError,
SOLANA_ERROR__JSON_RPC__SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE,
} from "@solana/web3.js";
import { getSystemErrorMessage, isSystemError } from "@solana-program/system";
/**
* STEP 6: SEND AND CONFIRM THE FINAL TRANSACTION
*/
console.log("Sending and confirming transaction");
await sendAndConfirmTransaction(finalSignedTransaction, {
commitment: "confirmed",
maxRetries: 0n,
skipPreflight: true,
});
console.log("Transfer confirmed: ", getSignatureFromTransaction(finalSignedTransaction));
Execute o código
Por fim, podemos executar o código:
npx esrun send-transaction.ts
Conclusão
O lançamento do SDK Web3.js 2.0 da Solana é uma atualização transformadora que permite aos desenvolvedores criar aplicações mais rápidas, eficientes e escaláveis na Solana. Ao adotar padrões modernos de JavaScript e introduzir recursos como APIs de criptografia nativas, compatibilidade com tree shaking e clientes TypeScript gerados automaticamente, o SDK melhora significativamente a experiência do desenvolvedor e o desempenho das aplicações.
O código completo do exemplo de programação está no GitHub.
Se você leu até aqui, valeu, anon! Insira seu endereço de e-mail abaixo para nunca perder uma atualização sobre as novidades da Solana. Quer se aprofundar? Confira os artigos mais recentes no blog da Helius e continue hoje mesmo sua jornada na Solana.
Recursos
Artigos relacionados
Assine a Helius
Acompanhe as novidades mais recentes do desenvolvimento Solana e receba atualizações quando publicarmos


